Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Re-factor the "iicmux" driver to support other types...



details:   https://anonhg.NetBSD.org/src/rev/136bb72df3b0
branches:  trunk
changeset: 1017476:136bb72df3b0
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Mon Dec 28 20:29:57 2020 +0000

description:
Re-factor the "iicmux" driver to support other types of muxes that are
themselves i2c devices.

diffstat:

 sys/dev/fdt/files.fdt    |    4 +-
 sys/dev/fdt/i2cmux_fdt.c |  344 ++++++++++++----------------------------------
 sys/dev/i2c/files.i2c    |    6 +-
 sys/dev/i2c/i2cmux.c     |  228 +++++++++++++++++++++++++++++++
 sys/dev/i2c/i2cmuxvar.h  |   69 +++++++++
 5 files changed, 395 insertions(+), 256 deletions(-)

diffs (truncated from 817 to 300 lines):

diff -r 6c6e6801c410 -r 136bb72df3b0 sys/dev/fdt/files.fdt
--- a/sys/dev/fdt/files.fdt     Mon Dec 28 20:19:50 2020 +0000
+++ b/sys/dev/fdt/files.fdt     Mon Dec 28 20:29:57 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.fdt,v 1.58 2020/12/23 04:09:32 thorpej Exp $
+# $NetBSD: files.fdt,v 1.59 2020/12/28 20:29:57 thorpej Exp $
 
 include        "external/bsd/libfdt/conf/files.libfdt"
 
@@ -54,7 +54,7 @@
 attach dispcon at fdt with dispcon_hdmi
 file   dev/fdt/hdmi_connector.c                dispcon_hdmi
 
-device iicmux: i2cbus
+device iicmux: i2cbus, i2cmux
 attach iicmux at fdt with iicmux_fdt
 file   dev/fdt/i2cmux_fdt.c                    iicmux_fdt
 
diff -r 6c6e6801c410 -r 136bb72df3b0 sys/dev/fdt/i2cmux_fdt.c
--- a/sys/dev/fdt/i2cmux_fdt.c  Mon Dec 28 20:19:50 2020 +0000
+++ b/sys/dev/fdt/i2cmux_fdt.c  Mon Dec 28 20:29:57 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: i2cmux_fdt.c,v 1.3 2020/12/28 15:08:06 thorpej Exp $   */
+/*     $NetBSD: i2cmux_fdt.c,v 1.4 2020/12/28 20:29:57 thorpej Exp $   */
 
 /*-
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i2cmux_fdt.c,v 1.3 2020/12/28 15:08:06 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i2cmux_fdt.c,v 1.4 2020/12/28 20:29:57 thorpej Exp $");
 
 #include <sys/types.h>
 #include <sys/device.h>
@@ -40,188 +40,101 @@
 #include <sys/gpio.h>
 
 #include <dev/fdt/fdtvar.h>
-#include <dev/i2c/i2cvar.h>
-
-/*
- * i2c mux
- *
- * This works by interposing a virtual controller in front of the
- * real i2c controller.  We provide our own acquire release functions
- * that perform the following tasks:
- *
- *     acquire -> acquire parent controller, program mux
- *
- *     release -> idle mux, release parent controller
- *
- * All of the actual I/O operations are transparently passed through.
- *
- * N.B. the locking order; the generic I2C layer has already acquired
- * our virtual controller's mutex before calling our acquire function,
- * and we will then acquire the real controller's mutex when we acquire
- * the bus, so the order is:
- *
- *     mux virtual controller -> parent controller
- */
-
-struct iicmux_softc;
-struct iicmux_bus;
-
-struct iicmux_config {
-       const char *desc;
-       int     (*get_mux_info)(struct iicmux_softc *);
-       int     (*get_bus_info)(struct iicmux_bus *);
-       int     (*acquire_bus)(struct iicmux_bus *, int);
-       void    (*release_bus)(struct iicmux_bus *, int);
-};
-
-struct iicmux_bus {
-       struct i2c_controller controller;
-       struct iicmux_softc *mux;
-       int phandle;
-       int busidx;
-
-       union {
-               struct {
-                       bus_addr_t value;
-               } gpio;
-
-               struct {
-                       bus_addr_t idx;
-               } pinctrl;
-       };
-};
-
-struct iicmux_softc {
-       device_t                        sc_dev;
-       int                             sc_phandle;
-       int                             sc_i2c_mux_phandle;
-       const struct iicmux_config *    sc_config;
-       i2c_tag_t                       sc_i2c_parent;
-       struct iicmux_bus *             sc_busses;
-       int                             sc_nbusses;
-
-       union {
-               struct {
-                       struct fdtbus_gpio_pin **pins;
-                       int npins;
-                       uint32_t idle_value;
-                       bool has_idle_value;
-               } sc_gpio;
-
-               struct {
-                       u_int idle_idx;
-                       bool has_idle_idx;
-               } sc_pinctrl;
-       };
-};
+#include <dev/i2c/i2cmuxvar.h>
 
 /*****************************************************************************/
 
