Date: Mon, 27 Apr 2026 15:57:59 +0000 From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 20baee6bfed2 - main - qcom_tlmm: prepare for supporting multiple TLMM platforms Message-ID: <69ef8787.42a48.26bf9566@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=20baee6bfed2f39008955dce1f0ce31eb10805f3 commit 20baee6bfed2f39008955dce1f0ce31eb10805f3 Author: Adrian Chadd <adrian@FreeBSD.org> AuthorDate: 2025-02-10 00:49:45 +0000 Commit: Adrian Chadd <adrian@FreeBSD.org> CommitDate: 2026-04-27 15:57:44 +0000 qcom_tlmm: prepare for supporting multiple TLMM platforms * Create a set of callbacks implementing the hardware specific GPIO bus operations * Migrate the IPQ4018 TLMM setup code into qcom_tlmm_ip4018.c Differential Revision: https://reviews.freebsd.org/D56349 --- sys/arm/conf/std.qca | 2 +- sys/arm/qualcomm/std.ipq4018 | 11 +- sys/arm64/conf/std.qcom | 3 + sys/conf/files.arm64 | 6 + sys/dev/qcom_tlmm/qcom_tlmm.c | 237 ++++++++++++++++++++++++++++++++++ sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c | 166 ++++-------------------- sys/dev/qcom_tlmm/qcom_tlmm_pin.c | 24 ++-- sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c | 28 ++-- sys/dev/qcom_tlmm/qcom_tlmm_var.h | 47 +++++++ 9 files changed, 350 insertions(+), 174 deletions(-) diff --git a/sys/arm/conf/std.qca b/sys/arm/conf/std.qca index ea6912606517..454b99e5b1b1 100644 --- a/sys/arm/conf/std.qca +++ b/sys/arm/conf/std.qca @@ -50,7 +50,7 @@ device qcom_gcc # TLMM (gpio/pinmux) device gpio -device qcom_tlmm_ipq4018 +device qcom_tlmm device fdt_pinctrl # TCSR (core top control and status registers) diff --git a/sys/arm/qualcomm/std.ipq4018 b/sys/arm/qualcomm/std.ipq4018 index 1c70ecc448bd..fef633576e95 100644 --- a/sys/arm/qualcomm/std.ipq4018 +++ b/sys/arm/qualcomm/std.ipq4018 @@ -50,11 +50,12 @@ dev/qcom_clk/qcom_clk_rcg2.c optional qcom_gcc dev/qcom_clk/qcom_clk_branch2.c optional qcom_gcc dev/qcom_clk/qcom_clk_ro_div.c optional qcom_gcc -dev/qcom_tlmm/qcom_tlmm_debug.c optional qcom_tlmm_ipq4018 -dev/qcom_tlmm/qcom_tlmm_ipq4018.c optional qcom_tlmm_ipq4018 -dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c optional qcom_tlmm_ipq4018 -dev/qcom_tlmm/qcom_tlmm_pin.c optional qcom_tlmm_ipq4018 -dev/qcom_tlmm/qcom_tlmm_pinmux.c optional qcom_tlmm_ipq4018 +dev/qcom_tlmm/qcom_tlmm_debug.c optional qcom_tlmm +dev/qcom_tlmm/qcom_tlmm_ipq4018.c optional qcom_tlmm +dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c optional qcom_tlmm +dev/qcom_tlmm/qcom_tlmm_pin.c optional qcom_tlmm +dev/qcom_tlmm/qcom_tlmm_pinmux.c optional qcom_tlmm +dev/qcom_tlmm/qcom_tlmm.c optional qcom_tlmm dev/qcom_tcsr/qcom_tcsr.c optional qcom_tcsr diff --git a/sys/arm64/conf/std.qcom b/sys/arm64/conf/std.qcom index 4051df46bf49..3b11523a3474 100644 --- a/sys/arm64/conf/std.qcom +++ b/sys/arm64/conf/std.qcom @@ -9,6 +9,9 @@ device qcom_mdio # MDIO support # Serial (COM) ports device uart_msm # Qualcomm MSM UART driver +# TLMM driver +device qcom_tlmm + # MMC/SD/SDIO Card slot support device sdhci diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 5d1b6e164a51..44f292d9048f 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -783,6 +783,12 @@ dev/qcom_clk/qcom_clk_rcg2.c optional qcom_gcc fdt dev/qcom_clk/qcom_clk_branch2.c optional qcom_gcc fdt dev/qcom_clk/qcom_clk_ro_div.c optional qcom_gcc fdt dev/qcom_mdio/qcom_mdio_ipq4018.c optional qcom_mdio fdt mdio mii +dev/qcom_tlmm/qcom_tlmm_debug.c optional qcom_tlmm gpio +dev/qcom_tlmm/qcom_tlmm_pin.c optional qcom_tlmm gpio +dev/qcom_tlmm/qcom_tlmm_pinmux.c optional qcom_tlmm gpio +dev/qcom_tlmm/qcom_tlmm.c optional qcom_tlmm gpio +dev/qcom_tlmm/qcom_tlmm_ipq4018.c optional qcom_tlmm gpio +dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c optional qcom_tlmm gpio # RockChip Drivers arm64/rockchip/rk3328_codec.c optional fdt rk3328codec soc_rockchip_rk3328 diff --git a/sys/dev/qcom_tlmm/qcom_tlmm.c b/sys/dev/qcom_tlmm/qcom_tlmm.c new file mode 100644 index 000000000000..3581e651fd59 --- /dev/null +++ b/sys/dev/qcom_tlmm/qcom_tlmm.c @@ -0,0 +1,237 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd <adrian@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 unmodified, 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. + */ + +/* + * This is a pinmux/gpio controller for the Qualcomm IPQ/MSM/Snapdragon SoCs. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/gpio.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <dev/gpio/gpiobusvar.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/fdt/fdt_pinctrl.h> + +#include "qcom_tlmm_var.h" +#include "qcom_tlmm_pin.h" +#include "qcom_tlmm_debug.h" + +#include "gpio_if.h" + +#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ + GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) + +/* TODO: put in a header file */ +extern void qcom_tlmm_ipq4018_attach(struct qcom_tlmm_softc *sc); + +struct qcom_tlmm_chipset_list { + qcom_tlmm_chipset_t id; + const char *ofw_str; + const char *desc_str; + void (*attach_func)(struct qcom_tlmm_softc *); +}; + +static struct qcom_tlmm_chipset_list qcom_tlmm_chipsets[] = { + { QCOM_TLMM_CHIPSET_IPQ4018, "qcom,ipq4019-pinctrl", + "Qualcomm Atheros TLMM IPQ4018/IPQ4019 GPIO/Pinmux driver", + qcom_tlmm_ipq4018_attach }, + { 0, NULL, NULL, NULL }, +}; + +static int +qcom_tlmm_probe(device_t dev) +{ + struct qcom_tlmm_softc *sc = device_get_softc(dev); + struct qcom_tlmm_chipset_list *ql; + int i; + + if (! ofw_bus_status_okay(dev)) + return (ENXIO); + + for (i = 0; qcom_tlmm_chipsets[i].id != 0; i++) { + ql = &qcom_tlmm_chipsets[i]; + device_printf(dev, "%s: checking %s\n", __func__, ql->ofw_str); + if (ofw_bus_is_compatible(dev, ql->ofw_str) == 1) { + sc->sc_chipset = ql->id; + sc->sc_attach_func = ql->attach_func; + device_set_desc(dev, ql->desc_str); + return (0); + } + } + + return (ENXIO); +} + +static int +qcom_tlmm_detach(device_t dev) +{ + struct qcom_tlmm_softc *sc = device_get_softc(dev); + + KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); + + gpiobus_detach_bus(dev); + if (sc->gpio_ih) + bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih); + if (sc->gpio_irq_res) + bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid, + sc->gpio_irq_res); + if (sc->gpio_mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, + sc->gpio_mem_res); + if (sc->gpio_pins) + free(sc->gpio_pins, M_DEVBUF); + mtx_destroy(&sc->gpio_mtx); + + return(0); +} + +static int +qcom_tlmm_attach(device_t dev) +{ + struct qcom_tlmm_softc *sc = device_get_softc(dev); + int i; + + KASSERT((device_get_unit(dev) == 0), + ("qcom_tlmm: Only one gpio module supported")); + + mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + /* Map control/status registers. */ + sc->gpio_mem_rid = 0; + sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->gpio_mem_rid, RF_ACTIVE); + + if (sc->gpio_mem_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + qcom_tlmm_detach(dev); + return (ENXIO); + } + + if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "unable to allocate IRQ resource\n"); + qcom_tlmm_detach(dev); + return (ENXIO); + } + + if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, + qcom_tlmm_filter, qcom_tlmm_intr, sc, &sc->gpio_ih))) { + device_printf(dev, + "WARNING: unable to register interrupt handler\n"); + qcom_tlmm_detach(dev); + return (ENXIO); + } + + sc->dev = dev; + sc->sc_debug = 0; + + /* Call platform specific attach function */ + sc->sc_attach_func(sc); + + qcom_tlmm_debug_sysctl_attach(sc); + + /* Allocate local pin state for all of our pins */ + sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins, + M_DEVBUF, M_WAITOK | M_ZERO); + + /* Note: direct map between gpio pin and gpio_pin[] entry */ + for (i = 0; i < sc->gpio_npins; i++) { + snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, + "gpio%d", i); + sc->gpio_pins[i].gp_pin = i; + sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; + (void) qcom_tlmm_pin_getflags(dev, i, + &sc->gpio_pins[i].gp_flags); + } + + fdt_pinctrl_register(dev, NULL); + fdt_pinctrl_configure_by_name(dev, "default"); + + sc->busdev = gpiobus_add_bus(dev); + if (sc->busdev == NULL) { + device_printf(dev, "%s: failed to attach bus\n", __func__); + qcom_tlmm_detach(dev); + return (ENXIO); + } + bus_attach_children(dev); + + return (0); +} + +static device_method_t qcom_tlmm_methods[] = { + /* Driver */ + DEVMETHOD(device_probe, qcom_tlmm_probe), + DEVMETHOD(device_attach, qcom_tlmm_attach), + DEVMETHOD(device_detach, qcom_tlmm_detach), + + /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, qcom_tlmm_get_bus), + DEVMETHOD(gpio_pin_max, qcom_tlmm_pin_max), + DEVMETHOD(gpio_pin_getname, qcom_tlmm_pin_getname), + DEVMETHOD(gpio_pin_getflags, qcom_tlmm_pin_getflags), + DEVMETHOD(gpio_pin_getcaps, qcom_tlmm_pin_getcaps), + DEVMETHOD(gpio_pin_setflags, qcom_tlmm_pin_setflags), + DEVMETHOD(gpio_pin_get, qcom_tlmm_pin_get), + DEVMETHOD(gpio_pin_set, qcom_tlmm_pin_set), + DEVMETHOD(gpio_pin_toggle, qcom_tlmm_pin_toggle), + + /* OFW */ + DEVMETHOD(ofw_bus_get_node, qcom_tlmm_pin_get_node), + + /* fdt_pinctrl interface */ + DEVMETHOD(fdt_pinctrl_configure, qcom_tlmm_pinctrl_configure), + + {0, 0}, +}; + +static driver_t qcom_tlmm_driver = { + "gpio", + qcom_tlmm_methods, + sizeof(struct qcom_tlmm_softc), +}; + +EARLY_DRIVER_MODULE(qcom_tlmm, simplebus, qcom_tlmm_driver, + NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); +EARLY_DRIVER_MODULE(qcom_tlmm, ofwbus, qcom_tlmm_driver, + NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); +MODULE_VERSION(qcom_tlmm, 1); diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c index 50f54b896748..f6f00bdb1e1f 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c @@ -245,152 +245,34 @@ static const struct qcom_tlmm_gpio_mux gpio_muxes[] = { GDEF(-1), }; -static int -qcom_tlmm_ipq4018_probe(device_t dev) -{ - - if (! ofw_bus_status_okay(dev)) - return (ENXIO); - - if (ofw_bus_is_compatible(dev, "qcom,ipq4019-pinctrl") == 0) - return (ENXIO); - - device_set_desc(dev, - "Qualcomm Atheross TLMM IPQ4018/IPQ4019 GPIO/Pinmux driver"); - return (0); -} - -static int -qcom_tlmm_ipq4018_detach(device_t dev) -{ - struct qcom_tlmm_softc *sc = device_get_softc(dev); - - KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); - - gpiobus_detach_bus(dev); - if (sc->gpio_ih) - bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih); - if (sc->gpio_irq_res) - bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid, - sc->gpio_irq_res); - if (sc->gpio_mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, - sc->gpio_mem_res); - if (sc->gpio_pins) - free(sc->gpio_pins, M_DEVBUF); - mtx_destroy(&sc->gpio_mtx); - - return(0); -} - +static struct qcom_tlmm_hw_callbacks qcom_tlmm_ipq4018_hw_callbacks = { + .qcom_tlmm_hw_pin_set_function = qcom_tlmm_ipq4018_hw_pin_set_function, + .qcom_tlmm_hw_pin_get_function = qcom_tlmm_ipq4018_hw_pin_get_function, + .qcom_tlmm_hw_pin_set_oe_output = qcom_tlmm_ipq4018_hw_pin_set_oe_output, + .qcom_tlmm_hw_pin_set_oe_input = qcom_tlmm_ipq4018_hw_pin_set_oe_input, + .qcom_tlmm_hw_pin_get_oe_state = qcom_tlmm_ipq4018_hw_pin_get_oe_state, + .qcom_tlmm_hw_pin_set_output_value = qcom_tlmm_ipq4018_hw_pin_set_output_value, + .qcom_tlmm_hw_pin_get_output_value = qcom_tlmm_ipq4018_hw_pin_get_output_value, + .qcom_tlmm_hw_pin_get_input_value = qcom_tlmm_ipq4018_hw_pin_get_input_value, + .qcom_tlmm_hw_pin_toggle_output_value = qcom_tlmm_ipq4018_hw_pin_toggle_output_value, + .qcom_tlmm_hw_pin_set_pupd_config = qcom_tlmm_ipq4018_hw_pin_set_pupd_config, + .qcom_tlmm_hw_pin_get_pupd_config = qcom_tlmm_ipq4018_hw_pin_get_pupd_config, + .qcom_tlmm_hw_pin_set_drive_strength = qcom_tlmm_ipq4018_hw_pin_set_drive_strength, + .qcom_tlmm_hw_pin_get_drive_strength = qcom_tlmm_ipq4018_hw_pin_get_drive_strength, + .qcom_tlmm_hw_pin_set_vm = qcom_tlmm_ipq4018_hw_pin_set_vm, + .qcom_tlmm_hw_pin_get_vm = qcom_tlmm_ipq4018_hw_pin_get_vm, + .qcom_tlmm_hw_pin_set_open_drain = qcom_tlmm_ipq4018_hw_pin_set_open_drain, + .qcom_tlmm_hw_pin_get_open_drain = qcom_tlmm_ipq4018_hw_pin_get_open_drain, +}; +/* TODO: move to a header file */ +extern void qcom_tlmm_ipq4018_attach(struct qcom_tlmm_softc *sc); -static int -qcom_tlmm_ipq4018_attach(device_t dev) +void +qcom_tlmm_ipq4018_attach(struct qcom_tlmm_softc *sc) { - struct qcom_tlmm_softc *sc = device_get_softc(dev); - int i; - - KASSERT((device_get_unit(dev) == 0), - ("qcom_tlmm_ipq4018: Only one gpio module supported")); - - mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); - - /* Map control/status registers. */ - sc->gpio_mem_rid = 0; - sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->gpio_mem_rid, RF_ACTIVE); - - if (sc->gpio_mem_res == NULL) { - device_printf(dev, "couldn't map memory\n"); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { - device_printf(dev, "unable to allocate IRQ resource\n"); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - - if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, - qcom_tlmm_filter, qcom_tlmm_intr, sc, &sc->gpio_ih))) { - device_printf(dev, - "WARNING: unable to register interrupt handler\n"); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - - sc->dev = dev; sc->gpio_npins = QCOM_TLMM_IPQ4018_GPIO_PINS; sc->gpio_muxes = &gpio_muxes[0]; - sc->sc_debug = 0; - - qcom_tlmm_debug_sysctl_attach(sc); - - /* Allocate local pin state for all of our pins */ - sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins, - M_DEVBUF, M_WAITOK | M_ZERO); - - /* Note: direct map between gpio pin and gpio_pin[] entry */ - for (i = 0; i < sc->gpio_npins; i++) { - snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, - "gpio%d", i); - sc->gpio_pins[i].gp_pin = i; - sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; - (void) qcom_tlmm_pin_getflags(dev, i, - &sc->gpio_pins[i].gp_flags); - } - - fdt_pinctrl_register(dev, NULL); - fdt_pinctrl_configure_by_name(dev, "default"); - - sc->busdev = gpiobus_add_bus(dev); - if (sc->busdev == NULL) { - device_printf(dev, "%s: failed to attach bus\n", __func__); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - - bus_attach_children(dev); - return (0); + sc->sc_hw = &qcom_tlmm_ipq4018_hw_callbacks; } - -static device_method_t qcom_tlmm_ipq4018_methods[] = { - /* Driver */ - DEVMETHOD(device_probe, qcom_tlmm_ipq4018_probe), - DEVMETHOD(device_attach, qcom_tlmm_ipq4018_attach), - DEVMETHOD(device_detach, qcom_tlmm_ipq4018_detach), - - /* GPIO protocol */ - DEVMETHOD(gpio_get_bus, qcom_tlmm_get_bus), - DEVMETHOD(gpio_pin_max, qcom_tlmm_pin_max), - DEVMETHOD(gpio_pin_getname, qcom_tlmm_pin_getname), - DEVMETHOD(gpio_pin_getflags, qcom_tlmm_pin_getflags), - DEVMETHOD(gpio_pin_getcaps, qcom_tlmm_pin_getcaps), - DEVMETHOD(gpio_pin_setflags, qcom_tlmm_pin_setflags), - DEVMETHOD(gpio_pin_get, qcom_tlmm_pin_get), - DEVMETHOD(gpio_pin_set, qcom_tlmm_pin_set), - DEVMETHOD(gpio_pin_toggle, qcom_tlmm_pin_toggle), - - /* OFW */ - DEVMETHOD(ofw_bus_get_node, qcom_tlmm_pin_get_node), - - /* fdt_pinctrl interface */ - DEVMETHOD(fdt_pinctrl_configure, qcom_tlmm_pinctrl_configure), - - {0, 0}, -}; - -static driver_t qcom_tlmm_ipq4018_driver = { - "gpio", - qcom_tlmm_ipq4018_methods, - sizeof(struct qcom_tlmm_softc), -}; - -EARLY_DRIVER_MODULE(qcom_tlmm_ipq4018, simplebus, qcom_tlmm_ipq4018_driver, - NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); -EARLY_DRIVER_MODULE(qcom_tlmm_ipq4018, ofwbus, qcom_tlmm_ipq4018_driver, - NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); -MODULE_VERSION(qcom_tlmm_ipq4018, 1); diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_pin.c b/sys/dev/qcom_tlmm/qcom_tlmm_pin.c index be7b37f21156..27d6f904d664 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_pin.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_pin.c @@ -85,11 +85,11 @@ qcom_tlmm_pin_configure(struct qcom_tlmm_softc *sc, * pin value before we flip on oe_output. */ pin->gp_flags |= GPIO_PIN_OUTPUT; - qcom_tlmm_ipq4018_hw_pin_set_oe_output(sc, + sc->sc_hw->qcom_tlmm_hw_pin_set_oe_output(sc, pin->gp_pin); } else { pin->gp_flags |= GPIO_PIN_INPUT; - qcom_tlmm_ipq4018_hw_pin_set_oe_input(sc, + sc->sc_hw->qcom_tlmm_hw_pin_set_oe_input(sc, pin->gp_pin); } } @@ -99,20 +99,20 @@ qcom_tlmm_pin_configure(struct qcom_tlmm_softc *sc, */ if (flags & GPIO_PIN_PULLUP) { pin->gp_flags |= GPIO_PIN_PULLUP; - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP); } else if (flags & GPIO_PIN_PULLDOWN) { pin->gp_flags |= GPIO_PIN_PULLDOWN; - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_DOWN); } else if ((flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) == (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) { pin->gp_flags |= GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN; - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_BUS_HOLD); } else { pin->gp_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_DISABLE); } } @@ -169,12 +169,12 @@ qcom_tlmm_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) GPIO_LOCK(sc); /* Lookup function - see what it is, whether we're a GPIO line */ - ret = qcom_tlmm_ipq4018_hw_pin_get_function(sc, pin, &val); + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_function(sc, pin, &val); if (ret != 0) goto done; /* Lookup input/output state */ - ret = qcom_tlmm_ipq4018_hw_pin_get_oe_state(sc, pin, &is_output); + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_oe_state(sc, pin, &is_output); if (ret != 0) goto done; if (is_output) @@ -183,7 +183,7 @@ qcom_tlmm_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) *flags |= GPIO_PIN_INPUT; /* Lookup pull-up / pull-down state */ - ret = qcom_tlmm_ipq4018_hw_pin_get_pupd_config(sc, pin, + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_pupd_config(sc, pin, &pupd_config); if (ret != 0) goto done; @@ -251,7 +251,7 @@ qcom_tlmm_pin_set(device_t dev, uint32_t pin, unsigned int value) return (EINVAL); GPIO_LOCK(sc); - ret = qcom_tlmm_ipq4018_hw_pin_set_output_value(sc, pin, value); + ret = sc->sc_hw->qcom_tlmm_hw_pin_set_output_value(sc, pin, value); GPIO_UNLOCK(sc); return (ret); @@ -267,7 +267,7 @@ qcom_tlmm_pin_get(device_t dev, uint32_t pin, unsigned int *val) return (EINVAL); GPIO_LOCK(sc); - ret = qcom_tlmm_ipq4018_hw_pin_get_input_value(sc, pin, val); + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_input_value(sc, pin, val); GPIO_UNLOCK(sc); return (ret); @@ -283,7 +283,7 @@ qcom_tlmm_pin_toggle(device_t dev, uint32_t pin) return (EINVAL); GPIO_LOCK(sc); - ret = qcom_tlmm_ipq4018_hw_pin_toggle_output_value(sc, pin); + ret = sc->sc_hw->qcom_tlmm_hw_pin_toggle_output_value(sc, pin); GPIO_UNLOCK(sc); return (ret); diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c b/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c index a4b4dffa3dbb..59e97dfe7602 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c @@ -238,7 +238,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, __func__, gmux->id, tmp); - err = qcom_tlmm_ipq4018_hw_pin_set_function(sc, gmux->id, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_function(sc, gmux->id, tmp); if (err != 0) { device_printf(sc->dev, @@ -263,7 +263,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, cfg->params[i]); switch (i) { case PIN_ID_BIAS_DISABLE: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_DISABLE); if (err != 0) { device_printf(sc->dev, @@ -274,7 +274,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_BIAS_PULL_DOWN: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_DOWN); if (err != 0) { device_printf(sc->dev, @@ -285,7 +285,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_BIAS_BUS_HOLD: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_BUS_HOLD); if (err != 0) { device_printf(sc->dev, @@ -297,7 +297,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, break; case PIN_ID_BIAS_PULL_UP: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP); if (err != 0) { device_printf(sc->dev, @@ -308,7 +308,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_OUTPUT_LOW: - err = qcom_tlmm_ipq4018_hw_pin_set_oe_output(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_oe_output(sc, gmux->id); if (err != 0) { device_printf(sc->dev, @@ -317,7 +317,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, __func__, gmux->id, err); goto done; } - err = qcom_tlmm_ipq4018_hw_pin_set_output_value( + err = sc->sc_hw->qcom_tlmm_hw_pin_set_output_value( sc, gmux->id, 0); if (err != 0) { device_printf(sc->dev, @@ -328,7 +328,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_OUTPUT_HIGH: - err = qcom_tlmm_ipq4018_hw_pin_set_oe_output(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_oe_output(sc, gmux->id); if (err != 0) { device_printf(sc->dev, @@ -337,7 +337,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, __func__, gmux->id, err); goto done; } - err = qcom_tlmm_ipq4018_hw_pin_set_output_value( + err = sc->sc_hw->qcom_tlmm_hw_pin_set_output_value( sc, gmux->id, 1); if (err != 0) { device_printf(sc->dev, @@ -348,7 +348,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_DRIVE_STRENGTH: - err = qcom_tlmm_ipq4018_hw_pin_set_drive_strength(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_drive_strength(sc, gmux->id, cfg->params[i]); if (err != 0) { device_printf(sc->dev, @@ -360,7 +360,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_VM_ENABLE: - err = qcom_tlmm_ipq4018_hw_pin_set_vm(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_vm(sc, gmux->id, true); if (err != 0) { device_printf(sc->dev, @@ -371,7 +371,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_VM_DISABLE: - err = qcom_tlmm_ipq4018_hw_pin_set_vm(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_vm(sc, gmux->id, false); if (err != 0) { device_printf(sc->dev, @@ -382,7 +382,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_DRIVE_OPEN_DRAIN: - err = qcom_tlmm_ipq4018_hw_pin_set_open_drain(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_open_drain(sc, gmux->id, true); if (err != 0) { device_printf(sc->dev, @@ -394,7 +394,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, break; case PIN_ID_INPUT_ENABLE: /* Configure pin as an input */ - err = qcom_tlmm_ipq4018_hw_pin_set_oe_input(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_oe_input(sc, gmux->id); if (err != 0) { device_printf(sc->dev, diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_var.h b/sys/dev/qcom_tlmm/qcom_tlmm_var.h index 1fea18275397..4fd37f83192e 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_var.h +++ b/sys/dev/qcom_tlmm/qcom_tlmm_var.h @@ -49,6 +49,10 @@ #define GPIO_CLEAR_BITS(sc, reg, bits) \ GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) & ~(bits)) +typedef enum { + QCOM_TLMM_CHIPSET_NONE = 0, + QCOM_TLMM_CHIPSET_IPQ4018 = 1, +} qcom_tlmm_chipset_t; enum prop_id { PIN_ID_BIAS_DISABLE = 0, @@ -141,6 +145,45 @@ struct qcom_tlmm_spec_pin { uint32_t hdrv_shift; }; +struct qcom_tlmm_softc; + +struct qcom_tlmm_hw_callbacks { + int (*qcom_tlmm_hw_pin_set_function)(struct qcom_tlmm_softc *, + int, int); + int (*qcom_tlmm_hw_pin_get_function)(struct qcom_tlmm_softc *, + int, int *); + int (*qcom_tlmm_hw_pin_set_oe_output)(struct qcom_tlmm_softc *, + int); + int (*qcom_tlmm_hw_pin_set_oe_input)(struct qcom_tlmm_softc *, + int); + int (*qcom_tlmm_hw_pin_get_oe_state)(struct qcom_tlmm_softc *, + int, bool *); + int (*qcom_tlmm_hw_pin_set_output_value)(struct qcom_tlmm_softc *, + uint32_t, unsigned int); + int (*qcom_tlmm_hw_pin_get_output_value)(struct qcom_tlmm_softc *, + uint32_t, unsigned int *); + int (*qcom_tlmm_hw_pin_get_input_value)(struct qcom_tlmm_softc *, + uint32_t, unsigned int *); + int (*qcom_tlmm_hw_pin_toggle_output_value)(struct qcom_tlmm_softc *, + uint32_t); + int (*qcom_tlmm_hw_pin_set_pupd_config)(struct qcom_tlmm_softc *, + uint32_t, qcom_tlmm_pin_pupd_config_t); + int (*qcom_tlmm_hw_pin_get_pupd_config)(struct qcom_tlmm_softc *, + uint32_t, qcom_tlmm_pin_pupd_config_t *); + int (*qcom_tlmm_hw_pin_set_drive_strength)(struct qcom_tlmm_softc *, + uint32_t, uint8_t); + int (*qcom_tlmm_hw_pin_get_drive_strength)(struct qcom_tlmm_softc *, + uint32_t, uint8_t *); + int (*qcom_tlmm_hw_pin_set_vm)(struct qcom_tlmm_softc *, + uint32_t, bool); + int (*qcom_tlmm_hw_pin_get_vm)(struct qcom_tlmm_softc *, + uint32_t, bool *); + int (*qcom_tlmm_hw_pin_set_open_drain)(struct qcom_tlmm_softc *, + uint32_t, bool); + int (*qcom_tlmm_hw_pin_get_open_drain)(struct qcom_tlmm_softc *, + uint32_t, bool *); +}; + struct qcom_tlmm_softc { device_t dev; device_t busdev; @@ -153,6 +196,10 @@ struct qcom_tlmm_softc { int gpio_npins; struct gpio_pin *gpio_pins; uint32_t sc_debug; + qcom_tlmm_chipset_t sc_chipset; + void (*sc_attach_func)(struct qcom_tlmm_softc *); + + struct qcom_tlmm_hw_callbacks *sc_hw; const struct qcom_tlmm_gpio_mux *gpio_muxes; const struct qcom_tlmm_spec_pin *spec_pins;home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69ef8787.42a48.26bf9566>
