The branch stable/13 has been updated by avg:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f1d2f22b34ab6c7216fcc980c57b60d5ef8f21d2

commit f1d2f22b34ab6c7216fcc980c57b60d5ef8f21d2
Author:     Andriy Gapon <a...@freebsd.org>
AuthorDate: 2020-08-18 09:16:28 +0000
Commit:     Andriy Gapon <a...@freebsd.org>
CommitDate: 2021-11-24 14:19:09 +0000

    pca954x: driver for PCA954x / TCA954x I2C switches
    
    At the moment only PCA9548A is supported and has been tested.
    
    (cherry picked from commit c0525ab1d1ce69ab3d589e95733caedb04e0dcbd)
---
 share/man/man4/Makefile              |   1 +
 share/man/man4/pca954x.4             | 119 +++++++++++++++++++
 sys/conf/files                       |   1 +
 sys/dev/iicbus/mux/pca954x.c         | 214 +++++++++++++++++++++++++++++++++++
 sys/modules/i2c/mux/Makefile         |   1 +
 sys/modules/i2c/mux/pca954x/Makefile |  20 ++++
 6 files changed, 356 insertions(+)

diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index e8c0a5651ff8..be66bf02e9f7 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -422,6 +422,7 @@ MAN=        aac.4 \
        owc.4 \
        ${_padlock.4} \
        pass.4 \
+       pca954x.4 \
        pccard.4 \
        pccbb.4 \
        pcf.4 \
diff --git a/share/man/man4/pca954x.4 b/share/man/man4/pca954x.4
new file mode 100644
index 000000000000..d845740f9b6c
--- /dev/null
+++ b/share/man/man4/pca954x.4
@@ -0,0 +1,119 @@
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+.\"
+.\" Copyright (c) 2020 Andriy Gapon <a...@freebsd.org>
+.\"
+.\" 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 AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 13, 2021
+.Dt PCA954X 4
+.Os
+.Sh NAME
+.Nm pca954x
+.Nd driver for PCA9548A I2C switch
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following line in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device pca954x"
+.Cd "device iicmux"
+.Cd "device iicbus"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+pca954x_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver supports the PCA9548A I2C bus switch and compatible chips such as
+TCA9548A.
+It automatically connects an upstream I2C bus to one of several downstream
+buses as needed when slave devices on the downstream buses initiate I/O.
+More information on the automatic switching behavior is available in
+.Xr iicmux 4 .
+.Sh FDT CONFIGURATION
+On an
+.Xr FDT 4
+based system, an
+.Nm
+device node is defined as a child node of its upstream I2C bus.
+The children of the
+.Nm
+node are additional I2C buses, which will have their own I2C slave
+devices described in their child nodes.
+.Pp
+The
+.Nm
+driver attaches to nodes where the
+.Va compatible
+property is set to one of
+.Bl -bullet
+.It
+.Qq nxp,pca9548
+.El
+.Pp
+The
+.Nm
+driver supports the following optional properties in addition to the standard
+I2C mux properties:
+.Bl -tag -width i2c-mux-idle-disconnect
+.It Va i2c-mux-idle-disconnect
+if defined, forces the switch to disconnect all children in idle state.
+.El
+.Sh HINTS CONFIGURATION
+On a
+.Xr device.hints 5
+based system, these values are configurable for
+.Nm :
+.Bl -tag -width hint.pca954x.<unit>.chip_type
+.It Va hint.pca954x.<unit>.at
+The upstream
+.Xr iicbus 4
+the
+.Nm
+instance is attached to.
+.It Va hint.pca954x.<unit>.chip_type
+The type of the chip.
+At present, only
+.Qq pca9548
+is supported.
+.El
+.Pp
+When configured via hints, the driver automatically adds an
+.Xr iicbus 4
+instance for every downstream bus supported by the chip.
+There is currently no way to indicate used versus unused channels.
+.Sh SEE ALSO
+.Xr iicbus 4 ,
+.Xr iicmux 4
+.Sh HISTORY
+The
+.Nm
+driver and this manual page was written by
+.An Andriy Gapon Aq Mt a...@freebsd.org .
diff --git a/sys/conf/files b/sys/conf/files
index 5051a38b2997..3dc1caf8b53a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1884,6 +1884,7 @@ dev/iicbus/mux/iicmux.c           optional iicmux
 dev/iicbus/mux/iicmux_if.m     optional iicmux
 dev/iicbus/mux/iic_gpiomux.c   optional iic_gpiomux fdt
 dev/iicbus/mux/ltc430x.c       optional ltc430x
+dev/iicbus/mux/pca954x.c       optional pca954x
 dev/iicbus/nxprtc.c            optional nxprtc | pcf8563
 dev/iicbus/ofw_iicbus.c                optional fdt iicbus
 dev/iicbus/pcf8574.c           optional pcf8574
