> Date: Thu, 19 May 2011 19:09:36 -0400
> From: Brynet <bry...@gmail.com>
> 
> Here it is a again with the magic relocated to piixreg.h.
> 
> To clarify, if you have:
> piixpm0 at pci0 dev 20 function 0 "ATI SBx00 SMBus"
> 
> Then check if the revision is >= 0x40, which is the relevant southbridge.
> 
> If it works, you'll see pretty stuff like this::
> spdmem0 at iic addr 0x50: 2GB DDR3 SDRAM PC3-10600 SO-DIMM
> ..

Had a look at the chipset docs, and it took me some time to figure out
how AMD had hidden these registers away.  So I wrote a somewhat less cryptic 
comment that explains the code a bit better.  I also noticed that there is
a register that indicates whether SMI is enabled or not.

So here's a cleaned up diff.  Does this still work for you?


Index: piixpm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/piixpm.c,v
retrieving revision 1.35
diff -u -p -r1.35 piixpm.c
--- piixpm.c    9 Apr 2011 04:33:40 -0000       1.35
+++ piixpm.c    21 May 2011 20:29:19 -0000
@@ -114,28 +114,80 @@ piixpm_attach(struct device *parent, str
 {
        struct piixpm_softc *sc = (struct piixpm_softc *)self;
        struct pci_attach_args *pa = aux;
-       struct i2cbus_attach_args iba;
-       pcireg_t base, conf;
+       bus_space_handle_t ioh;
+       u_int16_t smb0en;
+       bus_addr_t base;
+       pcireg_t conf;
        pci_intr_handle_t ih;
        const char *intrstr = NULL;
+       struct i2cbus_attach_args iba;
 
-       /* Read configuration */
-       conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC);
-       DPRINTF((": conf 0x%08x", conf));
-
-       if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) {
-               printf(": SMBus disabled\n");
-               return;
-       }
-
-       /* Map I/O space */
        sc->sc_iot = pa->pa_iot;
-       base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff;
-       if (PCI_MAPREG_IO_ADDR(base) == 0 ||
-           bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(base),
-           PIIX_SMB_SIZE, 0, &sc->sc_ioh)) {
-               printf(": can't map i/o space\n");
-               return;
+
+       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
+           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SBX00_SMB &&
+           PCI_REVISION(pa->pa_class) >= 0x40) {
+               /* 
+                * On the AMD SB800, the SMBus I/O registers are well
+                * hidden.  We need to look at the "SMBus0En" Power
+                * Management register to find out where they live.
+                * We use indirect IO access through the index/data
+                * pair at 0xcd6/0xcd7 to access "SMBus0En".  Since
+                * the index/data pair may be needed by other drivers,
+                * we only map them for the duration that we actually
+                * need them.
+                */
+               if (bus_space_map(sc->sc_iot, SB800_PMREG_BASE,
+                   SB800_PMREG_SIZE, 0, &ioh) != 0) {
+                       printf(": can't map i/o space\n");
+                       return;
+               }
+
+               /* Read "SmBus0En" */
+               bus_space_write_1(sc->sc_iot, ioh, 0, SB800_PMREG_SMB0EN);
+               smb0en = bus_space_read_1(sc->sc_iot, ioh, 1);
+               bus_space_write_1(sc->sc_iot, ioh, 0, SB800_PMREG_SMB0EN + 1);
+               smb0en |= (bus_space_read_1(sc->sc_iot, ioh, 1) << 8);
+
+               bus_space_unmap(sc->sc_iot, ioh, SB800_PMREG_SIZE);
+
+               if ((smb0en & SB800_SMB0EN_EN) == 0) {
+                       printf(": SMBus disabled\n");
+                       return;
+               }
+
+               /* Map I/O space */
+               base = smb0en & SB800_SMB0EN_BASE_MASK;
+               if (base == 0 || bus_space_map(sc->sc_iot, base,
+                   SB800_SMB_SIZE, 0, &sc->sc_ioh)) {
+                       printf(": can't map i/o space");
+                       return;
+               }
+
+               /* Read configuration */
+               conf = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 
SB800_SMB_HOSTC);
+               if (conf & SB800_SMB_HOSTC_SMI)
+                       conf = PIIX_SMB_HOSTC_SMI;
+               else
+                       conf = PIIX_SMB_HOSTC_IRQ;
+       } else {
+               /* Read configuration */
+               conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC);
+               DPRINTF((": conf 0x%08x", conf));
+
+               if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) {
+                       printf(": SMBus disabled\n");
+                       return;
+               }
+
+               /* Map I/O space */
+               base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) &
+                   PIIX_SMB_BASE_MASK;
+               if (base == 0 || bus_space_map(sc->sc_iot, base,
+                   PIIX_SMB_SIZE, 0, &sc->sc_ioh)) {
+                       printf(": can't map i/o space\n");
+                       return;
+               }
        }
 
        sc->sc_poll = 1;
Index: piixreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/piixreg.h,v
retrieving revision 1.3
diff -u -p -r1.3 piixreg.h
--- piixreg.h   3 Jan 2006 22:39:03 -0000       1.3
+++ piixreg.h   21 May 2011 20:29:19 -0000
@@ -29,6 +29,7 @@
 
 /* PCI configuration registers */
 #define PIIX_SMB_BASE  0x90            /* SMBus base address */
+#define PIIX_SMB_BASE_MASK     0xfffe
 #define PIIX_SMB_HOSTC 0xd0            /* SMBus host configuration */
 #define PIIX_SMB_HOSTC_HSTEN   (1 << 16)       /* enable host controller */
 #define PIIX_SMB_HOSTC_SMI     (0 << 17)       /* SMI */
@@ -63,5 +64,17 @@
 #define PIIX_SMB_SC_ALERTEN    (1 << 3)        /* enable SMBALERT# */
 
 #define PIIX_SMB_SIZE  0x10            /* SMBus I/O space size */
+
+/* AMD SB800 configuration registers */
+#define SB800_PMREG_BASE       0xcd6
+#define SB800_PMREG_SIZE       2       /* index/data pair */
+#define SB800_PMREG_SMB0EN     0x2c    /* 16-bit register */
+#define SB800_SMB0EN_EN                0x0001
+#define SB800_SMB0EN_BASE_MASK 0xffe0
+
+#define SB800_SMB_HOSTC        0x10            /* I2C bus configuration */
+#define SB800_SMB_HOSTC_SMI    (1 << 0)        /* SMI */
+
+#define SB800_SMB_SIZE 0x14            /* SMBus I/O space size */
 
 #endif /* !_DEV_PCI_PIIXREG_H_ */

Reply via email to