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