On Tue, Jan 07, 2020 at 09:27:50AM +0100, Claudio Jeker wrote:
> In -current I added support for the additional I2C busses on piixpm(4)
> now I noticed that on my old AMD system the I2C bus seems to either
> connect all those 4 busses together (or there is a bug in the driver).

Looks like this is indeed a problem with the driver.

With the following diff I now get:
piixpm0 at pci0 dev 20 function 0 "ATI SBx00 SMBus" rev 0x41: polling
iic0 at piixpm0
sdtemp0 at iic0 addr 0x18: stts2002
sdtemp1 at iic0 addr 0x19: stts2002
sdtemp2 at iic0 addr 0x1a: stts2002
sdtemp3 at iic0 addr 0x1b: stts2002
spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM ECC PC3-10600 with thermal sensor
spdmem1 at iic0 addr 0x51: 4GB DDR3 SDRAM ECC PC3-10600 with thermal sensor
spdmem2 at iic0 addr 0x52: 4GB DDR3 SDRAM ECC PC3-10600 with thermal sensor
spdmem3 at iic0 addr 0x53: 4GB DDR3 SDRAM ECC PC3-10600 with thermal sensor
iic1 at piixpm0                                                                 
piixpm0: exec: op 1, addr 0x18, cmdlen 1, len 0, flags 0x08: timeout, status 0x1
<BUSY>
iic2 at piixpm0
iic3 at piixpm0

Not sure what is up with the timeout on iic @ addr 0x18. If that is seen
on more systems it may be better to only use the primary bus on SB800
devices that don't support SB800_PMREG_SMB0SEL.

Please test and report back.
-- 
:wq Claudio

Index: piixpm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/piixpm.c,v
retrieving revision 1.40
diff -u -p -r1.40 piixpm.c
--- piixpm.c    16 Dec 2019 21:39:40 -0000      1.40
+++ piixpm.c    7 Jan 2020 11:19:09 -0000
@@ -60,6 +60,7 @@ struct piixpm_softc {
        int                     sc_poll;
        int                     sc_is_sb800;
        int                     sc_is_fch;
+       int                     sc_sb800_selen;
 
        struct piixpm_smbus     sc_busses[4];
        struct i2c_controller   sc_i2c_tag[4];
@@ -181,6 +182,12 @@ piixpm_attach(struct device *parent, str
                        val |= (bus_space_read_1(sc->sc_iot, ioh, 1) << 8);
                        smb0en = val & SB800_SMB0EN_EN;
                        base = val & SB800_SMB0EN_BASE_MASK;
+
+                       bus_space_write_1(sc->sc_iot, ioh, 0,
+                           SB800_PMREG_SMB0SELEN);
+                       val = bus_space_read_1(sc->sc_iot, ioh, 1);
+                       if (val & SB800_SMB0SELEN_EN)
+                               sc->sc_sb800_selen = 1;
                }
 
                if (smb0en == 0) {
@@ -296,11 +303,20 @@ piixpm_i2c_acquire_bus(void *cookie, int
                    AMDFCH41_PM_PORT_INDEX);
                bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 1,
                    smbus->sb_bus << 3);
-       } else if (sc->sc_is_sb800) {
+       } else if (sc->sc_is_sb800 && sc->sc_sb800_selen) {
                bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 0,
                    SB800_PMREG_SMB0SEL);
                bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 1,
                    smbus->sb_bus << 1);
+       } else if (sc->sc_is_sb800) {
+               uint8_t val;
+
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 0,
+                   SB800_PMREG_SMB0EN);
+               val = bus_space_read_1(sc->sc_iot, sc->sc_sb800_ioh, 1) &
+                   ~SB800_SMB0EN_PORT_MASK;
+               val |= smbus->sb_bus << 1;
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 1, val);
        }
 
        return (0);
@@ -317,11 +333,20 @@ piixpm_i2c_release_bus(void *cookie, int
                    AMDFCH41_PM_PORT_INDEX);
                bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 1,
                    0);
-       } else if (sc->sc_is_sb800) {
+       } else if (sc->sc_is_sb800 && sc->sc_sb800_selen) {
                bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 0,
                    SB800_PMREG_SMB0SEL);
                bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 1,
                    0);
+       } else if (sc->sc_is_sb800) {
+               uint8_t val;
+
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 0,
+                   SB800_PMREG_SMB0EN);
+               val = bus_space_read_1(sc->sc_iot, sc->sc_sb800_ioh, 1) &
+                   ~SB800_SMB0EN_PORT_MASK;
+               val |= 0;
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh, 1, val);
        }
 
        if (cold || sc->sc_poll || (flags & I2C_F_POLL))
Index: piixreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/piixreg.h,v
retrieving revision 1.5
diff -u -p -r1.5 piixreg.h
--- piixreg.h   16 Dec 2019 21:39:40 -0000      1.5
+++ piixreg.h   7 Jan 2020 11:12:29 -0000
@@ -70,8 +70,11 @@
 #define SB800_PMREG_SIZE       2       /* index/data pair */
 #define SB800_PMREG_SMB0EN     0x2c    /* 16-bit register */
 #define SB800_PMREG_SMB0SEL    0x2e    /* bus selection */
+#define SB800_PMREG_SMB0SELEN  0x2f    /* bus selection enable */
 #define SB800_SMB0EN_EN                0x0001
 #define SB800_SMB0EN_BASE_MASK 0xffe0
+#define SB800_SMB0EN_PORT_MASK 0x06
+#define SB800_SMB0SELEN_EN     0x01
 
 #define SB800_SMB_HOSTC        0x10            /* I2C bus configuration */
 #define SB800_SMB_HOSTC_SMI    (1 << 0)        /* SMI */

Reply via email to