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
..

-Bryan.

Index: piixpm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/piixpm.c,v
retrieving revision 1.35
diff -u -r1.35 piixpm.c
--- piixpm.c    9 Apr 2011 04:33:40 -0000       1.35
+++ piixpm.c    19 May 2011 22:57:59 -0000
@@ -114,50 +114,102 @@
 {
        struct piixpm_softc *sc = (struct piixpm_softc *)self;
        struct pci_attach_args *pa = aux;
-       struct i2cbus_attach_args iba;
-       pcireg_t base, conf;
+       pcireg_t conf;
+       bus_space_handle_t pm_ioh;
+       u_int8_t smben_reg[2];
+       bus_addr_t base;
        pci_intr_handle_t ih;
        const char *intrstr = NULL;
+       struct i2cbus_attach_args iba;
+
+       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) {
+               /* 
+                * AMD SB800+
+                * Power management reg: PMREG_BASE(index)/PMREG_BASE+1(data).
+                * SMB base addr + EN-bit: PMREG_BASE+SMB0EN(16), I/O mapped.
+                */
+               /* This could be mapped already, failure the only option? */
+               if (bus_space_map(sc->sc_iot, SB800_PMREG_BASE,
+                   SB800_PMREG_SIZE, 0, &pm_ioh) != 0) {
+                       printf(": can't map i/o space\n");
+                       return;
+               }
+
+               /* Read "SmBus0En" byte 1 */
+               bus_space_write_1(sc->sc_iot, pm_ioh, 0, SB800_PMREG_SMB0EN);
+               smben_reg[0] = bus_space_read_1(sc->sc_iot, pm_ioh, 1);
+               if ((smben_reg[0] & SB800_SMB_EN) == 0) {
+                       bus_space_unmap(sc->sc_iot, pm_ioh, SB800_PMREG_SIZE);
+                       printf(": SMBus disabled\n");
+                       return;
+               }
+               /* Read "SmBus0En" byte 2 */
+               bus_space_write_1(sc->sc_iot, pm_ioh, 0, SB800_PMREG_SMB0EN2);
+               smben_reg[1] = bus_space_read_1(sc->sc_iot, pm_ioh, 1);
+
+               /* XXX: PM_Reg may be required by other devices. */
+               bus_space_unmap(sc->sc_iot, pm_ioh, SB800_PMREG_SIZE);
 
-       /* 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;
-       }
-
-       sc->sc_poll = 1;
-       if ((conf & PIIX_SMB_HOSTC_INTMASK) == PIIX_SMB_HOSTC_SMI) {
-               /* No PCI IRQ */
+               /* Construct the base address. */
+               base = ((smben_reg[1] << SB800_SMB_BASE_SHIFT) | smben_reg[0]) &
+                   SB800_SMB_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;
+               }
+
+               /* XXX: IRQ.. */
                printf(": SMI");
+               sc->sc_poll = 1;
        } else {
-               if ((conf & PIIX_SMB_HOSTC_INTMASK) == PIIX_SMB_HOSTC_IRQ) {
+               /* 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;
+               }
+
+               sc->sc_poll = 1;
+               switch ((conf & PIIX_SMB_HOSTC_INTMASK)) {
+                       /* No PCI IRQ */
+                       case PIIX_SMB_HOSTC_SMI:
+                               printf(": SMI");
+                               break;
                        /* Install interrupt handler */
-                       if (pci_intr_map(pa, &ih) == 0) {
-                               intrstr = pci_intr_string(pa->pa_pc, ih);
-                               sc->sc_ih = pci_intr_establish(pa->pa_pc,
-                                   ih, IPL_BIO, piixpm_intr, sc,
-                                   sc->sc_dev.dv_xname);
-                               if (sc->sc_ih != NULL) {
-                                       printf(": %s", intrstr);
-                                       sc->sc_poll = 0;
+                       case PIIX_SMB_HOSTC_IRQ:
+                               if (pci_intr_map(pa, &ih) == 0) {
+                                       intrstr = pci_intr_string(pa->pa_pc,
+                                           ih);
+                                       sc->sc_ih = pci_intr_establish(
+                                           pa->pa_pc, ih,
+                                           IPL_BIO, piixpm_intr, sc,
+                                           sc->sc_dev.dv_xname);
+                                       if (sc->sc_ih != NULL) {
+                                               printf(": %s", intrstr);
+                                               sc->sc_poll = 0;
+                                               break;
+                                       }
                                }
-                       }
+                       /* Try polling.. */
+                       default:
+                               printf(": polling");
                }
-               if (sc->sc_poll)
-                       printf(": polling");
        }
 
        printf("\n");
Index: piixreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/piixreg.h,v
retrieving revision 1.3
diff -u -r1.3 piixreg.h
--- piixreg.h   3 Jan 2006 22:39:03 -0000       1.3
+++ piixreg.h   19 May 2011 22:57:59 -0000
@@ -27,6 +27,16 @@
  * Power management registers.
  */
 
+/* AMD SB800+ configuration registers */
+#define SB800_PMREG_BASE       0xcd6
+#define SB800_PMREG_SIZE       2       /* PMREG(index), PMREG+1(data) */
+#define SB800_PMREG_SMB0EN     0x2c    /* 16-bit register, byte addressed */
+#define SB800_PMREG_SMB0EN2    SB800_PMREG_SMB0EN + 1
+#define SB800_SMB_EN           0x01
+#define SB800_SMB_BASE_SHIFT   8
+#define SB800_SMB_BASE_MASK    0xffe0
+#define SB800_SMB_SIZE         PIIX_SMB_SIZE
+
 /* PCI configuration registers */
 #define PIIX_SMB_BASE  0x90            /* SMBus base address */
 #define PIIX_SMB_HOSTC 0xd0            /* SMBus host configuration */

Reply via email to