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 */