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