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