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