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