Source-Changes-HG archive

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

[src/thorpej-i2c-spi-conf]: src/sys/dev/ic Update the pcfiic driver for the n...



details:   https://anonhg.NetBSD.org/src/rev/e8dc6566599f
branches:  thorpej-i2c-spi-conf
changeset: 378777:e8dc6566599f
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Fri May 14 06:53:14 2021 +0000

description:
Update the pcfiic driver for the new i2c device enumeration scheme.
Push the multiple-channels complexity up into the ebus front-end,
as that specific to a particular Sun model of controller.  Now
the BBC-type controllers get multiple I2C bus instances attached to
them.

diffstat:

 sys/arch/sparc64/dev/pcfiic_ebus.c |  181 +++++++++++++++++++++++++++++++-----
 sys/dev/ic/pcf8584.c               |   95 ++++++++++++++-----
 sys/dev/ic/pcf8584var.h            |   36 +++++-
 3 files changed, 253 insertions(+), 59 deletions(-)

diffs (truncated from 484 to 300 lines):

diff -r 534fa4606901 -r e8dc6566599f sys/arch/sparc64/dev/pcfiic_ebus.c
--- a/sys/arch/sparc64/dev/pcfiic_ebus.c        Fri May 14 03:57:51 2021 +0000
+++ b/sys/arch/sparc64/dev/pcfiic_ebus.c        Fri May 14 06:53:14 2021 +0000
@@ -1,7 +1,36 @@
-/*     $NetBSD: pcfiic_ebus.c,v 1.7 2020/10/23 15:18:10 jdc Exp $      */
+/*     $NetBSD: pcfiic_ebus.c,v 1.7.6.1 2021/05/14 06:53:14 thorpej Exp $      */
 /*     $OpenBSD: pcfiic_ebus.c,v 1.13 2008/06/08 03:07:40 deraadt Exp $ */
 
 /*
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
  * Copyright (c) 2006 David Gwynne <dlg%openbsd.org@localhost>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -18,7 +47,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcfiic_ebus.c,v 1.7 2020/10/23 15:18:10 jdc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcfiic_ebus.c,v 1.7.6.1 2021/05/14 06:53:14 thorpej Exp $");
 
 /*
  * Device specific driver for the EBus i2c devices found on some sun4u
@@ -30,7 +59,8 @@
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/kernel.h>
-#include <sys/rwlock.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
 
 #include <sys/bus.h>
 #include <machine/openfirm.h>
@@ -44,20 +74,119 @@
 #include <dev/ic/pcf8584var.h>
 #include <dev/ic/pcf8584reg.h>
 
-int    pcfiic_ebus_match(device_t, struct cfdata *, void *);
-void   pcfiic_ebus_attach(device_t, device_t, void *);
-
 struct pcfiic_ebus_softc {
        struct pcfiic_softc     esc_sc;
 
-       int                     esc_node;
+       kmutex_t                esc_ctrl_lock;
+       bus_space_handle_t      esc_ioh;        /* for channel selection */
+
        void                    *esc_ih;
 };
 
