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