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