1*b1170c42SJianlong Huang // SPDX-License-Identifier: GPL-2.0 2*b1170c42SJianlong Huang /* 3*b1170c42SJianlong Huang * Pinctrl / GPIO driver for StarFive JH7110 SoC aon controller 4*b1170c42SJianlong Huang * 5*b1170c42SJianlong Huang * Copyright (C) 2022 StarFive Technology Co., Ltd. 6*b1170c42SJianlong Huang */ 7*b1170c42SJianlong Huang 8*b1170c42SJianlong Huang #include <linux/err.h> 9*b1170c42SJianlong Huang #include <linux/gpio/driver.h> 10*b1170c42SJianlong Huang #include <linux/init.h> 11*b1170c42SJianlong Huang #include <linux/interrupt.h> 12*b1170c42SJianlong Huang #include <linux/io.h> 13*b1170c42SJianlong Huang #include <linux/module.h> 14*b1170c42SJianlong Huang #include <linux/of.h> 15*b1170c42SJianlong Huang #include <linux/of_device.h> 16*b1170c42SJianlong Huang #include <linux/of_irq.h> 17*b1170c42SJianlong Huang #include <linux/of_platform.h> 18*b1170c42SJianlong Huang #include <linux/pinctrl/pinconf.h> 19*b1170c42SJianlong Huang #include <linux/pinctrl/pinconf-generic.h> 20*b1170c42SJianlong Huang #include <linux/pinctrl/pinctrl.h> 21*b1170c42SJianlong Huang #include <linux/pinctrl/pinmux.h> 22*b1170c42SJianlong Huang #include <linux/platform_device.h> 23*b1170c42SJianlong Huang #include <linux/pm_runtime.h> 24*b1170c42SJianlong Huang #include <linux/regmap.h> 25*b1170c42SJianlong Huang #include <linux/slab.h> 26*b1170c42SJianlong Huang 27*b1170c42SJianlong Huang #include <dt-bindings/pinctrl/starfive,jh7110-pinctrl.h> 28*b1170c42SJianlong Huang 29*b1170c42SJianlong Huang #include "../core.h" 30*b1170c42SJianlong Huang #include "../pinconf.h" 31*b1170c42SJianlong Huang #include "../pinmux.h" 32*b1170c42SJianlong Huang #include "pinctrl-starfive-jh7110.h" 33*b1170c42SJianlong Huang 34*b1170c42SJianlong Huang #define JH7110_AON_NGPIO 4 35*b1170c42SJianlong Huang #define JH7110_AON_GC_BASE 64 36*b1170c42SJianlong Huang 37*b1170c42SJianlong Huang /* registers */ 38*b1170c42SJianlong Huang #define JH7110_AON_DOEN 0x0 39*b1170c42SJianlong Huang #define JH7110_AON_DOUT 0x4 40*b1170c42SJianlong Huang #define JH7110_AON_GPI 0x8 41*b1170c42SJianlong Huang #define JH7110_AON_GPIOIN 0x2c 42*b1170c42SJianlong Huang 43*b1170c42SJianlong Huang #define JH7110_AON_GPIOEN 0xc 44*b1170c42SJianlong Huang #define JH7110_AON_GPIOIS 0x10 45*b1170c42SJianlong Huang #define JH7110_AON_GPIOIC 0x14 46*b1170c42SJianlong Huang #define JH7110_AON_GPIOIBE 0x18 47*b1170c42SJianlong Huang #define JH7110_AON_GPIOIEV 0x1c 48*b1170c42SJianlong Huang #define JH7110_AON_GPIOIE 0x20 49*b1170c42SJianlong Huang #define JH7110_AON_GPIORIS 0x28 50*b1170c42SJianlong Huang #define JH7110_AON_GPIOMIS 0x28 51*b1170c42SJianlong Huang 52*b1170c42SJianlong Huang #define JH7110_AON_GPO_PDA_0_5_CFG 0x30 53*b1170c42SJianlong Huang 54*b1170c42SJianlong Huang static const struct pinctrl_pin_desc jh7110_aon_pins[] = { 55*b1170c42SJianlong Huang PINCTRL_PIN(PAD_TESTEN, "TESTEN"), 56*b1170c42SJianlong Huang PINCTRL_PIN(PAD_RGPIO0, "RGPIO0"), 57*b1170c42SJianlong Huang PINCTRL_PIN(PAD_RGPIO1, "RGPIO1"), 58*b1170c42SJianlong Huang PINCTRL_PIN(PAD_RGPIO2, "RGPIO2"), 59*b1170c42SJianlong Huang PINCTRL_PIN(PAD_RGPIO3, "RGPIO3"), 60*b1170c42SJianlong Huang PINCTRL_PIN(PAD_RSTN, "RSTN"), 61*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_MDC, "GMAC0_MDC"), 62*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_MDIO, "GMAC0_MDIO"), 63*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_RXD0, "GMAC0_RXD0"), 64*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_RXD1, "GMAC0_RXD1"), 65*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_RXD2, "GMAC0_RXD2"), 66*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_RXD3, "GMAC0_RXD3"), 67*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_RXDV, "GMAC0_RXDV"), 68*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_RXC, "GMAC0_RXC"), 69*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_TXD0, "GMAC0_TXD0"), 70*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_TXD1, "GMAC0_TXD1"), 71*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_TXD2, "GMAC0_TXD2"), 72*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_TXD3, "GMAC0_TXD3"), 73*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_TXEN, "GMAC0_TXEN"), 74*b1170c42SJianlong Huang PINCTRL_PIN(PAD_GMAC0_TXC, "GMAC0_TXC"), 75*b1170c42SJianlong Huang }; 76*b1170c42SJianlong Huang 77*b1170c42SJianlong Huang static int jh7110_aon_set_one_pin_mux(struct jh7110_pinctrl *sfp, 78*b1170c42SJianlong Huang unsigned int pin, 79*b1170c42SJianlong Huang unsigned int din, u32 dout, 80*b1170c42SJianlong Huang u32 doen, u32 func) 81*b1170c42SJianlong Huang { 82*b1170c42SJianlong Huang if (pin < sfp->gc.ngpio && func == 0) 83*b1170c42SJianlong Huang jh7110_set_gpiomux(sfp, pin, din, dout, doen); 84*b1170c42SJianlong Huang 85*b1170c42SJianlong Huang return 0; 86*b1170c42SJianlong Huang } 87*b1170c42SJianlong Huang 88*b1170c42SJianlong Huang static int jh7110_aon_get_padcfg_base(struct jh7110_pinctrl *sfp, 89*b1170c42SJianlong Huang unsigned int pin) 90*b1170c42SJianlong Huang { 91*b1170c42SJianlong Huang if (pin < PAD_GMAC0_MDC) 92*b1170c42SJianlong Huang return JH7110_AON_GPO_PDA_0_5_CFG; 93*b1170c42SJianlong Huang 94*b1170c42SJianlong Huang return -1; 95*b1170c42SJianlong Huang } 96*b1170c42SJianlong Huang 97*b1170c42SJianlong Huang static void jh7110_aon_irq_handler(struct irq_desc *desc) 98*b1170c42SJianlong Huang { 99*b1170c42SJianlong Huang struct jh7110_pinctrl *sfp = jh7110_from_irq_desc(desc); 100*b1170c42SJianlong Huang struct irq_chip *chip = irq_desc_get_chip(desc); 101*b1170c42SJianlong Huang unsigned long mis; 102*b1170c42SJianlong Huang unsigned int pin; 103*b1170c42SJianlong Huang 104*b1170c42SJianlong Huang chained_irq_enter(chip, desc); 105*b1170c42SJianlong Huang 106*b1170c42SJianlong Huang mis = readl_relaxed(sfp->base + JH7110_AON_GPIOMIS); 107*b1170c42SJianlong Huang for_each_set_bit(pin, &mis, JH7110_AON_NGPIO) 108*b1170c42SJianlong Huang generic_handle_domain_irq(sfp->gc.irq.domain, pin); 109*b1170c42SJianlong Huang 110*b1170c42SJianlong Huang chained_irq_exit(chip, desc); 111*b1170c42SJianlong Huang } 112*b1170c42SJianlong Huang 113*b1170c42SJianlong Huang static int jh7110_aon_init_hw(struct gpio_chip *gc) 114*b1170c42SJianlong Huang { 115*b1170c42SJianlong Huang struct jh7110_pinctrl *sfp = container_of(gc, 116*b1170c42SJianlong Huang struct jh7110_pinctrl, gc); 117*b1170c42SJianlong Huang 118*b1170c42SJianlong Huang /* mask all GPIO interrupts */ 119*b1170c42SJianlong Huang writel_relaxed(0, sfp->base + JH7110_AON_GPIOIE); 120*b1170c42SJianlong Huang /* clear edge interrupt flags */ 121*b1170c42SJianlong Huang writel_relaxed(0, sfp->base + JH7110_AON_GPIOIC); 122*b1170c42SJianlong Huang writel_relaxed(0x0f, sfp->base + JH7110_AON_GPIOIC); 123*b1170c42SJianlong Huang /* enable GPIO interrupts */ 124*b1170c42SJianlong Huang writel_relaxed(1, sfp->base + JH7110_AON_GPIOEN); 125*b1170c42SJianlong Huang return 0; 126*b1170c42SJianlong Huang } 127*b1170c42SJianlong Huang 128*b1170c42SJianlong Huang static const struct jh7110_gpio_irq_reg jh7110_aon_irq_reg = { 129*b1170c42SJianlong Huang .is_reg_base = JH7110_AON_GPIOIS, 130*b1170c42SJianlong Huang .ic_reg_base = JH7110_AON_GPIOIC, 131*b1170c42SJianlong Huang .ibe_reg_base = JH7110_AON_GPIOIBE, 132*b1170c42SJianlong Huang .iev_reg_base = JH7110_AON_GPIOIEV, 133*b1170c42SJianlong Huang .ie_reg_base = JH7110_AON_GPIOIE, 134*b1170c42SJianlong Huang .ris_reg_base = JH7110_AON_GPIORIS, 135*b1170c42SJianlong Huang .mis_reg_base = JH7110_AON_GPIOMIS, 136*b1170c42SJianlong Huang }; 137*b1170c42SJianlong Huang 138*b1170c42SJianlong Huang static const struct jh7110_pinctrl_soc_info jh7110_aon_pinctrl_info = { 139*b1170c42SJianlong Huang .pins = jh7110_aon_pins, 140*b1170c42SJianlong Huang .npins = ARRAY_SIZE(jh7110_aon_pins), 141*b1170c42SJianlong Huang .ngpios = JH7110_AON_NGPIO, 142*b1170c42SJianlong Huang .gc_base = JH7110_AON_GC_BASE, 143*b1170c42SJianlong Huang .dout_reg_base = JH7110_AON_DOUT, 144*b1170c42SJianlong Huang .dout_mask = GENMASK(3, 0), 145*b1170c42SJianlong Huang .doen_reg_base = JH7110_AON_DOEN, 146*b1170c42SJianlong Huang .doen_mask = GENMASK(2, 0), 147*b1170c42SJianlong Huang .gpi_reg_base = JH7110_AON_GPI, 148*b1170c42SJianlong Huang .gpi_mask = GENMASK(3, 0), 149*b1170c42SJianlong Huang .gpioin_reg_base = JH7110_AON_GPIOIN, 150*b1170c42SJianlong Huang .irq_reg = &jh7110_aon_irq_reg, 151*b1170c42SJianlong Huang .jh7110_set_one_pin_mux = jh7110_aon_set_one_pin_mux, 152*b1170c42SJianlong Huang .jh7110_get_padcfg_base = jh7110_aon_get_padcfg_base, 153*b1170c42SJianlong Huang .jh7110_gpio_irq_handler = jh7110_aon_irq_handler, 154*b1170c42SJianlong Huang .jh7110_gpio_init_hw = jh7110_aon_init_hw, 155*b1170c42SJianlong Huang }; 156*b1170c42SJianlong Huang 157*b1170c42SJianlong Huang static const struct of_device_id jh7110_aon_pinctrl_of_match[] = { 158*b1170c42SJianlong Huang { 159*b1170c42SJianlong Huang .compatible = "starfive,jh7110-aon-pinctrl", 160*b1170c42SJianlong Huang .data = &jh7110_aon_pinctrl_info, 161*b1170c42SJianlong Huang }, 162*b1170c42SJianlong Huang { /* sentinel */ } 163*b1170c42SJianlong Huang }; 164*b1170c42SJianlong Huang MODULE_DEVICE_TABLE(of, jh7110_aon_pinctrl_of_match); 165*b1170c42SJianlong Huang 166*b1170c42SJianlong Huang static struct platform_driver jh7110_aon_pinctrl_driver = { 167*b1170c42SJianlong Huang .probe = jh7110_pinctrl_probe, 168*b1170c42SJianlong Huang .driver = { 169*b1170c42SJianlong Huang .name = "starfive-jh7110-aon-pinctrl", 170*b1170c42SJianlong Huang .of_match_table = jh7110_aon_pinctrl_of_match, 171*b1170c42SJianlong Huang }, 172*b1170c42SJianlong Huang }; 173*b1170c42SJianlong Huang module_platform_driver(jh7110_aon_pinctrl_driver); 174*b1170c42SJianlong Huang 175*b1170c42SJianlong Huang MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC aon controller"); 176*b1170c42SJianlong Huang MODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>"); 177*b1170c42SJianlong Huang MODULE_LICENSE("GPL"); 178