-static int
-iicmux_acquire_bus(void * const v, int const flags)
-{
-       struct iicmux_bus * const bus = v;
-       struct iicmux_softc * const sc = bus->mux;
-       int error;
+struct mux_info_gpio {
+       struct fdtbus_gpio_pin **pins;
+       int npins;
+       uint32_t idle_value;
+       bool has_idle_value;
+};
+
+struct bus_info_gpio {
+       bus_addr_t value;
+};
 
-       error = iic_acquire_bus(sc->sc_i2c_parent, flags);
-       if (error) {
-               return error;
-       }
+static void *
+iicmux_gpio_get_mux_info(struct iicmux_softc * const sc)
+{
+       struct mux_info_gpio *mux_data;
+       int i;
 
-       error = sc->sc_config->acquire_bus(bus, flags);
-       if (error) {
-               iic_release_bus(sc->sc_i2c_parent, flags);
+       mux_data = kmem_zalloc(sizeof(*mux_data), KM_SLEEP);
+
+       mux_data->npins = fdtbus_gpio_count(sc->sc_phandle, "mux-gpios");
+       if (mux_data->npins == 0) {
+               aprint_error_dev(sc->sc_dev,
+                   "unable to get mux-gpios property\n");
+               goto bad;
        }
 
-       return error;
-}
-
-static void
-iicmux_release_bus(void * const v, int const flags)
-{
-       struct iicmux_bus * const bus = v;
-       struct iicmux_softc * const sc = bus->mux;
-
-       sc->sc_config->release_bus(bus, flags);
-       iic_release_bus(sc->sc_i2c_parent, flags);
-}
-
-static int
-iicmux_exec(void * const v, i2c_op_t const op, i2c_addr_t const addr,
-    const void * const cmdbuf, size_t const cmdlen, void * const databuf,
-    size_t const datalen, int const flags)
-{
-       struct iicmux_bus * const bus = v;
-       struct iicmux_softc * const sc = bus->mux;
-
-       return iic_exec(sc->sc_i2c_parent, op, addr, cmdbuf, cmdlen,
-                       databuf, datalen, flags);
-}
-
-/*****************************************************************************/
-
-static int
-iicmux_gpio_get_mux_info(struct iicmux_softc * const sc)
-{
-       int i;
-
-       sc->sc_gpio.npins = fdtbus_gpio_count(sc->sc_phandle, "mux-gpios");
-       if (sc->sc_gpio.npins == 0) {
-               aprint_error_dev(sc->sc_dev,
-                   "unable to get mux-gpios property\n");
-               return ENXIO;
-       }
-
-       sc->sc_gpio.pins =
-           kmem_zalloc(sizeof(*sc->sc_gpio.pins) * sc->sc_gpio.npins,
-                              KM_SLEEP);
-       for (i = 0; i < sc->sc_gpio.npins; i++) {
-               sc->sc_gpio.pins[i] = fdtbus_gpio_acquire_index(sc->sc_phandle,
+       mux_data->pins =
+           kmem_zalloc(sizeof(*mux_data->pins) * mux_data->npins, KM_SLEEP);
+       for (i = 0; i < mux_data->npins; i++) {
+               mux_data->pins[i] = fdtbus_gpio_acquire_index(sc->sc_phandle,
                    "mux-gpios", i, GPIO_PIN_OUTPUT);
-               if (sc->sc_gpio.pins[i] == NULL) {
+               if (mux_data->pins[i] == NULL) {
                        aprint_error_dev(sc->sc_dev,
                            "unable to acquire gpio #%d\n", i);
-                       return ENXIO;
+                       goto bad;
                }
        }
 
-       sc->sc_gpio.has_idle_value =
+       mux_data->has_idle_value =
            of_getprop_uint32(sc->sc_phandle, "idle-state",
-                             &sc->sc_gpio.idle_value) == 0;
+                             &mux_data->idle_value) == 0;
+
+       return mux_data;
 
-       return 0;
+ bad:
+       for (i = 0; i < mux_data->npins; i++) {
+               if (mux_data->pins[i] != NULL) {
+                       fdtbus_gpio_release(mux_data->pins[i]);
+               }
+       }
+       kmem_free(mux_data, sizeof(*mux_data));
+       return NULL;
 }
 
-static int
+static void *
 iicmux_gpio_get_bus_info(struct iicmux_bus * const bus)
 {
        struct iicmux_softc * const sc = bus->mux;
+       struct bus_info_gpio *bus_info;
        int error;
 
-       error = fdtbus_get_reg(bus->phandle, 0, &bus->gpio.value, NULL);
+       bus_info = kmem_zalloc(sizeof(*bus_info), KM_SLEEP);
+
+       error = fdtbus_get_reg(bus->phandle, 0, &bus_info->value, NULL);
        if (error) {
                aprint_error_dev(sc->sc_dev,
                    "unable to get reg property for bus %d\n", bus->busidx);
+               kmem_free(bus_info, sizeof(*bus_info));
+               return NULL;
        }
 
-       return error;
+       return bus_info;
 }
 
 static void
 iicmux_gpio_set_value(struct iicmux_softc * const sc, bus_addr_t value)
 {
+       struct mux_info_gpio * const mux_info = sc->sc_mux_data;
        int i;
 
-       for (i = 0; i < sc->sc_gpio.npins; i++, value >>= 1) {
-               fdtbus_gpio_write(sc->sc_gpio.pins[i], value & 1);
+       for (i = 0; i < mux_info->npins; i++, value >>= 1) {
+               fdtbus_gpio_write(mux_info->pins[i], value & 1);
        }
 }
 
 static int
 iicmux_gpio_acquire_bus(struct iicmux_bus * const bus, int const flags __unused)
 {
-       iicmux_gpio_set_value(bus->mux, bus->gpio.value);
+       struct bus_info_gpio * const bus_info = bus->bus_data;
+
+       iicmux_gpio_set_value(bus->mux, bus_info->value);
 
        return 0;
 }
@@ -229,10 +142,11 @@
 static void
 iicmux_gpio_release_bus(struct iicmux_bus * const bus, int const flags __unused)
 {
-       struct iicmux_softc *sc = bus->mux;
+       struct iicmux_softc * const sc = bus->mux;
+       struct mux_info_gpio * const mux_info = sc->sc_mux_data;
 
-       if (sc->sc_gpio.has_idle_value) {
-               iicmux_gpio_set_value(sc, sc->sc_gpio.idle_value);
+       if (mux_info->has_idle_value) {
+               iicmux_gpio_set_value(sc, mux_info->idle_value);
        }
 }
 
@@ -246,31 +160,47 @@
 
 /*****************************************************************************/
 
-static int



Home | Main Index | Thread Index | Old Index