Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111493623
D46742.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D46742.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 5, 11:31 AM (14 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16974265
Default Alt Text
D46742.diff (11 KB)
Attached To
Mode
D46742: Add pinctrl_single driver
Attached
Detach File
Event Timeline
Log In to Comment