From: kettenis Date: Sun, 26 Aug 2018 19:50:08 +0000 (+0000) Subject: Add pinctrl(4), a generic pin mux driver. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=fc8968b8613d7c187ae041f19a199826ee2299f9;p=openbsd Add pinctrl(4), a generic pin mux driver. ok patrick@ --- diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC index f16dda3c4a1..b06c5b1012a 100644 --- a/sys/arch/arm64/conf/GENERIC +++ b/sys/arch/arm64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.84 2018/08/26 16:52:16 kettenis Exp $ +# $OpenBSD: GENERIC,v 1.85 2018/08/26 19:50:08 kettenis Exp $ # # GENERIC machine description file # @@ -78,6 +78,7 @@ ccp* at fdt? # AMD Cryptographic Co-processor com* at fdt? # Generic devices +pinctrl* at fdt? early 1 plgpio* at fdt? early 1 plrtc* at fdt? pluart* at fdt? diff --git a/sys/arch/arm64/conf/RAMDISK b/sys/arch/arm64/conf/RAMDISK index 35fe7b2f1e6..f018b43fee9 100644 --- a/sys/arch/arm64/conf/RAMDISK +++ b/sys/arch/arm64/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.68 2018/08/26 16:52:16 kettenis Exp $ +# $OpenBSD: RAMDISK,v 1.69 2018/08/26 19:50:08 kettenis Exp $ # # GENERIC machine description file # @@ -87,6 +87,7 @@ xhci* at fdt? com* at fdt? # Generic devices +pinctrl* at fdt? early 1 plgpio* at fdt? early 1 plrtc* at fdt? pluart* at fdt? diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt index b7fc3dcbfaa..985d86bf2f7 100644 --- a/sys/dev/fdt/files.fdt +++ b/sys/dev/fdt/files.fdt @@ -1,8 +1,12 @@ -# $OpenBSD: files.fdt,v 1.69 2018/08/26 16:52:16 kettenis Exp $ +# $OpenBSD: files.fdt,v 1.70 2018/08/26 19:50:08 kettenis Exp $ # # Config file and device description for machine-independent FDT code. # Included by ports that need it. +device pinctrl +attach pinctrl at fdt +file dev/fdt/pinctrl.c pinctrl + device simplefb: wsemuldisplaydev, rasops15, rasops16, rasops24, rasops32 attach simplefb at fdt file dev/fdt/simplefb.c simplefb diff --git a/sys/dev/fdt/pinctrl.c b/sys/dev/fdt/pinctrl.c new file mode 100644 index 00000000000..9b6bef39b99 --- /dev/null +++ b/sys/dev/fdt/pinctrl.c @@ -0,0 +1,139 @@ +/* $OpenBSD: pinctrl.c,v 1.1 2018/08/26 19:50:08 kettenis Exp $ */ +/* + * Copyright (c) 2018 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) + +struct pinctrl_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + uint32_t sc_reg_width; + uint32_t sc_func_mask; +}; + +int pinctrl_match(struct device *, void *, void *); +void pinctrl_attach(struct device *, struct device *, void *); + +struct cfattach pinctrl_ca = { + sizeof (struct pinctrl_softc), pinctrl_match, pinctrl_attach +}; + +struct cfdriver pinctrl_cd = { + NULL, "pinctrl", DV_DULL +}; + +int pinctrl_pinctrl(uint32_t, void *); + +int +pinctrl_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "pinctrl-single"); +} + +void +pinctrl_attach(struct device *parent, struct device *self, void *aux) +{ + struct pinctrl_softc *sc = (struct pinctrl_softc *)self; + struct fdt_attach_args *faa = aux; + + if (faa->fa_nreg < 1) { + printf(": no registers\n"); + return; + } + + sc->sc_reg_width = OF_getpropint(faa->fa_node, + "pinctrl-single,register-width", 0); + if (sc->sc_reg_width != 32) { + printf(": unsupported register width\n"); + return; + } + + sc->sc_func_mask = OF_getpropint(faa->fa_node, + "pinctrl-single,function-mask", 0); + if (sc->sc_func_mask == 0) { + printf(": bogus function mask\n"); + return; + } + + sc->sc_iot = faa->fa_iot; + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + + pinctrl_register(faa->fa_node, pinctrl_pinctrl, sc); + + printf("\n"); +} + +int +pinctrl_pinctrl(uint32_t phandle, void *cookie) +{ + struct pinctrl_softc *sc = cookie; + uint32_t *pins; + int node, len, i; + + node = OF_getnodebyphandle(phandle); + if (node == 0) + return -1; + + len = OF_getproplen(node, "pinctrl-single,pins"); + if (len <= 0) + return -1; + + pins = malloc(len, M_TEMP, M_WAITOK); + OF_getpropintarray(node, "pinctrl-single,pins", pins, len); + + for (i = 0; i < len / sizeof(uint32_t); i += 2) { + uint32_t reg = pins[i]; + uint32_t func = pins[i + 1]; + uint32_t val; + + switch (sc->sc_reg_width) { + case 32: + val = HREAD4(sc, reg); + val &= ~sc->sc_func_mask; + val |= (func & sc->sc_func_mask); + HWRITE4(sc, reg, val); + break; + } + } + + free(pins, M_TEMP, len); + return 0; +}