Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci The SB800 SMBus controller has four selectable S...



details:   https://anonhg.NetBSD.org/src/rev/94ad6c8e6f42
branches:  trunk
changeset: 788825:94ad6c8e6f42
user:      soren <soren%NetBSD.org@localhost>
date:      Mon Jul 22 13:27:14 2013 +0000

description:
The SB800 SMBus controller has four selectable SDA lines.
Expose them as four iic busses.

diffstat:

 sys/dev/pci/piixpm.c    |  121 +++++++++++++++++++++++++++++------------------
 sys/dev/pci/piixpmreg.h |   15 +++++-
 2 files changed, 88 insertions(+), 48 deletions(-)

diffs (297 lines):

diff -r 15ff735177ac -r 94ad6c8e6f42 sys/dev/pci/piixpm.c
--- a/sys/dev/pci/piixpm.c      Mon Jul 22 12:36:56 2013 +0000
+++ b/sys/dev/pci/piixpm.c      Mon Jul 22 13:27:14 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpm.c,v 1.41 2013/07/18 22:14:54 soren Exp $ */
+/* $NetBSD: piixpm.c,v 1.42 2013/07/22 13:27:14 soren 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.41 2013/07/18 22:14:54 soren Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.42 2013/07/22 13:27:14 soren Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -55,40 +55,37 @@
 #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_smbus {
+       int                     sda;
+       struct                  piixpm_softc *softc;
+};
 
 struct piixpm_softc {
        device_t                sc_dev;
 
-       bus_space_tag_t         sc_smb_iot;
+       bus_space_tag_t         sc_iot;
+#define        sc_pm_iot sc_iot
+#define sc_smb_iot sc_iot
+       bus_space_handle_t      sc_pm_ioh;
+       bus_space_handle_t      sc_sb800_ioh;
        bus_space_handle_t      sc_smb_ioh;
        void *                  sc_smb_ih;
        int                     sc_poll;
 
-       bus_space_tag_t         sc_pm_iot;
-       bus_space_handle_t      sc_pm_ioh;
-
        pci_chipset_tag_t       sc_pc;
        pcitag_t                sc_pcitag;
        pcireg_t                sc_id;
 
-       struct i2c_controller   sc_i2c_tag;
+       struct piixpm_smbus     sc_busses[4];
+       struct i2c_controller   sc_i2c_tags[4];
+
        kmutex_t                sc_i2c_mutex;
        struct {
-               i2c_op_t     op;
-               void *      buf;
-               size_t       len;
-               int          flags;
-               volatile int error;
+               i2c_op_t        op;
+               void *          buf;
+               size_t          len;
+               int             flags;
+               volatile int    error;
        }                       sc_i2c_xfer;
 
        pcireg_t                sc_devact[2];
@@ -100,8 +97,7 @@
 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 int     piixpm_sb800_init(struct piixpm_softc *);
 static void    piixpm_csb5_reset(void *);
 static int     piixpm_i2c_acquire_bus(void *, int);
 static void    piixpm_i2c_release_bus(void *, int);
@@ -159,8 +155,10 @@
        pcireg_t pmmisc;
        pci_intr_handle_t ih;
        const char *intrstr = NULL;
+       int i, numbusses = 1;
 
        sc->sc_dev = self;
+       sc->sc_iot = pa->pa_iot;
        sc->sc_id = pa->pa_id;
        sc->sc_pc = pa->pa_pc;
        sc->sc_pcitag = pa->pa_tag;
@@ -183,7 +181,6 @@
        if (!(pmmisc & 1))
                goto nopowermanagement;
 
-       sc->sc_pm_iot = pa->pa_iot;
        /* Map I/O space */
        base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PM_BASE);
        if (bus_space_map(sc->sc_pm_iot, PCI_MAPREG_IO_ADDR(base),
@@ -207,8 +204,10 @@
        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)
+               if (piixpm_sb800_init(sc) == 0) {
+                       numbusses = 4;
                        goto attach_i2c;
+               }
                aprint_normal_dev(self, "SMBus disabled\n");
                return;
        }
@@ -219,7 +218,6 @@
        }
 
        /* Map I/O space */
-       sc->sc_smb_iot = pa->pa_iot;
        base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff;
        if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base),
            PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) {
@@ -252,17 +250,20 @@
 attach_i2c:
        /* Attach I2C bus */
        mutex_init(&sc->sc_i2c_mutex, MUTEX_DEFAULT, IPL_NONE);
-       sc->sc_i2c_tag.ic_cookie = sc;
-       sc->sc_i2c_tag.ic_acquire_bus = piixpm_i2c_acquire_bus;
-       sc->sc_i2c_tag.ic_release_bus = piixpm_i2c_release_bus;
-       sc->sc_i2c_tag.ic_exec = piixpm_i2c_exec;
 
-       memset(&iba, 0, sizeof(iba));
-       iba.iba_type = I2C_TYPE_SMBUS;
-       iba.iba_tag = &sc->sc_i2c_tag;
-       config_found_ia(self, "i2cbus", &iba, iicbus_print);
+       for (i = 0; i < numbusses; i++) {
+               sc->sc_busses[i].sda = i;
+               sc->sc_busses[i].softc = sc;
+               sc->sc_i2c_tags[i].ic_cookie = &sc->sc_busses[i];
+               sc->sc_i2c_tags[i].ic_acquire_bus = piixpm_i2c_acquire_bus;
+               sc->sc_i2c_tags[i].ic_release_bus = piixpm_i2c_release_bus;
+               sc->sc_i2c_tags[i].ic_exec = piixpm_i2c_exec;
 
-       return;
+               memset(&iba, 0, sizeof(iba));
+               iba.iba_type = I2C_TYPE_SMBUS;
+               iba.iba_tag = &sc->sc_i2c_tags[i];
+               config_found_ia(self, "i2cbus", &iba, iicbus_print);
+       }
 }
 
 static bool
