Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Newer ATI SB800 SMBus controllers don't report t...
details: https://anonhg.NetBSD.org/src/rev/50170280582f
branches: trunk
changeset: 770085:50170280582f
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sun Oct 02 23:25:20 2011 +0000
description:
Newer ATI SB800 SMBus controllers don't report the base address in PCI
config space. According to the SB800-Series Southbridges Register Reference
Guide, we can still read this value from PM config space using indirect I/O.
diffstat:
sys/dev/pci/piixpm.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 72 insertions(+), 2 deletions(-)
diffs (123 lines):
diff -r 8ec7f73a8e1e -r 50170280582f sys/dev/pci/piixpm.c
--- a/sys/dev/pci/piixpm.c Sun Oct 02 22:20:33 2011 +0000
+++ b/sys/dev/pci/piixpm.c Sun Oct 02 23:25:20 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpm.c,v 1.35 2011/02/13 11:20:12 hannken Exp $ */
+/* $NetBSD: piixpm.c,v 1.36 2011/10/02 23:25:20 jmcneill Exp $ */
/* $OpenBSD: piixpm.c,v 1.20 2006/02/27 08:25:02 grange Exp $ */
/*
@@ -22,7 +22,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.35 2011/02/13 11:20:12 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.36 2011/10/02 23:25:20 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -55,6 +55,17 @@
#define PIIXPM_DELAY 200
#define PIIXPM_TIMEOUT 1
+#define PIIXPM_INDIRECTIO_BASE 0xcd6
+#define PIIXPM_INDIRECTIO_SIZE 2
+#define PIIXPM_INDIRECTIO_INDEX 0
+#define PIIXPM_INDIRECTIO_DATA 1
+
+#define SB800_PM_SMBUS0EN_LO 0x2c
+#define SB800_PM_SMBUS0EN_HI 0x2d
+
+#define SB800_PM_SMBUS0EN_ENABLE 0x0001
+#define SB800_PM_SMBUS0EN_BADDR 0xffe0
+
struct piixpm_softc {
device_t sc_dev;
@@ -89,6 +100,8 @@
static bool piixpm_suspend(device_t, const pmf_qual_t *);
static bool piixpm_resume(device_t, const pmf_qual_t *);
+static int piixpm_sb800_init(struct piixpm_softc *,
+ struct pci_attach_args *);
static void piixpm_csb5_reset(void *);
static int piixpm_i2c_acquire_bus(void *, int);
static void piixpm_i2c_release_bus(void *, int);
@@ -195,6 +208,17 @@
(PCI_REVISION(pa->pa_class) < 3) ? ACPIPMT_BADLATCH : 0 );
nopowermanagement:
+
+ /* SB800 rev 0x40+ needs special initialization */
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB &&
+ PCI_REVISION(pa->pa_class) >= 0x40) {
+ if (piixpm_sb800_init(sc, pa) == 0)
+ goto attach_i2c;
+ aprint_normal_dev(self, "SMBus disabled\n");
+ return;
+ }
+
if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) {
aprint_normal_dev(self, "SMBus disabled\n");
return;
@@ -229,6 +253,7 @@
if (sc->sc_poll)
aprint_normal("polling");
+attach_i2c:
aprint_normal("\n");
/* Attach I2C bus */
@@ -272,6 +297,51 @@
return true;
}
+/*
+ * Extract SMBus base address from SB800 Power Management (PM) registers.
+ * The PM registers can be accessed either through indirect I/O (CD6/CD7) or
+ * direct mapping if AcpiMMioDecodeEn is enabled. Since this function is only
+ * called once it uses indirect I/O for simplicity.
+ */
+static int
+piixpm_sb800_init(struct piixpm_softc *sc, struct pci_attach_args *pa)
+{
+ bus_space_tag_t iot = pa->pa_iot;
+ bus_space_handle_t ioh; /* indirect I/O handle */
+ uint16_t val, base_addr;
+
+ /* Fetch SMB base address */
+ if (bus_space_map(iot,
+ PIIXPM_INDIRECTIO_BASE, PIIXPM_INDIRECTIO_SIZE, 0, &ioh)) {
+ device_printf(sc->sc_dev, "couldn't map indirect I/O space\n");
+ return EBUSY;
+ }
+ bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_INDEX,
+ SB800_PM_SMBUS0EN_LO);
+ val = bus_space_read_1(iot, ioh, PIIXPM_INDIRECTIO_DATA);
+ bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_INDEX,
+ SB800_PM_SMBUS0EN_HI);
+ val |= bus_space_read_1(iot, ioh, PIIXPM_INDIRECTIO_DATA) << 8;
+ bus_space_unmap(iot, ioh, 2);
+
+ if ((val & SB800_PM_SMBUS0EN_ENABLE) == 0)
+ return ENOENT;
+
+ base_addr = val & SB800_PM_SMBUS0EN_BADDR;
+
+ aprint_debug_dev(sc->sc_dev, "SMBus @ 0x%04x\n", base_addr);
+
+ sc->sc_smb_iot = iot;
+ if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base_addr),
+ PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
+ aprint_error_dev(sc->sc_dev, "can't map smbus I/O space\n");
+ return EBUSY;
+ }
+ sc->sc_poll = 1;
+
+ return 0;
+}
+
static void
piixpm_csb5_reset(void *arg)
{
Home |
Main Index |
Thread Index |
Old Index