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