Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Teach a couple of i2cbus controllers how to resc...



details:   https://anonhg.NetBSD.org/src/rev/dcecd5d22bda
branches:  trunk
changeset: 337929:dcecd5d22bda
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Sun May 03 22:51:11 2015 +0000

description:
Teach a couple of i2cbus controllers how to rescan.  This enables
{,un}loading and {at,de}taching of the iic(4) driver/module at a
later time. Tested piixpm on QEMU, and ichsmb on my live server.

diffstat:

 sys/dev/pci/ichsmb.c |  48 ++++++++++++++++++++++++++++++++++------
 sys/dev/pci/piixpm.c |  60 +++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 90 insertions(+), 18 deletions(-)

diffs (249 lines):

diff -r f4f7d15181c2 -r dcecd5d22bda sys/dev/pci/ichsmb.c
--- a/sys/dev/pci/ichsmb.c      Sun May 03 22:40:02 2015 +0000
+++ b/sys/dev/pci/ichsmb.c      Sun May 03 22:51:11 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ichsmb.c,v 1.41 2015/04/02 15:32:19 tnn Exp $  */
+/*     $NetBSD: ichsmb.c,v 1.42 2015/05/03 22:51:11 pgoyette Exp $     */
 /*     $OpenBSD: ichiic.c,v 1.18 2007/05/03 09:36:26 dlg Exp $ */
 
 /*
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.41 2015/04/02 15:32:19 tnn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.42 2015/05/03 22:51:11 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -67,10 +67,13 @@
                int          flags;
                volatile int error;
        }                       sc_i2c_xfer;
+       device_t                sc_i2c_device;
 };
 
 static int     ichsmb_match(device_t, cfdata_t, void *);
 static void    ichsmb_attach(device_t, device_t, void *);
+static int     ichsmb_rescan(device_t, const char *, const int *);
+static void    ichsmb_chdet(device_t, device_t);
 
 static int     ichsmb_i2c_acquire_bus(void *, int);
 static void    ichsmb_i2c_release_bus(void *, int);
@@ -80,8 +83,8 @@
 static int     ichsmb_intr(void *);
 
 
-CFATTACH_DECL_NEW(ichsmb, sizeof(struct ichsmb_softc),
-    ichsmb_match, ichsmb_attach, NULL, NULL);
+CFATTACH_DECL3_NEW(ichsmb, sizeof(struct ichsmb_softc),
+    ichsmb_match, ichsmb_attach, NULL, NULL, ichsmb_rescan, ichsmb_chdet, 0);
 
 
 static int
@@ -134,12 +137,12 @@
 {
        struct ichsmb_softc *sc = device_private(self);
        struct pci_attach_args *pa = aux;
-       struct i2cbus_attach_args iba;
        pcireg_t conf;
        bus_size_t iosize;
        pci_intr_handle_t ih;
        const char *intrstr = NULL;
        char intrbuf[PCI_INTRSTR_LEN];
+       int flags;
 
        sc->sc_dev = self;
 
@@ -181,6 +184,26 @@
                        aprint_normal_dev(self, "polling\n");
        }
 
+       sc->sc_i2c_device = NULL;
+       flags = 0;
+       ichsmb_rescan(self, "i2cbus", &flags);
+
+out:   if (!pmf_device_register(self, NULL, NULL))
+               aprint_error_dev(self, "couldn't establish power handler\n");
+}
+
+static int
+ichsmb_rescan(device_t self, const char *ifattr, const int *flags)
+{
+       struct ichsmb_softc *sc = device_private(self);
+       struct i2cbus_attach_args iba;
+
+       if (!ifattr_match(ifattr, "i2cbus"))
+               return 0;
+
+       if (sc->sc_i2c_device)
+               return 0;
+
        /* Attach I2C bus */
        mutex_init(&sc->sc_i2c_mutex, MUTEX_DEFAULT, IPL_NONE);
        sc->sc_i2c_tag.ic_cookie = sc;
@@ -191,10 +214,19 @@
        memset(&iba, 0, sizeof(iba));
        iba.iba_type = I2C_TYPE_SMBUS;
        iba.iba_tag = &sc->sc_i2c_tag;
-       config_found(self, &iba, iicbus_print);
+       sc->sc_i2c_device = config_found_ia(self, ifattr, &iba, iicbus_print);
+
+       return 0;
+}
 
-out:   if (!pmf_device_register(self, NULL, NULL))
-               aprint_error_dev(self, "couldn't establish power handler\n");
+static void
+ichsmb_chdet(device_t self, device_t child)
+{
+       struct ichsmb_softc *sc = device_private(self);
+
+       if (sc->sc_i2c_device == child)
+               sc->sc_i2c_device = NULL;
+
 }
 
 static int
