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(domain: sfp->gc.irq.domain, hwirq: 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 | |