Page MenuHomeFreeBSD

D46742.diff
No OneTemporary

D46742.diff

diff --git a/sys/arm/conf/AM335X b/sys/arm/conf/AM335X
--- a/sys/arm/conf/AM335X
+++ b/sys/arm/conf/AM335X
@@ -140,7 +140,7 @@
# Pinmux
device fdt_pinctrl
-#device pinctrl_single
+device pinctrl_single
# TI Programmable Realtime Unit support
device ti_pruss
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2625,6 +2625,7 @@
dev/phy/phynode_if.m optional phy
dev/phy/phy_usb.c optional phy
dev/phy/phynode_usb_if.m optional phy
+dev/pinctrl/pinctrl_single.c optional fdt fdt_pinctrl pinctrl_single
dev/pms/freebsd/driver/ini/src/agtiapi.c optional pmspcv \
compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
dev/pms/RefTisa/sallsdk/spc/sadisc.c optional pmspcv \
diff --git a/sys/dev/pinctrl/pinctrl_single.c b/sys/dev/pinctrl/pinctrl_single.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/pinctrl/pinctrl_single.c
@@ -0,0 +1,386 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2023 Oskar Holmlund
+ *
+ * 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.
+ */
+
+/*
+ * sys/contrib/device-tree/Bindings/pinctrl/pinctrl-single.txt
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/syscon/syscon.h>
+#include <dev/fdt/fdt_pinctrl.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "syscon_if.h"
+
+MALLOC_DECLARE(M_SYSCON);
+
+#if 0
+#define DPRINTF(dev, msg...) device_printf(dev, msg)
+#else
+#define DPRINTF(dev, msg...)
+#endif
+
+#define PINCTRL_SINGLE 2
+#define PINCONF_SINGLE 1
+
+static struct ofw_compat_data compat_data[] = {
+ {"pinctrl-single", PINCTRL_SINGLE},
+ {"pinconf-single", PINCONF_SINGLE},
+ {NULL, 0},
+};
+
+static struct resource_spec pinctrl_single_res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct pinctrl_single_softc {
+ device_t sc_dev;
+ struct resource *sc_res[1];
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ struct syscon *sc_syscon;
+
+ uint32_t sc_ncells;
+ uint32_t sc_regwidth;
+ uint32_t sc_funcmask;
+};
+
+/* --- dev/syscon syscon_method_t interface --- */
+static int
+pinctrl_single_syscon_unlocked_write_4(struct syscon *syscon, bus_size_t offset,
+ uint32_t value)
+{
+ struct pinctrl_single_softc *sc;
+
+ sc = device_get_softc(syscon->pdev);
+ DPRINTF(sc->sc_dev, "offset=%lx write %x\n", offset, value);
+ switch (sc->sc_regwidth) {
+ case 8:
+ bus_space_write_1(sc->sc_bst, sc->sc_bsh, offset, value);
+ break;
+ case 16:
+ bus_space_write_2(sc->sc_bst, sc->sc_bsh, offset, value);
+ break;
+ case 32:
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, offset, value);
+ break;
+ }
+ return (0);
+}
+
+static uint32_t
+pinctrl_single_syscon_unlocked_read_4(struct syscon *syscon, bus_size_t offset)
+{
+ struct pinctrl_single_softc *sc;
+ uint32_t value;
+
+ sc = device_get_softc(syscon->pdev);
+
+ switch (sc->sc_regwidth) {
+ case 8:
+ value = bus_space_read_1(sc->sc_bst, sc->sc_bsh, offset);
+ case 16:
+ value = bus_space_read_2(sc->sc_bst, sc->sc_bsh, offset);
+ case 32:
+ value = bus_space_read_4(sc->sc_bst, sc->sc_bsh, offset);
+ }
+ DPRINTF(sc->sc_dev, "offset=%lx Read %x\n", offset, value);
+
+ return (value);
+}
+
+static syscon_method_t pinctrl_single_syscon_reg_methods[] = {
+ SYSCONMETHOD(syscon_unlocked_read_4,
+ pinctrl_single_syscon_unlocked_read_4),
+ SYSCONMETHOD(syscon_unlocked_write_4,
+ pinctrl_single_syscon_unlocked_write_4),
+
+ SYSCONMETHOD_END
+};
+
+DEFINE_CLASS_1(pinctrl_single_syscon_reg, pinctrl_single_syscon_reg_class,
+ pinctrl_single_syscon_reg_methods, 0, syscon_class);
+
+static int
+pinctrl_single_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ {
+ case PINCTRL_SINGLE:
+ device_set_desc(dev, "pinctrl-single");
+ break;
+
+ case PINCONF_SINGLE:
+ device_set_desc(dev, "pinconf-single");
+ break;
+
+ default:
+ return (ENXIO);
+ }
+
+ if (bootverbose == 0)
+ device_quiet(dev);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pinctrl_single_attach(device_t dev)
+{
+ phandle_t node;
+ int err;
+ struct pinctrl_single_softc *sc = device_get_softc(dev);
+
+ sc->sc_dev = dev;
+
+ node = ofw_bus_get_node(sc->sc_dev);
+
+ err = OF_getencprop(node, "#pinctrl-cells",
+ &sc->sc_ncells, sizeof(sc->sc_ncells));
+ if (err == -1) {
+ device_printf(sc->sc_dev, "Missing #pinctrl-cells\n");
+ return (ENXIO);
+ }
+ if (!(sc->sc_ncells == 1 || sc->sc_ncells == 2)) {
+ device_printf(sc->sc_dev, "Expect #pinctrl-cells=[1||2]\n");
+ return (ENXIO);
+ }
+
+ err = OF_getencprop(node, "pinctrl-single,register-width",
+ &sc->sc_regwidth, sizeof(sc->sc_regwidth));
+ if (err == -1) {
+ device_printf(sc->sc_dev,
+ "Missing pinctrl-single,register-width\n");
+ return (ENXIO);
+ }
+ if (!(sc->sc_regwidth == 8 ||
+ sc->sc_regwidth == 16 ||
+ sc->sc_regwidth == 32)) {
+ device_printf(sc->sc_dev,
+ "Expect pinctrl-single,register-width=[8||16|32]\n");
+ return (ENXIO);
+ }
+
+ err = OF_getencprop(node, "pinctrl-single,function-mask",
+ &sc->sc_funcmask, sizeof(sc->sc_funcmask));
+ if (err == -1) {
+ device_printf(sc->sc_dev,
+ "Missing pinctrl-single,function-mask\n");
+ return (ENXIO);
+ }
+
+
+ if (bus_alloc_resources(dev, pinctrl_single_res_spec, sc->sc_res)) {
+ device_printf(dev, "Could not allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
+
+ /* dev/syscon interface */
+ sc->sc_syscon = syscon_create_ofw_node(dev,
+ &pinctrl_single_syscon_reg_class, node);
+ if (sc->sc_syscon == NULL) {
+ device_printf(dev, "Failed to create/register syscon\n");
+ bus_release_resources(dev, pinctrl_single_res_spec,
+ sc->sc_res);
+ return (ENXIO);
+ }
+
+
+ err = fdt_pinctrl_register(sc->sc_dev, "pinctrl-single,pins");
+ if (err != 0) {
+ device_printf(sc->sc_dev,
+ "Failed to register pinctrl-single,pins\n");
+
+ syscon_unregister(sc->sc_syscon);
+ free(sc->sc_syscon, M_SYSCON);
+
+ bus_release_resources(dev, pinctrl_single_res_spec,
+ sc->sc_res);
+ return (ENXIO);
+ }
+ fdt_pinctrl_configure_tree(sc->sc_dev);
+
+ return (0);
+}
+
+static int
+pinctrl_single_detach(device_t dev)
+{
+ /* Dont allow it to detach */
+ return (EBUSY);
+}
+
+static int
+pinctrl_single_pins_configure_pins(device_t dev, phandle_t cfgxref)
+{
+ uint32_t *values;
+ uint32_t drive_strength[2];
+ uint32_t bias_pullup[4];
+ uint32_t bias_pulldown[4];
+ bool has_drive_strength = false;
+ bool has_bias_pullup = false;
+ bool has_bias_pulldown = false;
+ int nvalues, i, dI, len;
+ struct pinctrl_single_softc *sc;
+ phandle_t cfgnode;
+
+ sc = device_get_softc(dev);
+ cfgnode = OF_node_from_xref(cfgxref);
+ nvalues = OF_getencprop_alloc_multi(cfgnode, "pinctrl-single,pins",
+ sizeof(uint32_t), (void **)&values);
+
+ if (nvalues < 0)
+ return (ENOENT);
+ if (sc->sc_ncells == 1 && (nvalues % 2) != 0) {
+ device_printf(sc->sc_dev,
+ "expect pinctrl-single,pins values to be multiple of 2(%d)\n",
+ nvalues);
+ return (ENOENT);
+ }
+ else if (sc->sc_ncells == 2 && (nvalues % 3) != 0) {
+ device_printf(sc->sc_dev,
+ "expect pinctrl-single,pins values to be multiple of 3(%d)\n",
+ nvalues);
+ return (ENOENT);
+ }
+
+ if (OF_hasprop(cfgnode, "pinctrl-single,drive-strength")) {
+ len = OF_getencprop(cfgnode, "pinctrl-single,drive-strength",
+ drive_strength, sizeof(drive_strength));
+ if (len == sizeof(drive_strength))
+ has_drive_strength = true;
+ }
+
+ if (OF_hasprop(cfgnode, "pinctrl-single,bias-pullup")) {
+ len = OF_getencprop(cfgnode, "pinctrl-single,bias-pullup",
+ bias_pullup, sizeof(bias_pullup));
+ if (len == sizeof(bias_pullup))
+ has_bias_pullup = true;
+ }
+
+ if (OF_hasprop(cfgnode, "pinctrl-single,bias-pulldown")) {
+ len = OF_getencprop(cfgnode, "pinctrl-single,bias-pulldown",
+ bias_pulldown, sizeof(bias_pulldown));
+ if (len == sizeof(bias_pulldown))
+ has_bias_pulldown = true;
+ }
+
+ dI = sc->sc_ncells + 1;
+ for (i = 0; i < nvalues; i += dI) {
+ uint32_t value;
+ uint32_t offset = values[i+0];
+ uint32_t conf_value = values[i+1];
+ if (sc->sc_ncells == 2)
+ conf_value |= values[i+2];
+
+ value = pinctrl_single_syscon_unlocked_read_4(sc->sc_syscon,
+ offset);
+ value &= ~sc->sc_funcmask;
+ value |= (conf_value & sc->sc_funcmask);
+
+ if (has_drive_strength) {
+ value &= ~drive_strength[1];
+ value |= (drive_strength[0] & drive_strength[1]);
+ }
+
+ if (has_bias_pullup) {
+ value &= ~bias_pullup[3];
+ value |= (bias_pullup[0] & bias_pullup[3]);
+ }
+
+ if (has_bias_pulldown) {
+ value &= ~bias_pulldown[3];
+ value |= (bias_pulldown[0] & bias_pulldown[3]);
+ }
+
+ pinctrl_single_syscon_unlocked_write_4(sc->sc_syscon,
+ offset, value);
+ }
+
+ OF_prop_free(values);
+
+ return (0);
+}
+
+/* syscon interface */
+static int
+pinctrl_single_syscon_get_handle(device_t dev, struct syscon **syscon)
+{
+ struct pinctrl_single_softc *sc;
+
+ sc = device_get_softc(dev);
+ *syscon = sc->sc_syscon;
+ if (*syscon == NULL)
+ return (ENODEV);
+ return (0);
+}
+
+static device_method_t pinctrl_single_methods[] = {
+ DEVMETHOD(device_probe, pinctrl_single_probe),
+ DEVMETHOD(device_attach, pinctrl_single_attach),
+ DEVMETHOD(device_detach, pinctrl_single_detach),
+
+ /* fdt_pinctrl interface */
+ DEVMETHOD(fdt_pinctrl_configure, pinctrl_single_pins_configure_pins),
+
+ /* syscon interface */
+ DEVMETHOD(syscon_get_handle, pinctrl_single_syscon_get_handle),
+
+ DEVMETHOD_END
+};
+
+static driver_t pinctrl_single_driver = {
+ "pinctrl_single",
+ pinctrl_single_methods,
+ sizeof(struct pinctrl_single_softc),
+};
+
+EARLY_DRIVER_MODULE(pinctrl_single, simplebus, pinctrl_single_driver, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(pinctrl_single, 1);

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 23, 2:38 PM (17 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12551755
Default Alt Text
D46742.diff (11 KB)

Event Timeline