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/10a00c4376ad
branches: trunk
changeset: 948675:10a00c4376ad
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 d34484219242 -r 10a00c4376ad 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 d34484219242 -r 10a00c4376ad 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