-CFATTACH_DECL_NEW(pcfiic, sizeof(struct pcfiic_ebus_softc),
-       pcfiic_ebus_match, pcfiic_ebus_attach, NULL, NULL);
+static void
+bbc_select_channel(struct pcfiic_ebus_softc *esc, uint8_t channel)
+{
+       bus_space_write_1(esc->esc_sc.sc_iot, esc->esc_ioh, 0, channel);
+       bus_space_barrier(esc->esc_sc.sc_iot, esc->esc_ioh, 0, 1,
+           BUS_SPACE_BARRIER_WRITE);
+}
+
+static int
+bbc_acquire_bus(void *v, int flags)
+{
+       struct pcfiic_channel *ch = v;
+       struct pcfiic_ebus_softc *esc = container_of(ch->ch_sc,
+           struct pcfiic_ebus_softc, esc_sc);
+
+       if (flags & I2C_F_POLL) {
+               if (! mutex_tryenter(&esc->esc_ctrl_lock)) {
+                       return EBUSY;
+               }
+       } else {
+               mutex_enter(&esc->esc_ctrl_lock);
+       }
+
+       bbc_select_channel(esc, (uint8_t)ch->ch_channel);
+       return 0;
+}
+
+static void
+bbc_release_bus(void *v, int flags)
+{
+       struct pcfiic_channel *ch = v;
+       struct pcfiic_ebus_softc *esc = container_of(ch->ch_sc,
+           struct pcfiic_ebus_softc, esc_sc);
+
+       mutex_exit(&esc->esc_ctrl_lock);
+}
+
+static void
+bbc_initialize_channels(struct pcfiic_ebus_softc *esc)
+{
+       struct pcfiic_softc *sc = &esc->esc_sc;
+       struct pcfiic_channel *ch;
+       devhandle_t devhandle = device_handle(sc->sc_dev);
+       unsigned int busmap = 0;
+       int node = devhandle_to_of(devhandle);
+       uint32_t reg[2];
+       uint32_t channel;
+       int i, nchannels;
 
-int
+       /*
+        * Two physical I2C busses share a single controller.  The
+        * devices are not distinct, so it's not easy to treat it
+        * it as a mux.
+        *
+        * The locking order is:
+        *
+        *      iic bus mutex -> ctrl_lock
+        *
+        * ctrl_lock is taken in bbc_acquire_bus.
+        */
+       mutex_init(&esc->esc_ctrl_lock, MUTEX_DEFAULT, IPL_NONE);
+       sc->sc_acquire_bus = bbc_acquire_bus;
+       sc->sc_release_bus = bbc_release_bus;
+
+       /*
+        * The Sun device tree has all devices, no matter the
+        * channel, as direct children of this node.  Figure
+        * out which channel numbers are listed, count them,
+        * and then populate the channel structures.
+        */
+       for (node = OF_child(node); node != 0; node = OF_peer(node)) {
+               if (OF_getprop(node, "reg", reg, sizeof(reg)) != sizeof(reg)) {
+                       continue;
+               }
+
+               /* Channel is in the first cell. */
+               channel = be32toh(reg[0]);
+               KASSERT(channel < 32);
+
+               busmap |= __BIT(channel);
+       }
+
+       nchannels = popcount(busmap);
+       if (nchannels == 0) {
+               /* No child devices. */
+               return;
+       }
+
+       ch = kmem_alloc(nchannels * sizeof(*ch), KM_SLEEP);
+       for (i = 0; i < nchannels; i++) {
+               channel = ffs(busmap);
+               KASSERT(channel != 0);
+               channel--;      /* ffs() returns 0 if no bits set. */
+               busmap &= ~__BIT(channel);
+
+               ch[i].ch_channel = channel;
+               ch[i].ch_devhandle = devhandle;
+       }
+
+       sc->sc_channels = ch;
+       sc->sc_nchannels = nchannels;
+}
+
+static int
 pcfiic_ebus_match(device_t parent, struct cfdata *match, void *aux)
 {
        struct ebus_attach_args         *ea = aux;
@@ -82,15 +211,15 @@ pcfiic_ebus_match(device_t parent, struc
        return (0);
 }
 
-void
+static void
 pcfiic_ebus_attach(device_t parent, device_t self, void *aux)
 {
        struct pcfiic_ebus_softc        *esc = device_private(self);
        struct pcfiic_softc             *sc = &esc->esc_sc;
        struct ebus_attach_args         *ea = aux;
        char                            compat[32];
-       u_int64_t                       addr;
-       u_int8_t                        clock = PCF8584_CLK_12 | PCF8584_SCL_90;
+       uint32_t                        addr[2];
+       uint8_t                         clock = PCF8584_CLK_12 | PCF8584_SCL_90;
        int                             swapregs = 0;
 
        if (ea->ea_nreg < 1 || ea->ea_nreg > 2) {
@@ -121,15 +250,15 @@ pcfiic_ebus_attach(device_t parent, devi
        }
 
        if (OF_getprop(ea->ea_node, "own-address", &addr, sizeof(addr)) == -1) {
-               addr = 0xaa;
-       } else if (addr == 0x00 || addr > 0xff) {
+               addr[0] = 0;
+               addr[1] = 0x55 << 1;
+       } else if (addr[1] == 0x00 || addr[1] > 0xff) {
                printf(": invalid address on I2C bus");
                return;
        }
 
-       if (bus_space_map(ea->ea_bustag,
-           EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
-           ea->ea_reg[0].size, 0, &sc->sc_ioh) == 0) {
+       if (bus_space_map(ea->ea_bustag, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
+                         ea->ea_reg[0].size, 0, &sc->sc_ioh) == 0) {
                sc->sc_iot = ea->ea_bustag;
        } else {
                printf(": can't map register space\n");
@@ -140,14 +269,14 @@ pcfiic_ebus_attach(device_t parent, devi
                /*
                 * Second register only occurs on BBC-based machines,
                 * and is likely not prom mapped
-               */
-               if (bus_space_map(sc->sc_iot, EBUS_ADDR_FROM_REG(&ea->ea_reg[1]),
-                   ea->ea_reg[1].size, 0, &sc->sc_ioh2) != 0) {
+                */
+               if (bus_space_map(sc->sc_iot,
+                                 EBUS_ADDR_FROM_REG(&ea->ea_reg[1]),
+                                 ea->ea_reg[1].size, 0, &esc->esc_ioh) != 0) {
                        printf(": can't map 2nd register space\n");
                        return;
                }
-               sc->sc_master = 1;
-               printf(": iic mux present");
+               bbc_initialize_channels(esc);
        }
 
        if (ea->ea_nintr >= 1)
@@ -156,9 +285,11 @@ pcfiic_ebus_attach(device_t parent, devi
        else
                esc->esc_ih = NULL;
 
-
        if (esc->esc_ih == NULL)
                sc->sc_poll = 1;
 
-       pcfiic_attach(sc, (i2c_addr_t)(addr >> 1), clock, swapregs);
+       pcfiic_attach(sc, (i2c_addr_t)(addr[1] >> 1), clock, swapregs);
 }
+
+CFATTACH_DECL_NEW(pcfiic, sizeof(struct pcfiic_ebus_softc),
+    pcfiic_ebus_match, pcfiic_ebus_attach, NULL, NULL);
diff -r 534fa4606901 -r e8dc6566599f sys/dev/ic/pcf8584.c
--- a/sys/dev/ic/pcf8584.c      Fri May 14 03:57:51 2021 +0000
+++ b/sys/dev/ic/pcf8584.c      Fri May 14 06:53:14 2021 +0000
@@ -1,7 +1,36 @@
-/*     $NetBSD: pcf8584.c,v 1.18 2021/04/24 23:36:55 thorpej Exp $     */
+/*     $NetBSD: pcf8584.c,v 1.18.2.1 2021/05/14 06:53:14 thorpej Exp $ */
 /*     $OpenBSD: pcf8584.c,v 1.9 2007/10/20 18:46:21 kettenis Exp $ */
 
 /*
+ * Copyright (c) 2021 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
  * Copyright (c) 2006 David Gwynne <dlg%openbsd.org@localhost>



Home | Main Index | Thread Index | Old Index