Add pinctrl driver for AON domain. Signed-off-by: Alex Soo <yuklin.soo@xxxxxxxxxxxxxxxx> Reviewed-by: Ley Foon Tan <leyfoon.tan@xxxxxxxxxxxxxxxx> --- MAINTAINERS | 7 + drivers/pinctrl/starfive/Kconfig | 12 + drivers/pinctrl/starfive/Makefile | 1 + .../starfive/pinctrl-starfive-jh8100-aon.c | 241 ++++++++++++++++++ .../starfive/pinctrl-starfive-jh8100.h | 2 + 5 files changed, 263 insertions(+) create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c diff --git a/MAINTAINERS b/MAINTAINERS index 53084079f5f5..451ee21086a7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20776,6 +20776,13 @@ S: Maintained F: drivers/reset/starfive/reset-starfive-jh81* F: include/dt-bindings/reset/starfive?jh81*.h +STARFIVE JH8100 PINCTRL DRIVERS +M: Alex Soo <yuklin.soo@xxxxxxxxxxxxxxxx> +S: Supported +F: Documentation/devicetree/bindings/pinctrl/starfive,jh81*.yaml +F: drivers/pinctrl/starfive/pinctrl-starfive-jh81* +F: include/dt-bindings/pinctrl/starfive,jh8100-pinctrl.h + STATIC BRANCH/CALL M: Peter Zijlstra <peterz@xxxxxxxxxxxxx> M: Josh Poimboeuf <jpoimboe@xxxxxxxxxx> diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig index bb1fb3788d5b..4d62d7199f5d 100644 --- a/drivers/pinctrl/starfive/Kconfig +++ b/drivers/pinctrl/starfive/Kconfig @@ -94,3 +94,15 @@ config PINCTRL_STARFIVE_JH8100_SYS_GMAC This also provides a syscon interface to configure the GMAC1 voltage level for RGMII(1.8V 2.5V), GMII(2.5V/3.3V), to configure the SDIO1 voltage level to support the 3.3/1.8V voltage switching in high-speed mode, and configure the GMAC1 network interface and timing (slew rate). + +config PINCTRL_STARFIVE_JH8100_AON + tristate "Always-on pinctrl and GPIO driver for the StarFive JH8100 SoC" + depends on ARCH_STARFIVE || COMPILE_TEST + depends on OF + select PINCTRL_STARFIVE_JH8100 + default ARCH_STARFIVE + help + Say yes here to support always-on pin control on the StarFive JH8100 SoC. + This also provides a syscon interface to configure the GMAC0 voltage level for RGMII(1.8V + 2.5V), GMII(2.5V/3.3V), to configure the SDIO0 voltage level to support the 3.3/1.8V voltage + switching in high-speed mode, and configure the GMAC0 network interface and timing (slew rate). diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile index 236a693a8aef..46b1ab97779b 100644 --- a/drivers/pinctrl/starfive/Makefile +++ b/drivers/pinctrl/starfive/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH8100) += pinctrl-starfive-jh8100.o obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_EAST) += pinctrl-starfive-jh8100-sys-east.o obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_WEST) += pinctrl-starfive-jh8100-sys-west.o obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_SYS_GMAC) += pinctrl-starfive-jh8100-sys-gmac.o +obj-$(CONFIG_PINCTRL_STARFIVE_JH8100_AON) += pinctrl-starfive-jh8100-aon.o diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c new file mode 100644 index 000000000000..fc478bc0e0b2 --- /dev/null +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100-aon.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Pinctrl / GPIO driver for StarFive JH8100 SoC aon controller + * + * Copyright (C) 2023 StarFive Technology Co., Ltd. + * Author: Alex Soo <yuklin.soo@xxxxxxxxxxxxxxxx> + * + */ + +#include <linux/bits.h> +#include <linux/err.h> +#include <linux/gpio/driver.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinmux.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/slab.h> + +#include <dt-bindings/pinctrl/starfive,jh8100-pinctrl.h> + +#include "../core.h" +#include "../pinconf.h" +#include "../pinmux.h" +#include "pinctrl-starfive-jh8100.h" + +#define JH8100_AON_NGPIO 16 +#define JH8100_AON_GC_BASE 64 + +/* registers */ +#define JH8100_AON_DOEN 0x00 +#define JH8100_AON_DOUT 0x10 +#define JH8100_AON_GPI 0x20 +#define JH8100_AON_GPIOIN 0x54 + +#define JH8100_AON_GPIOEN 0x34 +#define JH8100_AON_GPIOIS 0x38 +#define JH8100_AON_GPIOIC 0x3c +#define JH8100_AON_GPIOIBE 0x40 +#define JH8100_AON_GPIOIEV 0x44 +#define JH8100_AON_GPIOIE 0x48 +#define JH8100_AON_GPIORIS 0x4c +#define JH8100_AON_GPIOMIS 0x50 + +#define JH8100_AON_GPO_PDA_0_14_CFG 0x90 + +static const struct pinctrl_pin_desc jh8100_aon_pins[] = { + PINCTRL_PIN(PAD_RGPIO0, "AON_RGPIO0"), + PINCTRL_PIN(PAD_RGPIO1, "AON_RGPIO1"), + PINCTRL_PIN(PAD_RGPIO2, "AON_RGPIO2"), + PINCTRL_PIN(PAD_RGPIO3, "AON_RGPIO3"), + PINCTRL_PIN(PAD_RGPIO4, "AON_RGPIO4"), + PINCTRL_PIN(PAD_RGPIO5, "AON_RGPIO5"), + PINCTRL_PIN(PAD_RGPIO6, "AON_RGPIO6"), + PINCTRL_PIN(PAD_RGPIO7, "AON_RGPIO7"), + PINCTRL_PIN(PAD_RGPIO8, "AON_RGPIO8"), + PINCTRL_PIN(PAD_RGPIO9, "AON_RGPIO9"), + PINCTRL_PIN(PAD_RGPIO10, "AON_RGPIO10"), + PINCTRL_PIN(PAD_RGPIO11, "AON_RGPIO11"), + PINCTRL_PIN(PAD_RGPIO12, "AON_RGPIO12"), + PINCTRL_PIN(PAD_RGPIO13, "AON_RGPIO13"), + PINCTRL_PIN(PAD_RGPIO14, "AON_RGPIO14"), + PINCTRL_PIN(PAD_RGPIO15, "AON_RGPIO15"), + PINCTRL_PIN(PAD_TESTEN, "AON_TESTEN"), + PINCTRL_PIN(PAD_RSTN, "AON_RSTN"), + PINCTRL_PIN(PAD_OSCK_XIN, "AON_OSCK_XIN"), + PINCTRL_PIN(PAD_OSCK_XOUT, "AON_OSCK_XOUT"), + PINCTRL_PIN(PAD_OSCM_XIN, "AON_OSCM_XIN"), + PINCTRL_PIN(PAD_OSCM_XOUT, "AON_OSCM_XOUT"), + PINCTRL_PIN(PAD_GMAC0_MDC, "AON_GMAC0_MDC"), + PINCTRL_PIN(PAD_GMAC0_MDIO, "AON_GMAC0_MDIO"), + PINCTRL_PIN(PAD_GMAC0_RXD0, "AON_GMAC0_RXD0"), + PINCTRL_PIN(PAD_GMAC0_RXD1, "AON_GMAC0_RXD1"), + PINCTRL_PIN(PAD_GMAC0_RXD2, "AON_GMAC0_RXD2"), + PINCTRL_PIN(PAD_GMAC0_RXD3, "AON_GMAC0_RXD3"), + PINCTRL_PIN(PAD_GMAC0_RXDV, "AON_GMAC0_RXDV"), + PINCTRL_PIN(PAD_GMAC0_RXC, "AON_GMAC0_RXC"), + PINCTRL_PIN(PAD_GMAC0_TXD0, "AON_GMAC0_TXD0"), + PINCTRL_PIN(PAD_GMAC0_TXD1, "AON_GMAC0_TXD1"), + PINCTRL_PIN(PAD_GMAC0_TXD2, "AON_GMAC0_TXD2"), + PINCTRL_PIN(PAD_GMAC0_TXD3, "AON_GMAC0_TXD3"), + PINCTRL_PIN(PAD_GMAC0_TXEN, "AON_GMAC0_TXEN"), + PINCTRL_PIN(PAD_GMAC0_TXC, "AON_GMAC0_TXC"), +}; + +static int jh8100_aon_set_one_pin_mux(struct jh8100_pinctrl *sfp, + unsigned int pin, + unsigned int din, u32 dout, + u32 doen, u32 func) +{ + if (pin < sfp->gc.ngpio && func == 0) + jh8100_set_gpiomux(sfp, pin, din, dout, doen); + + return 0; +} + +static int jh8100_aon_get_padcfg_base(struct jh8100_pinctrl *sfp, + unsigned int pin) +{ + if (pin < PAD_GMAC0_MDC) + return JH8100_AON_GPO_PDA_0_14_CFG; + + return -1; +} + +static void jh8100_aon_irq_handler(struct irq_desc *desc) +{ + struct jh8100_pinctrl *sfp = jh8100_from_irq_desc(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long mis; + unsigned int pin; + + chained_irq_enter(chip, desc); + + mis = readl_relaxed(sfp->base + JH8100_AON_GPIOMIS); + for_each_set_bit(pin, &mis, JH8100_AON_NGPIO) + generic_handle_domain_irq(sfp->gc.irq.domain, pin); + + chained_irq_exit(chip, desc); +} + +static int jh8100_aon_init_hw(struct gpio_chip *gc) +{ + struct jh8100_pinctrl *sfp = container_of(gc, + struct jh8100_pinctrl, gc); + + /* mask all GPIO interrupts */ + writel_relaxed(0, sfp->base + JH8100_AON_GPIOIE); + /* clear edge interrupt flags */ + writel_relaxed(0, sfp->base + JH8100_AON_GPIOIC); + writel_relaxed(0x0fff, sfp->base + JH8100_AON_GPIOIC); + /* enable GPIO interrupts */ + writel_relaxed(1, sfp->base + JH8100_AON_GPIOEN); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int jh8100_aon_pinctrl_suspend(struct device *dev) +{ + struct jh8100_pinctrl *sfp; + int i; + + sfp = dev_get_drvdata(dev); + if (!sfp) + return -EINVAL; + + if (device_may_wakeup(dev)) + enable_irq_wake(sfp->wakeup_irq); + + for (i = 0; i < JH8100_AON_REG_NUM; i++) + sfp->jh8100_aon_regs[i] = readl_relaxed(sfp->base + (i * 4)); + + return pinctrl_force_sleep(sfp->pctl); +} + +static int jh8100_aon_pinctrl_resume(struct device *dev) +{ + struct jh8100_pinctrl *sfp; + int i; + + sfp = dev_get_drvdata(dev); + if (!sfp) + return -EINVAL; + + if (device_may_wakeup(dev)) + disable_irq_wake(sfp->wakeup_irq); + + for (i = 0; i < JH8100_AON_REG_NUM; i++) + writel_relaxed(sfp->jh8100_aon_regs[i], sfp->base + (i * 4)); + + return pinctrl_force_default(sfp->pctl); +} +#endif + +static SIMPLE_DEV_PM_OPS(jh8100_aon_pinctrl_dev_pm_ops, + jh8100_aon_pinctrl_suspend, + jh8100_aon_pinctrl_resume); + +static const struct jh8100_gpio_irq_reg jh8100_aon_irq_reg = { + .is_reg_base = JH8100_AON_GPIOIS, + .ic_reg_base = JH8100_AON_GPIOIC, + .ibe_reg_base = JH8100_AON_GPIOIBE, + .iev_reg_base = JH8100_AON_GPIOIEV, + .ie_reg_base = JH8100_AON_GPIOIE, + .ris_reg_base = JH8100_AON_GPIORIS, + .mis_reg_base = JH8100_AON_GPIOMIS, +}; + +static const struct jh8100_pinctrl_soc_info jh8100_aon_pinctrl_info = { + .pins = jh8100_aon_pins, + .npins = ARRAY_SIZE(jh8100_aon_pins), + .ngpios = JH8100_AON_NGPIO, + .gc_base = JH8100_AON_GC_BASE, + .dout_reg_base = JH8100_AON_DOUT, + .dout_mask = GENMASK(4, 0), + .doen_reg_base = JH8100_AON_DOEN, + .doen_mask = GENMASK(2, 0), + .gpi_reg_base = JH8100_AON_GPI, + .gpi_mask = GENMASK(4, 0), + .gpioin_reg_base = JH8100_AON_GPIOIN, + .irq_reg = &jh8100_aon_irq_reg, + .jh8100_set_one_pin_mux = jh8100_aon_set_one_pin_mux, + .jh8100_get_padcfg_base = jh8100_aon_get_padcfg_base, + .jh8100_gpio_irq_handler = jh8100_aon_irq_handler, + .jh8100_gpio_init_hw = jh8100_aon_init_hw, +}; + +static const struct of_device_id jh8100_aon_pinctrl_of_match[] = { + { + .compatible = "starfive,jh8100-aon-pinctrl", + .data = &jh8100_aon_pinctrl_info, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, jh8100_aon_pinctrl_of_match); + +static struct platform_driver jh8100_aon_pinctrl_driver = { + .probe = jh8100_pinctrl_probe, + .driver = { + .name = "starfive-jh8100-aon-pinctrl", +#ifdef CONFIG_PM_SLEEP + .pm = &jh8100_aon_pinctrl_dev_pm_ops, +#endif + .of_match_table = jh8100_aon_pinctrl_of_match, + }, +}; +module_platform_driver(jh8100_aon_pinctrl_driver); + +MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH8100 SoC aon controller"); +MODULE_AUTHOR("Alex Soo <yuklin.soo@xxxxxxxxxxxxxxxx>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h index 43b62609fa3e..8347fa83e8dd 100644 --- a/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h +++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh8100.h @@ -16,6 +16,7 @@ #define JH8100_SYS_WEST_REG_NUM 44 #define JH8100_SYS_EAST_REG_NUM 116 #define JH8100_SYS_GMAC_REG_NUM 19 +#define JH8100_AON_REG_NUM 65 struct jh8100_pinctrl { struct device *dev; @@ -30,6 +31,7 @@ struct jh8100_pinctrl { unsigned int jh8100_sys_west_regs[JH8100_SYS_WEST_REG_NUM]; unsigned int jh8100_sys_east_regs[JH8100_SYS_EAST_REG_NUM]; unsigned int jh8100_sys_gmac_regs[JH8100_SYS_GMAC_REG_NUM]; + unsigned int jh8100_aon_regs[JH8100_AON_REG_NUM]; /* wakeup */ int wakeup_gpio; int wakeup_irq; -- 2.25.1