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