1 /*
2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <dm.h>
8 #include "irq-internal.h"
9
10 DECLARE_GLOBAL_DATA_PTR;
11
12 static struct gpio_bank gpio_banks[GPIO_BANK_NUM] = {
13 #if GPIO_BANK_NUM >= 1
14 GPIO_BANK_REGISTER(0, GPIO_BANK_PINS),
15 #endif
16 #if GPIO_BANK_NUM >= 2
17 GPIO_BANK_REGISTER(1, GPIO_BANK_PINS),
18 #endif
19 #if GPIO_BANK_NUM >= 3
20 GPIO_BANK_REGISTER(2, GPIO_BANK_PINS),
21 #endif
22 #if GPIO_BANK_NUM >= 4
23 GPIO_BANK_REGISTER(3, GPIO_BANK_PINS),
24 #endif
25 #if GPIO_BANK_NUM >= 5
26 GPIO_BANK_REGISTER(4, GPIO_BANK_PINS),
27 #endif
28 #if GPIO_BANK_NUM >= 6
29 GPIO_BANK_REGISTER(5, GPIO_BANK_PINS),
30 #endif
31 #if GPIO_BANK_NUM >= 7
32 GPIO_BANK_REGISTER(6, GPIO_BANK_PINS),
33 #endif
34 #if GPIO_BANK_NUM >= 8
35 GPIO_BANK_REGISTER(7, GPIO_BANK_PINS),
36 #endif
37 #if GPIO_BANK_NUM >= 9
38 GPIO_BANK_REGISTER(8, GPIO_BANK_PINS),
39 #endif
40 #if GPIO_BANK_NUM >= 10
41 GPIO_BANK_REGISTER(9, GPIO_BANK_PINS),
42 #endif
43 };
44
45 static const char *aliases_gpios[GPIO_BANK_NUM];
46 static const char *order_gpios[GPIO_BANK_NUM];
47
gpio_is_valid(u32 gpio)48 static int gpio_is_valid(u32 gpio)
49 {
50 if ((gpio == EINVAL_GPIO) ||
51 !GPIO_BANK_VALID(gpio) ||
52 !GPIO_PIN_VALID(gpio)) {
53 IRQ_E("gpio-%d(bank-%d, pin-%d) is invalid!\n",
54 gpio, GPIO_BANK(gpio), GPIO_PIN(gpio));
55 return 0;
56 }
57
58 return 1;
59 }
60
__hard_gpio_to_irq(u32 gpio)61 static int __hard_gpio_to_irq(u32 gpio)
62 {
63 int idx, bank = 0, pin = 0;
64 int irq;
65
66 if (!gpio_is_valid(gpio))
67 return -EINVAL;
68
69 bank = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET;
70 pin = (gpio & GPIO_PIN_MASK) >> GPIO_PIN_OFFSET;
71
72 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) {
73 if (gpio_banks[idx].id == bank) {
74 irq = (gpio_banks[idx].irq_base + pin);
75 if (irq_is_busy(irq))
76 return -EBUSY;
77 return irq;
78 }
79 }
80
81 return -EINVAL;
82 }
83
init_order_gpios(void)84 static int init_order_gpios(void)
85 {
86 const void *fdt = gd->fdt_blob;
87 static int initialized;
88 int node, offset;
89 int i = 0;
90
91 if (initialized)
92 return 0;
93
94 node = fdt_path_offset(fdt, "/pinctrl");
95 if (node < 0)
96 return -EINVAL;
97
98 for (offset = fdt_first_subnode(fdt, node);
99 offset >= 0 && i < GPIO_BANK_NUM;
100 offset = fdt_next_subnode(fdt, offset)) {
101 if (i >= GPIO_BANK_NUM)
102 break;
103
104 order_gpios[i++] = fdt_get_name(fdt, offset, NULL);
105 IRQ_D("order gpio: %s\n", order_gpios[i - 1]);
106 }
107
108 initialized = 1;
109
110 return 0;
111 }
112
init_aliases_gpios(void)113 static int init_aliases_gpios(void)
114 {
115 static int initialized;
116 char alias_name[6];
117 int i;
118
119 if (initialized)
120 return 0;
121
122 for (i = 0; i < GPIO_BANK_NUM; i++) {
123 snprintf(alias_name, 6, "gpio%d", i);
124 aliases_gpios[i] = fdt_get_alias(gd->fdt_blob, alias_name);
125 if (!aliases_gpios[i])
126 return -EINVAL;
127
128 IRQ_D("aliases gpio: %s\n", aliases_gpios[i]);
129 }
130
131 initialized = 1;
132
133 return 0;
134 }
135
lookup_gpio_bank(const char * name)136 static int lookup_gpio_bank(const char *name)
137 {
138 int bank, ret;
139
140 for (bank = 0; bank < GPIO_BANK_NUM; bank++) {
141 if (strstr(name, gpio_banks[bank].name))
142 return bank;
143 }
144
145 ret = init_aliases_gpios();
146 for (bank = 0; !ret && bank < GPIO_BANK_NUM; bank++) {
147 /*
148 * @name pattern can be:
149 * /pinctrl/gpio@fd8a0000 or gpio@fd8a0000
150 */
151 if (strstr(aliases_gpios[bank], name))
152 return bank;
153 }
154
155 ret = init_order_gpios();
156 for (bank = 0; !ret && bank < GPIO_BANK_NUM; bank++) {
157 if (!strcmp(name, order_gpios[bank]))
158 return bank;
159 }
160
161 return -ENOENT;
162 }
163
__phandle_gpio_to_irq(u32 gpio_phandle,u32 offset)164 static int __phandle_gpio_to_irq(u32 gpio_phandle, u32 offset)
165 {
166 const void *blob = gd->fdt_blob;
167 const char *gpio_name;
168 int irq, node;
169 int bank;
170
171 node = fdt_node_offset_by_phandle(blob, gpio_phandle);
172 if (node < 0) {
173 IRQ_E("No gpio node by phandle(0x%x), ret=%d\n", gpio_phandle, node);
174 return EINVAL_GPIO;
175 }
176
177 gpio_name = fdt_get_name(blob, node, NULL);
178 if (!gpio_name)
179 return EINVAL_GPIO;
180
181 bank = lookup_gpio_bank(gpio_name);
182 if (bank < 0) {
183 IRQ_E("IRQ Framework can't find: %s\n", gpio_name);
184 return EINVAL_GPIO;
185 }
186
187 IRQ_D("%s: gpio%d-%d\n", __func__, bank, offset);
188
189 irq = RK_IRQ_GPIO(bank, offset);
190 if (!gpio_is_valid(irq))
191 return EINVAL_GPIO;
192
193 return __hard_gpio_to_irq(irq);
194 }
195
__irq_to_gpio(int irq)196 static int __irq_to_gpio(int irq)
197 {
198 int bank, pin, idx;
199
200 bank = (irq - PIN_BASE) / GPIO_BANK_PINS;
201 pin = (irq - PIN_BASE) % GPIO_BANK_PINS;
202
203 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) {
204 if (gpio_banks[idx].id == bank) {
205 return (bank << GPIO_BANK_OFFSET) |
206 (pin << GPIO_PIN_OFFSET);
207 }
208 }
209
210 return -EINVAL;
211 }
212
gpio_to_irq(struct gpio_desc * gpio)213 int gpio_to_irq(struct gpio_desc *gpio)
214 {
215 int irq_gpio, bank, ret = EINVAL_GPIO;
216 char *name, *name_tok;
217 bool found;
218
219 if (!gpio->dev->name) {
220 IRQ_E("Can't find dev name for gpio bank\n");
221 return EINVAL_GPIO;
222 }
223
224 name_tok = strdup(gpio->dev->name);
225 if (!name_tok) {
226 IRQ_E("Strdup '%s' failed!\n", gpio->dev->name);
227 return -ENOMEM;
228 }
229
230 name = strtok(name_tok, "@");
231 if (!name) {
232 IRQ_E("Can't strtok '@' for '%s'\n", name_tok);
233 goto out;
234 }
235
236 for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) {
237 if (!strcmp(gpio_banks[bank].name, name)) {
238 found = true;
239 break;
240 }
241 }
242
243 if (!found) {
244 IRQ_E("GPIO irq framework can't find '%s'\n", name);
245 goto out;
246 }
247
248 irq_gpio = RK_IRQ_GPIO(bank, gpio->offset);
249 if (!gpio_is_valid(irq_gpio))
250 goto out;
251
252 free(name_tok);
253 return __hard_gpio_to_irq(irq_gpio);
254
255 out:
256 free(name_tok);
257 return ret;
258 }
259
hard_gpio_to_irq(u32 gpio)260 int hard_gpio_to_irq(u32 gpio)
261 {
262 if (!gpio_is_valid(gpio))
263 return EINVAL_GPIO;
264
265 return __hard_gpio_to_irq(gpio);
266 }
267
phandle_gpio_to_irq(u32 gpio_phandle,u32 pin)268 int phandle_gpio_to_irq(u32 gpio_phandle, u32 pin)
269 {
270 if (gpio_phandle < 0)
271 return EINVAL_GPIO;
272
273 return __phandle_gpio_to_irq(gpio_phandle, pin);
274 }
275
irq_to_gpio(int irq)276 int irq_to_gpio(int irq)
277 {
278 return __irq_to_gpio(irq);
279 }
280
gpio_id_to_bank(u32 id)281 struct gpio_bank *gpio_id_to_bank(u32 id)
282 {
283 int idx;
284
285 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) {
286 if (gpio_banks[idx].id == id)
287 return &gpio_banks[idx];
288 }
289
290 return NULL;
291 }
292
gpio_to_bank(u32 gpio)293 struct gpio_bank *gpio_to_bank(u32 gpio)
294 {
295 int id;
296
297 if (!gpio_is_valid(gpio))
298 return NULL;
299
300 id = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET;
301
302 return gpio_id_to_bank(id);
303 }
304