diff -r f4f7d15181c2 -r dcecd5d22bda sys/dev/pci/piixpm.c
--- a/sys/dev/pci/piixpm.c      Sun May 03 22:40:02 2015 +0000
+++ b/sys/dev/pci/piixpm.c      Sun May 03 22:51:11 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: piixpm.c,v 1.45 2014/06/22 09:48:20 hannken Exp $ */
+/* $NetBSD: piixpm.c,v 1.46 2015/05/03 22:51:11 pgoyette 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.45 2014/06/22 09:48:20 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: piixpm.c,v 1.46 2015/05/03 22:51:11 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -76,6 +76,8 @@
        pcitag_t                sc_pcitag;
        pcireg_t                sc_id;
 
+       int                     sc_numbusses;
+       device_t                sc_i2c_device[4];
        struct piixpm_smbus     sc_busses[4];
        struct i2c_controller   sc_i2c_tags[4];
 
@@ -93,6 +95,8 @@
 
 static int     piixpm_match(device_t, cfdata_t, void *);
 static void    piixpm_attach(device_t, device_t, void *);
+static int     piixpm_rescan(device_t, const char *, const int *);
+static void    piixpm_chdet(device_t, device_t);
 
 static bool    piixpm_suspend(device_t, const pmf_qual_t *);
 static bool    piixpm_resume(device_t, const pmf_qual_t *);
@@ -106,8 +110,8 @@
 
 static int     piixpm_intr(void *);
 
-CFATTACH_DECL_NEW(piixpm, sizeof(struct piixpm_softc),
-    piixpm_match, piixpm_attach, NULL, NULL);
+CFATTACH_DECL3_NEW(piixpm, sizeof(struct piixpm_softc),
+    piixpm_match, piixpm_attach, NULL, NULL, piixpm_rescan, piixpm_chdet, 0);
 
 static int
 piixpm_match(device_t parent, cfdata_t match, void *aux)
@@ -150,12 +154,11 @@
 {
        struct piixpm_softc *sc = device_private(self);
        struct pci_attach_args *pa = aux;
-       struct i2cbus_attach_args iba;
        pcireg_t base, conf;
        pcireg_t pmmisc;
        pci_intr_handle_t ih;
        const char *intrstr = NULL;
-       int i, numbusses = 1;
+       int i, flags;
        char intrbuf[PCI_INTRSTR_LEN];
 
        sc->sc_dev = self;
@@ -163,6 +166,7 @@
        sc->sc_id = pa->pa_id;
        sc->sc_pc = pa->pa_pc;
        sc->sc_pcitag = pa->pa_tag;
+       sc->sc_numbusses = 1;
 
        pci_aprint_devinfo(pa, NULL);
 
@@ -206,7 +210,7 @@
            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_SMB &&
            PCI_REVISION(pa->pa_class) >= 0x40) {
                if (piixpm_sb800_init(sc) == 0) {
-                       numbusses = 4;
+                       sc->sc_numbusses = 4;
                        goto attach_i2c;
                }
                aprint_normal_dev(self, "SMBus disabled\n");
@@ -249,24 +253,60 @@
        aprint_normal("\n");
 
 attach_i2c:
+       for (i = 0; i < sc->sc_numbusses; i++)
+               sc->sc_i2c_device[i] = NULL;
+
+       flags = 0;
+       piixpm_rescan(self, "i2cbus", &flags);
+}
+
+static int
+piixpm_rescan(device_t self, const char *ifattr, const int *flags)
+{
+       struct piixpm_softc *sc = device_private(self);
+       struct i2cbus_attach_args iba;
+       int i;
+
+       if (!ifattr_match(ifattr, "i2cbus"))
+               return 0;
+
        /* Attach I2C bus */
        mutex_init(&sc->sc_i2c_mutex, MUTEX_DEFAULT, IPL_NONE);
 
-       for (i = 0; i < numbusses; i++) {
+       for (i = 0; i < sc->sc_numbusses; i++) {
+               if (sc->sc_i2c_device[i])
+                       continue;
                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;
-
                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);
+               sc->sc_i2c_device[i] = config_found_ia(self, ifattr, &iba,
+                                                   iicbus_print);
+       }
+
+       return 0;
+}
+
+static void
+piixpm_chdet(device_t self, device_t child)
+{
+       struct piixpm_softc *sc = device_private(self);
+       int i;
+
+       for (i = 0; i < sc->sc_numbusses; i++) {
+               if (sc->sc_i2c_device[i] == child) {
+                       sc->sc_i2c_device[i] = NULL;
+                       break;
+               }
        }
 }
 
+
 static bool
 piixpm_suspend(device_t dv, const pmf_qual_t *qual)
 {



Home | Main Index | Thread Index | Old Index