@@ -298,9 +299,9 @@
  * called once it uses indirect I/O for simplicity.
  */
 static int
-piixpm_sb800_init(struct piixpm_softc *sc, struct pci_attach_args *pa)
+piixpm_sb800_init(struct piixpm_softc *sc)
 {
-       bus_space_tag_t iot = pa->pa_iot;
+       bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh; /* indirect I/O handle */
        uint16_t val, base_addr;
 
@@ -316,7 +317,7 @@
        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);
+       sc->sc_sb800_ioh = ioh;
 
        if ((val & SB800_PM_SMBUS0EN_ENABLE) == 0)
                return ENOENT;
@@ -325,8 +326,10 @@
 
        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),
+       bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_INDEX, SB800_PM_SMBUS0SELEN);
+       bus_space_write_1(iot, ioh, PIIXPM_INDIRECTIO_DATA, 1); /* SMBUS0SEL */
+
+       if (bus_space_map(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;
@@ -361,18 +364,40 @@
 static int
 piixpm_i2c_acquire_bus(void *cookie, int flags)
 {
-       struct piixpm_softc *sc = cookie;
+       struct piixpm_smbus *smbus = cookie;
+       struct piixpm_softc *sc = smbus->softc;
 
        if (!cold)
                mutex_enter(&sc->sc_i2c_mutex);
 
+       if (smbus->sda > 0)     /* SB800 */
+       {
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+                   PIIXPM_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL);
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+                   PIIXPM_INDIRECTIO_DATA, smbus->sda << 1);
+       }
+
        return 0;
 }
 
 static void
 piixpm_i2c_release_bus(void *cookie, int flags)
 {
-       struct piixpm_softc *sc = cookie;
+       struct piixpm_smbus *smbus = cookie;
+       struct piixpm_softc *sc = smbus->softc;
+
+       if (smbus->sda > 0)     /* SB800 */
+       {
+               /*
+                * HP Microserver hangs after reboot if not set to SDA0.
+                * Also add shutdown hook?
+                */
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+                   PIIXPM_INDIRECTIO_INDEX, SB800_PM_SMBUS0SEL);
+               bus_space_write_1(sc->sc_iot, sc->sc_sb800_ioh,
+                   PIIXPM_INDIRECTIO_DATA, 0);
+       }
 
        if (!cold)
                mutex_exit(&sc->sc_i2c_mutex);
@@ -382,7 +407,8 @@
 piixpm_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
 {
-       struct piixpm_softc *sc = cookie;
+       struct piixpm_smbus *smbus = cookie;
+       struct piixpm_softc *sc = smbus->softc;
        const u_int8_t *b;
        u_int8_t ctl = 0, st;
        int retries;
@@ -394,7 +420,7 @@
        bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, 
            PIIX_SMB_HS_INTR | PIIX_SMB_HS_DEVERR | 
            PIIX_SMB_HS_BUSERR | PIIX_SMB_HS_FAILED);
-        bus_space_barrier(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, 1,
+       bus_space_barrier(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, 1,
            BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
 
        /* Wait for bus to be idle */
@@ -481,7 +507,7 @@
                }
                if (st & PIIX_SMB_HS_BUSY)
                        goto timeout;
-               piixpm_intr(sc);
+               piixpm_intr(smbus);
        } else {
                /* Wait for interrupt */
                if (tsleep(sc, PRIBIO, "iicexec", PIIXPM_TIMEOUT * hz))
@@ -516,7 +542,8 @@
 static int
 piixpm_intr(void *arg)
 {
-       struct piixpm_softc *sc = arg;
+       struct piixpm_smbus *smbus = arg;
+       struct piixpm_softc *sc = smbus->softc;
        u_int8_t st;
        u_int8_t *b;
        size_t len;
diff -r 15ff735177ac -r 94ad6c8e6f42 sys/dev/pci/piixpmreg.h
--- a/sys/dev/pci/piixpmreg.h   Mon Jul 22 12:36:56 2013 +0000
+++ b/sys/dev/pci/piixpmreg.h   Mon Jul 22 13:27:14 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpmreg.h,v 1.5 2011/02/13 11:20:12 hannken Exp $ */
+/* $NetBSD: piixpmreg.h,v 1.6 2013/07/22 13:27:14 soren Exp $ */
 /*     $OpenBSD: piixreg.h,v 1.3 2006/01/03 22:39:03 grange Exp $      */
 
 /*
@@ -75,4 +75,17 @@
 #define PIIX_PM_SIZE   0x38            /* Power management I/O space size */
 #define PIIX_SMB_SIZE  0x10            /* SMBus I/O space size */
 
+#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_SMBUS0SEL     0x2e 
+#define SB800_PM_SMBUS0SELEN   0x2f 
+                                      
+#define SB800_PM_SMBUS0EN_ENABLE 0x0001
+#define SB800_PM_SMBUS0EN_BADDR        0xffe0
+
 #endif /* !_DEV_PCI_PIIXREG_H_ */



Home | Main Index | Thread Index | Old Index