xref: /rk3399_rockchip-uboot/drivers/irq/irq-gpio-switch.c (revision 5e8564cf419797f9095431e6eb6f0c00dfa423d2)
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-generic.h>
9 #include "irq-gpio-switch.h"
10 
11 DECLARE_GLOBAL_DATA_PTR;
12 
13 static struct gpio_bank gpio_banks[GPIO_BANK_NUM] = {
14 #if GPIO_BANK_NUM >= 1
15 	GPIO_BANK_REGISTER(0, GPIO_BANK_PINS),
16 #endif
17 #if GPIO_BANK_NUM >= 2
18 	GPIO_BANK_REGISTER(1, GPIO_BANK_PINS),
19 #endif
20 #if GPIO_BANK_NUM >= 3
21 	GPIO_BANK_REGISTER(2, GPIO_BANK_PINS),
22 #endif
23 #if GPIO_BANK_NUM >= 4
24 	GPIO_BANK_REGISTER(3, GPIO_BANK_PINS),
25 #endif
26 #if GPIO_BANK_NUM >= 5
27 	GPIO_BANK_REGISTER(4, GPIO_BANK_PINS),
28 #endif
29 #if GPIO_BANK_NUM >= 6
30 	GPIO_BANK_REGISTER(5, GPIO_BANK_PINS),
31 #endif
32 #if GPIO_BANK_NUM >= 7
33 	GPIO_BANK_REGISTER(6, GPIO_BANK_PINS),
34 #endif
35 #if GPIO_BANK_NUM >= 8
36 	GPIO_BANK_REGISTER(7, GPIO_BANK_PINS),
37 #endif
38 #if GPIO_BANK_NUM >= 9
39 	GPIO_BANK_REGISTER(8, GPIO_BANK_PINS),
40 #endif
41 #if GPIO_BANK_NUM >= 10
42 	GPIO_BANK_REGISTER(9, GPIO_BANK_PINS),
43 #endif
44 };
45 
46 static int gpio_is_valid(u32 gpio)
47 {
48 	if ((gpio == EINVAL_GPIO) ||
49 	    !GPIO_BANK_VALID(gpio) ||
50 	    !GPIO_PIN_VALID(gpio)) {
51 		IRQ_E("gpio-%d(bank-%d, pin-%d) is invalid!\n",
52 		      gpio, GPIO_BANK(gpio), GPIO_PIN(gpio));
53 		return 0;
54 	}
55 
56 	return 1;
57 }
58 
59 static int __hard_gpio_to_irq(u32 gpio)
60 {
61 	int idx, bank = 0, pin = 0;
62 	int irq;
63 
64 	if (!gpio_is_valid(gpio))
65 		return -EINVAL;
66 
67 	bank = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET;
68 	pin = (gpio & GPIO_PIN_MASK) >> GPIO_PIN_OFFSET;
69 
70 	for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) {
71 		if (gpio_banks[idx].id == bank) {
72 			irq = (gpio_banks[idx].irq_base + pin);
73 			if (irq_is_busy(irq))
74 				return -EBUSY;
75 			return irq;
76 		}
77 	}
78 
79 	return -EINVAL;
80 }
81 
82 static int __phandle_gpio_to_irq(u32 gpio_phandle, u32 offset)
83 {
84 	int irq_gpio, bank, ret = EINVAL_GPIO;
85 	const char *name;
86 	char *name_tok;
87 	bool found;
88 	int node;
89 
90 	node = fdt_node_offset_by_phandle(gd->fdt_blob, gpio_phandle);
91 	if (node < 0) {
92 		IRQ_E("Can't find node by gpio_phandle=%d, ret=%d\n",
93 		      gpio_phandle, node);
94 		return EINVAL_GPIO;
95 	}
96 
97 	name = fdt_get_name(gd->fdt_blob, node, NULL);
98 	if (!name) {
99 		IRQ_E("Can't find gpio bank for phandle=%d\n", gpio_phandle);
100 		return EINVAL_GPIO;
101 	}
102 
103 	name_tok = strdup(name);
104 	if (!name_tok) {
105 		IRQ_E("Strdup '%s' failed!\n", name);
106 		return -ENOMEM;
107 	}
108 
109 	name = strtok(name_tok, "@");
110 	if (!name) {
111 		IRQ_E("Can't strtok '@' for '%s'\n", name_tok);
112 		goto out;
113 	}
114 
115 	for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) {
116 		if (!strcmp(gpio_banks[bank].name, name)) {
117 			found = true;
118 			break;
119 		}
120 	}
121 
122 	if (!found) {
123 		IRQ_E("GPIO irq framework can't find '%s'\n", name);
124 		goto out;
125 	}
126 
127 	IRQ_D("%s: gpio%d-%d\n", __func__, bank, offset);
128 	irq_gpio = RK_IRQ_GPIO(bank, offset);
129 	if (!gpio_is_valid(irq_gpio))
130 		goto out;
131 
132 	free(name_tok);
133 	return __hard_gpio_to_irq(irq_gpio);
134 
135 out:
136 	free(name_tok);
137 	return ret;
138 }
139 
140 static int __irq_to_gpio(int irq)
141 {
142 	int bank, pin, idx;
143 
144 	bank = (irq - PIN_BASE) / GPIO_BANK_PINS;
145 	pin = (irq - PIN_BASE) % GPIO_BANK_PINS;
146 
147 	for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) {
148 		if (gpio_banks[idx].id == bank) {
149 			return (bank << GPIO_BANK_OFFSET) |
150 				(pin << GPIO_PIN_OFFSET);
151 		}
152 	}
153 
154 	return -EINVAL;
155 }
156 
157 int gpio_to_irq(struct gpio_desc *gpio)
158 {
159 	int irq_gpio, bank, ret = EINVAL_GPIO;
160 	char *name, *name_tok;
161 	bool found;
162 
163 	if (!gpio->dev->name) {
164 		IRQ_E("Can't find dev name for gpio bank\n");
165 		return EINVAL_GPIO;
166 	}
167 
168 	name_tok = strdup(gpio->dev->name);
169 	if (!name_tok) {
170 		IRQ_E("Strdup '%s' failed!\n", gpio->dev->name);
171 		return -ENOMEM;
172 	}
173 
174 	name = strtok(name_tok, "@");
175 	if (!name) {
176 		IRQ_E("Can't strtok '@' for '%s'\n", name_tok);
177 		goto out;
178 	}
179 
180 	for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) {
181 		if (!strcmp(gpio_banks[bank].name, name)) {
182 			found = true;
183 			break;
184 		}
185 	}
186 
187 	if (!found) {
188 		IRQ_E("GPIO irq framework can't find '%s'\n", name);
189 		goto out;
190 	}
191 
192 	irq_gpio = RK_IRQ_GPIO(bank, gpio->offset);
193 	if (!gpio_is_valid(irq_gpio))
194 		goto out;
195 
196 	free(name_tok);
197 	return __hard_gpio_to_irq(irq_gpio);
198 
199 out:
200 	free(name_tok);
201 	return ret;
202 }
203 
204 int hard_gpio_to_irq(u32 gpio)
205 {
206 	if (!gpio_is_valid(gpio))
207 		return EINVAL_GPIO;
208 
209 	return __hard_gpio_to_irq(gpio);
210 }
211 
212 int phandle_gpio_to_irq(u32 gpio_phandle, u32 pin)
213 {
214 	if (gpio_phandle < 0)
215 		return EINVAL_GPIO;
216 
217 	return __phandle_gpio_to_irq(gpio_phandle, pin);
218 }
219 
220 int irq_to_gpio(int irq)
221 {
222 	return __irq_to_gpio(irq);
223 }
224 
225 struct gpio_bank *gpio_id_to_bank(u32 id)
226 {
227 	int idx;
228 
229 	for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) {
230 		if (gpio_banks[idx].id == id)
231 			return &gpio_banks[idx];
232 	}
233 
234 	return NULL;
235 }
236 
237 struct gpio_bank *gpio_to_bank(u32 gpio)
238 {
239 	int id;
240 
241 	if (!gpio_is_valid(gpio))
242 		return NULL;
243 
244 	id = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET;
245 
246 	return gpio_id_to_bank(id);
247 }
248