xref: /rk3399_rockchip-uboot/drivers/irq/irq-gpio-switch.c (revision c6d8e6aac063eabd956f25ad0e4c1531dd59f385)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
276 int irq_to_gpio(int irq)
277 {
278 	return __irq_to_gpio(irq);
279 }
280 
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 
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