diff --git a/sys/dev/iicbus/mux/pca954x.c b/sys/dev/iicbus/mux/pca954x.c
new file mode 100644
index 000000000000..44c81539691e
--- /dev/null
+++ b/sys/dev/iicbus/mux/pca954x.c
@@ -0,0 +1,214 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) Andriy Gapon
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+
+#ifdef FDT
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+#endif
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+#include "iicbus_if.h"
+#include "iicmux_if.h"
+#include <dev/iicbus/mux/iicmux.h>
+
+struct pca954x_descr {
+       const char      *partname;
+       const char      *description;
+       int             numchannels;
+};
+
+static struct pca954x_descr pca9548_descr = {
+       .partname = "pca9548",
+       .description = "PCA9548A I2C Mux",
+       .numchannels = 8,
+};
+
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+       { "nxp,pca9548", (uintptr_t)&pca9548_descr },
+       { NULL, 0 },
+};
+#else
+static struct pca954x_descr *part_descrs[] = {
+       &pca9548_descr,
+};
+#endif
+
+struct pca954x_softc {
+       struct iicmux_softc mux;
+       uint8_t addr;
+       bool idle_disconnect;
+};
+
+static int
+pca954x_bus_select(device_t dev, int busidx, struct iic_reqbus_data *rd)
+{
+       struct iic_msg msg;
+       struct pca954x_softc *sc = device_get_softc(dev);
+       uint8_t busbits;
+       int error;
+
+       /*
+        * The iicmux caller ensures busidx is between 0 and the number of buses
+        * we passed to iicmux_init_softc(), no need for validation here.  If
+        * the fdt data has the idle_disconnect property we idle the bus by
+        * selecting no downstream buses, otherwise we just leave the current
+        * bus active.
+        */
+       if (busidx == IICMUX_SELECT_IDLE) {
+               if (sc->idle_disconnect)
+                       busbits = 0;
+               else
+                       return (0);
+       } else {
+               busbits = 1u << busidx;
+       }
+
+       msg.slave = sc->addr;
+       msg.flags = IIC_M_WR;
+       msg.len = 1;
+       msg.buf = &busbits;
+       error = iicbus_transfer(dev, &msg, 1);
+       return (error);
+}
+
+static const struct pca954x_descr *
+pca954x_find_chip(device_t dev)
+{
+#ifdef FDT
+       const struct ofw_compat_data *compat;
+
+       compat = ofw_bus_search_compatible(dev, compat_data);
+       if (compat == NULL)
+               return (NULL);
+       return ((const struct pca954x_descr *)compat->ocd_data);
+#else
+       const char *type;
+       int i;
+
+       if (resource_string_value(device_get_name(dev), device_get_unit(dev),
+           "chip_type", &type) == 0) {
+               for (i = 0; i < nitems(part_descrs) - 1; ++i) {
+                       if (strcasecmp(type, part_descrs[i]->partname) == 0)
+                               return (part_descrs[i]);
+               }
+       }
+       return (NULL);
+#endif
+}
+
+static int
+pca954x_probe(device_t dev)
+{
+       const struct pca954x_descr *descr;
+
+       descr = pca954x_find_chip(dev);
+       if (descr == NULL)
+               return (ENXIO);
+
+       device_set_desc(dev, descr->description);
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pca954x_attach(device_t dev)
+{
+#ifdef FDT
+       phandle_t node;
+#endif
+       struct pca954x_softc *sc;
+       const struct pca954x_descr *descr;
+       int err;
+
+       sc = device_get_softc(dev);
+       sc->addr = iicbus_get_addr(dev);
+#ifdef FDT
+       node = ofw_bus_get_node(dev);
+       sc->idle_disconnect = OF_hasprop(node, "i2c-mux-idle-disconnect");
+#endif
+
+       descr = pca954x_find_chip(dev);
+       err = iicmux_attach(dev, device_get_parent(dev), descr->numchannels);
+       if (err == 0)
+                bus_generic_attach(dev);
+       return (err);
+}
+
+static int
+pca954x_detach(device_t dev)
+{
+       int err;
+
+       err = iicmux_detach(dev);
+       return (err);
+}
+
+static device_method_t pca954x_methods[] = {
+       /* device methods */
+       DEVMETHOD(device_probe,                 pca954x_probe),
+       DEVMETHOD(device_attach,                pca954x_attach),
+       DEVMETHOD(device_detach,                pca954x_detach),
+
+       /* iicmux methods */
+       DEVMETHOD(iicmux_bus_select,            pca954x_bus_select),
+
+       DEVMETHOD_END
+};
+
+static devclass_t pca954x_devclass;
+
+DEFINE_CLASS_1(pca9548, pca954x_driver, pca954x_methods,
+    sizeof(struct pca954x_softc), iicmux_driver);
+DRIVER_MODULE(pca9548, iicbus, pca954x_driver, pca954x_devclass, 0, 0);
+
+#ifdef FDT
+DRIVER_MODULE(ofw_iicbus, pca9548, ofw_iicbus_driver, ofw_iicbus_devclass, 0, 
0);
+#else
+DRIVER_MODULE(iicbus, pca9548, iicbus_driver, iicbus_devclass, 0, 0);
+#endif
+
+MODULE_DEPEND(pca9548, iicmux, 1, 1, 1);
+MODULE_DEPEND(pca9548, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+MODULE_VERSION(pca9548, 1);
+
+#ifdef FDT
+IICBUS_FDT_PNP_INFO(compat_data);
+#endif
diff --git a/sys/modules/i2c/mux/Makefile b/sys/modules/i2c/mux/Makefile
index 8e228a7a7fef..a972a00a3b3a 100644
--- a/sys/modules/i2c/mux/Makefile
+++ b/sys/modules/i2c/mux/Makefile
@@ -3,6 +3,7 @@
 SUBDIR = \
        iicmux \
        ltc430x \
+       pca954x \
 
 .if !empty(OPT_FDT)
 SUBDIR+= iic_gpiomux
diff --git a/sys/modules/i2c/mux/pca954x/Makefile 
b/sys/modules/i2c/mux/pca954x/Makefile
new file mode 100644
index 000000000000..622b327204c5
--- /dev/null
+++ b/sys/modules/i2c/mux/pca954x/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.PATH:         ${SRCTOP}/sys/dev/iicbus/mux
+
+KMOD=  pca954x
+SRCS=  pca954x.c
+
+SRCS+= \
+       bus_if.h \
+       device_if.h \
+       iicbus_if.h \
+       iicmux_if.h \
+       opt_platform.h \
+
+.if !empty(OPT_FDT)
+SRCS+= ofw_bus_if.h
+.endif
+
+
+.include <bsd.kmod.mk>

Reply via email to