]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
f517afd5 LW |
2 | /* |
3 | * GPIO driver for TI DaVinci DA8xx SOCs. | |
4 | * | |
5 | * (C) Copyright 2011 Guralp Systems Ltd. | |
6 | * Laurence Withers <[email protected]> | |
f517afd5 LW |
7 | */ |
8 | ||
8e51c0f2 AF |
9 | #include <dm.h> |
10 | #include <fdtdec.h> | |
336d4615 | 11 | #include <malloc.h> |
f517afd5 | 12 | #include <asm/io.h> |
401d1c4f | 13 | #include <asm/global_data.h> |
f517afd5 | 14 | #include <asm/gpio.h> |
1eddf549 | 15 | #include <dt-bindings/gpio/gpio.h> |
f517afd5 | 16 | |
0f3cf2b3 K |
17 | #include "da8xx_gpio.h" |
18 | ||
bcee8d67 | 19 | #if !CONFIG_IS_ENABLED(DM_GPIO) |
0f3cf2b3 K |
20 | #include <asm/arch/hardware.h> |
21 | #include <asm/arch/davinci_misc.h> | |
22 | ||
f517afd5 LW |
23 | static struct gpio_registry { |
24 | int is_registered; | |
25 | char name[GPIO_NAME_SIZE]; | |
26 | } gpio_registry[MAX_NUM_GPIOS]; | |
27 | ||
03414ac4 | 28 | #if defined(CONFIG_SOC_DA8XX) |
f517afd5 LW |
29 | #define pinmux(x) (&davinci_syscfg_regs->pinmux[x]) |
30 | ||
b9f56698 TN |
31 | #if defined(CONFIG_SOC_DA8XX) && !defined(CONFIG_SOC_DA850) |
32 | static const struct pinmux_config gpio_pinmux[] = { | |
33 | { pinmux(13), 8, 6 }, /* GP0[0] */ | |
34 | { pinmux(13), 8, 7 }, | |
35 | { pinmux(14), 8, 0 }, | |
36 | { pinmux(14), 8, 1 }, | |
37 | { pinmux(14), 8, 2 }, | |
38 | { pinmux(14), 8, 3 }, | |
39 | { pinmux(14), 8, 4 }, | |
40 | { pinmux(14), 8, 5 }, | |
41 | { pinmux(14), 8, 6 }, | |
42 | { pinmux(14), 8, 7 }, | |
43 | { pinmux(15), 8, 0 }, | |
44 | { pinmux(15), 8, 1 }, | |
45 | { pinmux(15), 8, 2 }, | |
46 | { pinmux(15), 8, 3 }, | |
47 | { pinmux(15), 8, 4 }, | |
48 | { pinmux(15), 8, 5 }, | |
49 | { pinmux(15), 8, 6 }, /* GP1[0] */ | |
50 | { pinmux(15), 8, 7 }, | |
51 | { pinmux(16), 8, 0 }, | |
52 | { pinmux(16), 8, 1 }, | |
53 | { pinmux(16), 8, 2 }, | |
54 | { pinmux(16), 8, 3 }, | |
55 | { pinmux(16), 8, 4 }, | |
56 | { pinmux(16), 8, 5 }, | |
57 | { pinmux(16), 8, 6 }, | |
58 | { pinmux(16), 8, 7 }, | |
59 | { pinmux(17), 8, 0 }, | |
60 | { pinmux(17), 8, 1 }, | |
61 | { pinmux(17), 8, 2 }, | |
62 | { pinmux(17), 8, 3 }, | |
63 | { pinmux(17), 8, 4 }, | |
64 | { pinmux(17), 8, 5 }, | |
65 | { pinmux(17), 8, 6 }, /* GP2[0] */ | |
66 | { pinmux(17), 8, 7 }, | |
67 | { pinmux(18), 8, 0 }, | |
68 | { pinmux(18), 8, 1 }, | |
69 | { pinmux(18), 8, 2 }, | |
70 | { pinmux(18), 8, 3 }, | |
71 | { pinmux(18), 8, 4 }, | |
72 | { pinmux(18), 8, 5 }, | |
73 | { pinmux(18), 8, 6 }, | |
74 | { pinmux(18), 8, 7 }, | |
75 | { pinmux(19), 8, 0 }, | |
76 | { pinmux(9), 8, 2 }, | |
77 | { pinmux(9), 8, 3 }, | |
78 | { pinmux(9), 8, 4 }, | |
79 | { pinmux(9), 8, 5 }, | |
80 | { pinmux(9), 8, 6 }, | |
81 | { pinmux(10), 8, 1 }, /* GP3[0] */ | |
82 | { pinmux(10), 8, 2 }, | |
83 | { pinmux(10), 8, 3 }, | |
84 | { pinmux(10), 8, 4 }, | |
85 | { pinmux(10), 8, 5 }, | |
86 | { pinmux(10), 8, 6 }, | |
87 | { pinmux(10), 8, 7 }, | |
88 | { pinmux(11), 8, 0 }, | |
89 | { pinmux(11), 8, 1 }, | |
90 | { pinmux(11), 8, 2 }, | |
91 | { pinmux(11), 8, 3 }, | |
92 | { pinmux(11), 8, 4 }, | |
93 | { pinmux(9), 8, 7 }, | |
94 | { pinmux(2), 8, 6 }, | |
95 | { pinmux(11), 8, 5 }, | |
96 | { pinmux(11), 8, 6 }, | |
97 | { pinmux(12), 8, 4 }, /* GP4[0] */ | |
98 | { pinmux(12), 8, 5 }, | |
99 | { pinmux(12), 8, 6 }, | |
100 | { pinmux(12), 8, 7 }, | |
101 | { pinmux(13), 8, 0 }, | |
102 | { pinmux(13), 8, 1 }, | |
103 | { pinmux(13), 8, 2 }, | |
104 | { pinmux(13), 8, 3 }, | |
105 | { pinmux(13), 8, 4 }, | |
106 | { pinmux(13), 8, 5 }, | |
107 | { pinmux(11), 8, 7 }, | |
108 | { pinmux(12), 8, 0 }, | |
109 | { pinmux(12), 8, 1 }, | |
110 | { pinmux(12), 8, 2 }, | |
111 | { pinmux(12), 8, 3 }, | |
112 | { pinmux(9), 8, 1 }, | |
113 | { pinmux(7), 8, 3 }, /* GP5[0] */ | |
114 | { pinmux(7), 8, 4 }, | |
115 | { pinmux(7), 8, 5 }, | |
116 | { pinmux(7), 8, 6 }, | |
117 | { pinmux(7), 8, 7 }, | |
118 | { pinmux(8), 8, 0 }, | |
119 | { pinmux(8), 8, 1 }, | |
120 | { pinmux(8), 8, 2 }, | |
121 | { pinmux(8), 8, 3 }, | |
122 | { pinmux(8), 8, 4 }, | |
123 | { pinmux(8), 8, 5 }, | |
124 | { pinmux(8), 8, 6 }, | |
125 | { pinmux(8), 8, 7 }, | |
126 | { pinmux(9), 8, 0 }, | |
127 | { pinmux(7), 8, 1 }, | |
128 | { pinmux(7), 8, 2 }, | |
129 | { pinmux(5), 8, 1 }, /* GP6[0] */ | |
130 | { pinmux(5), 8, 2 }, | |
131 | { pinmux(5), 8, 3 }, | |
132 | { pinmux(5), 8, 4 }, | |
133 | { pinmux(5), 8, 5 }, | |
134 | { pinmux(5), 8, 6 }, | |
135 | { pinmux(5), 8, 7 }, | |
136 | { pinmux(6), 8, 0 }, | |
137 | { pinmux(6), 8, 1 }, | |
138 | { pinmux(6), 8, 2 }, | |
139 | { pinmux(6), 8, 3 }, | |
140 | { pinmux(6), 8, 4 }, | |
141 | { pinmux(6), 8, 5 }, | |
142 | { pinmux(6), 8, 6 }, | |
143 | { pinmux(6), 8, 7 }, | |
144 | { pinmux(7), 8, 0 }, | |
145 | { pinmux(1), 8, 0 }, /* GP7[0] */ | |
146 | { pinmux(1), 8, 1 }, | |
147 | { pinmux(1), 8, 2 }, | |
148 | { pinmux(1), 8, 3 }, | |
149 | { pinmux(1), 8, 4 }, | |
150 | { pinmux(1), 8, 5 }, | |
151 | { pinmux(1), 8, 6 }, | |
152 | { pinmux(1), 8, 7 }, | |
153 | { pinmux(2), 8, 0 }, | |
154 | { pinmux(2), 8, 1 }, | |
155 | { pinmux(2), 8, 2 }, | |
156 | { pinmux(2), 8, 3 }, | |
157 | { pinmux(2), 8, 4 }, | |
158 | { pinmux(2), 8, 5 }, | |
159 | { pinmux(0), 1, 0 }, | |
160 | { pinmux(0), 1, 1 }, | |
161 | }; | |
76b40ab4 | 162 | #else /* CONFIG_SOC_DA8XX && CONFIG_SOC_DA850 */ |
f517afd5 LW |
163 | static const struct pinmux_config gpio_pinmux[] = { |
164 | { pinmux(1), 8, 7 }, /* GP0[0] */ | |
165 | { pinmux(1), 8, 6 }, | |
166 | { pinmux(1), 8, 5 }, | |
167 | { pinmux(1), 8, 4 }, | |
168 | { pinmux(1), 8, 3 }, | |
169 | { pinmux(1), 8, 2 }, | |
170 | { pinmux(1), 8, 1 }, | |
171 | { pinmux(1), 8, 0 }, | |
172 | { pinmux(0), 8, 7 }, | |
173 | { pinmux(0), 8, 6 }, | |
174 | { pinmux(0), 8, 5 }, | |
175 | { pinmux(0), 8, 4 }, | |
176 | { pinmux(0), 8, 3 }, | |
177 | { pinmux(0), 8, 2 }, | |
178 | { pinmux(0), 8, 1 }, | |
179 | { pinmux(0), 8, 0 }, | |
180 | { pinmux(4), 8, 7 }, /* GP1[0] */ | |
181 | { pinmux(4), 8, 6 }, | |
182 | { pinmux(4), 8, 5 }, | |
183 | { pinmux(4), 8, 4 }, | |
184 | { pinmux(4), 8, 3 }, | |
185 | { pinmux(4), 8, 2 }, | |
186 | { pinmux(4), 4, 1 }, | |
187 | { pinmux(4), 4, 0 }, | |
188 | { pinmux(3), 4, 0 }, | |
189 | { pinmux(2), 4, 6 }, | |
190 | { pinmux(2), 4, 5 }, | |
191 | { pinmux(2), 4, 4 }, | |
192 | { pinmux(2), 4, 3 }, | |
193 | { pinmux(2), 4, 2 }, | |
194 | { pinmux(2), 4, 1 }, | |
195 | { pinmux(2), 8, 0 }, | |
196 | { pinmux(6), 8, 7 }, /* GP2[0] */ | |
197 | { pinmux(6), 8, 6 }, | |
198 | { pinmux(6), 8, 5 }, | |
199 | { pinmux(6), 8, 4 }, | |
200 | { pinmux(6), 8, 3 }, | |
201 | { pinmux(6), 8, 2 }, | |
202 | { pinmux(6), 8, 1 }, | |
203 | { pinmux(6), 8, 0 }, | |
204 | { pinmux(5), 8, 7 }, | |
205 | { pinmux(5), 8, 6 }, | |
206 | { pinmux(5), 8, 5 }, | |
207 | { pinmux(5), 8, 4 }, | |
208 | { pinmux(5), 8, 3 }, | |
209 | { pinmux(5), 8, 2 }, | |
210 | { pinmux(5), 8, 1 }, | |
211 | { pinmux(5), 8, 0 }, | |
212 | { pinmux(8), 8, 7 }, /* GP3[0] */ | |
213 | { pinmux(8), 8, 6 }, | |
214 | { pinmux(8), 8, 5 }, | |
215 | { pinmux(8), 8, 4 }, | |
216 | { pinmux(8), 8, 3 }, | |
217 | { pinmux(8), 8, 2 }, | |
218 | { pinmux(8), 8, 1 }, | |
219 | { pinmux(8), 8, 0 }, | |
220 | { pinmux(7), 8, 7 }, | |
221 | { pinmux(7), 8, 6 }, | |
222 | { pinmux(7), 8, 5 }, | |
223 | { pinmux(7), 8, 4 }, | |
224 | { pinmux(7), 8, 3 }, | |
225 | { pinmux(7), 8, 2 }, | |
226 | { pinmux(7), 8, 1 }, | |
227 | { pinmux(7), 8, 0 }, | |
228 | { pinmux(10), 8, 7 }, /* GP4[0] */ | |
229 | { pinmux(10), 8, 6 }, | |
230 | { pinmux(10), 8, 5 }, | |
231 | { pinmux(10), 8, 4 }, | |
232 | { pinmux(10), 8, 3 }, | |
233 | { pinmux(10), 8, 2 }, | |
234 | { pinmux(10), 8, 1 }, | |
235 | { pinmux(10), 8, 0 }, | |
236 | { pinmux(9), 8, 7 }, | |
237 | { pinmux(9), 8, 6 }, | |
238 | { pinmux(9), 8, 5 }, | |
239 | { pinmux(9), 8, 4 }, | |
240 | { pinmux(9), 8, 3 }, | |
241 | { pinmux(9), 8, 2 }, | |
242 | { pinmux(9), 8, 1 }, | |
243 | { pinmux(9), 8, 0 }, | |
244 | { pinmux(12), 8, 7 }, /* GP5[0] */ | |
245 | { pinmux(12), 8, 6 }, | |
246 | { pinmux(12), 8, 5 }, | |
247 | { pinmux(12), 8, 4 }, | |
248 | { pinmux(12), 8, 3 }, | |
249 | { pinmux(12), 8, 2 }, | |
250 | { pinmux(12), 8, 1 }, | |
251 | { pinmux(12), 8, 0 }, | |
252 | { pinmux(11), 8, 7 }, | |
253 | { pinmux(11), 8, 6 }, | |
254 | { pinmux(11), 8, 5 }, | |
255 | { pinmux(11), 8, 4 }, | |
256 | { pinmux(11), 8, 3 }, | |
257 | { pinmux(11), 8, 2 }, | |
258 | { pinmux(11), 8, 1 }, | |
259 | { pinmux(11), 8, 0 }, | |
260 | { pinmux(19), 8, 6 }, /* GP6[0] */ | |
261 | { pinmux(19), 8, 5 }, | |
262 | { pinmux(19), 8, 4 }, | |
263 | { pinmux(19), 8, 3 }, | |
264 | { pinmux(19), 8, 2 }, | |
265 | { pinmux(16), 8, 1 }, | |
266 | { pinmux(14), 8, 1 }, | |
267 | { pinmux(14), 8, 0 }, | |
268 | { pinmux(13), 8, 7 }, | |
269 | { pinmux(13), 8, 6 }, | |
270 | { pinmux(13), 8, 5 }, | |
271 | { pinmux(13), 8, 4 }, | |
272 | { pinmux(13), 8, 3 }, | |
273 | { pinmux(13), 8, 2 }, | |
274 | { pinmux(13), 8, 1 }, | |
275 | { pinmux(13), 8, 0 }, | |
276 | { pinmux(18), 8, 1 }, /* GP7[0] */ | |
277 | { pinmux(18), 8, 0 }, | |
278 | { pinmux(17), 8, 7 }, | |
279 | { pinmux(17), 8, 6 }, | |
280 | { pinmux(17), 8, 5 }, | |
281 | { pinmux(17), 8, 4 }, | |
282 | { pinmux(17), 8, 3 }, | |
283 | { pinmux(17), 8, 2 }, | |
284 | { pinmux(17), 8, 1 }, | |
285 | { pinmux(17), 8, 0 }, | |
286 | { pinmux(16), 8, 7 }, | |
287 | { pinmux(16), 8, 6 }, | |
288 | { pinmux(16), 8, 5 }, | |
289 | { pinmux(16), 8, 4 }, | |
290 | { pinmux(16), 8, 3 }, | |
291 | { pinmux(16), 8, 2 }, | |
292 | { pinmux(19), 8, 0 }, /* GP8[0] */ | |
293 | { pinmux(3), 4, 7 }, | |
294 | { pinmux(3), 4, 6 }, | |
295 | { pinmux(3), 4, 5 }, | |
296 | { pinmux(3), 4, 4 }, | |
297 | { pinmux(3), 4, 3 }, | |
298 | { pinmux(3), 4, 2 }, | |
299 | { pinmux(2), 4, 7 }, | |
300 | { pinmux(19), 8, 1 }, | |
301 | { pinmux(19), 8, 0 }, | |
302 | { pinmux(18), 8, 7 }, | |
303 | { pinmux(18), 8, 6 }, | |
304 | { pinmux(18), 8, 5 }, | |
305 | { pinmux(18), 8, 4 }, | |
306 | { pinmux(18), 8, 3 }, | |
307 | { pinmux(18), 8, 2 }, | |
308 | }; | |
76b40ab4 TR |
309 | #endif /* CONFIG_SOC_DA8XX && !CONFIG_SOC_DA850 */ |
310 | #else /* !CONFIG_SOC_DA8XX */ | |
03414ac4 | 311 | #define davinci_configure_pin_mux(a, b) |
76b40ab4 | 312 | #endif /* CONFIG_SOC_DA8XX */ |
f517afd5 | 313 | |
8e51c0f2 | 314 | int gpio_request(unsigned int gpio, const char *label) |
f517afd5 | 315 | { |
365d6070 | 316 | if (gpio >= MAX_NUM_GPIOS) |
f517afd5 LW |
317 | return -1; |
318 | ||
365d6070 | 319 | if (gpio_registry[gpio].is_registered) |
f517afd5 LW |
320 | return -1; |
321 | ||
365d6070 JH |
322 | gpio_registry[gpio].is_registered = 1; |
323 | strncpy(gpio_registry[gpio].name, label, GPIO_NAME_SIZE); | |
324 | gpio_registry[gpio].name[GPIO_NAME_SIZE - 1] = 0; | |
f517afd5 | 325 | |
365d6070 | 326 | davinci_configure_pin_mux(&gpio_pinmux[gpio], 1); |
f517afd5 LW |
327 | |
328 | return 0; | |
329 | } | |
330 | ||
8e51c0f2 | 331 | int gpio_free(unsigned int gpio) |
f517afd5 | 332 | { |
365d6070 JH |
333 | if (gpio >= MAX_NUM_GPIOS) |
334 | return -1; | |
f517afd5 | 335 | |
365d6070 JH |
336 | if (!gpio_registry[gpio].is_registered) |
337 | return -1; | |
338 | ||
339 | gpio_registry[gpio].is_registered = 0; | |
340 | gpio_registry[gpio].name[0] = '\0'; | |
341 | /* Do not configure as input or change pin mux here */ | |
342 | return 0; | |
f517afd5 | 343 | } |
8e51c0f2 | 344 | #endif |
f517afd5 | 345 | |
8e51c0f2 | 346 | static int _gpio_direction_input(struct davinci_gpio *bank, unsigned int gpio) |
f517afd5 | 347 | { |
8e51c0f2 | 348 | setbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); |
f517afd5 LW |
349 | return 0; |
350 | } | |
351 | ||
8e51c0f2 | 352 | static int _gpio_get_value(struct davinci_gpio *bank, unsigned int gpio) |
f517afd5 | 353 | { |
f517afd5 | 354 | unsigned int ip; |
365d6070 | 355 | ip = in_le32(&bank->in_data) & (1U << GPIO_BIT(gpio)); |
f517afd5 LW |
356 | return ip ? 1 : 0; |
357 | } | |
358 | ||
8e51c0f2 | 359 | static int _gpio_set_value(struct davinci_gpio *bank, unsigned int gpio, int value) |
f517afd5 | 360 | { |
f517afd5 | 361 | if (value) |
365d6070 | 362 | bank->set_data = 1U << GPIO_BIT(gpio); |
f517afd5 | 363 | else |
365d6070 JH |
364 | bank->clr_data = 1U << GPIO_BIT(gpio); |
365 | ||
366 | return 0; | |
f517afd5 LW |
367 | } |
368 | ||
8e51c0f2 AF |
369 | static int _gpio_get_dir(struct davinci_gpio *bank, unsigned int gpio) |
370 | { | |
371 | return in_le32(&bank->dir) & (1U << GPIO_BIT(gpio)); | |
372 | } | |
373 | ||
3135022c K |
374 | static int _gpio_direction_output(struct davinci_gpio *bank, unsigned int gpio, |
375 | int value) | |
376 | { | |
377 | clrbits_le32(&bank->dir, 1U << GPIO_BIT(gpio)); | |
378 | _gpio_set_value(bank, gpio, value); | |
379 | return 0; | |
380 | } | |
bcee8d67 SG |
381 | |
382 | #if !CONFIG_IS_ENABLED(DM_GPIO) | |
8e51c0f2 | 383 | |
f517afd5 LW |
384 | void gpio_info(void) |
385 | { | |
8e51c0f2 | 386 | unsigned int gpio, dir, val; |
f517afd5 LW |
387 | struct davinci_gpio *bank; |
388 | ||
365d6070 JH |
389 | for (gpio = 0; gpio < MAX_NUM_GPIOS; ++gpio) { |
390 | bank = GPIO_BANK(gpio); | |
8e51c0f2 | 391 | dir = _gpio_get_dir(bank, gpio); |
365d6070 | 392 | val = gpio_get_value(gpio); |
f517afd5 LW |
393 | |
394 | printf("% 4d: %s: %d [%c] %s\n", | |
365d6070 JH |
395 | gpio, dir ? " in" : "out", val, |
396 | gpio_registry[gpio].is_registered ? 'x' : ' ', | |
397 | gpio_registry[gpio].name); | |
f517afd5 LW |
398 | } |
399 | } | |
8e51c0f2 AF |
400 | |
401 | int gpio_direction_input(unsigned int gpio) | |
402 | { | |
403 | struct davinci_gpio *bank; | |
404 | ||
405 | bank = GPIO_BANK(gpio); | |
406 | return _gpio_direction_input(bank, gpio); | |
407 | } | |
408 | ||
409 | int gpio_direction_output(unsigned int gpio, int value) | |
410 | { | |
411 | struct davinci_gpio *bank; | |
412 | ||
413 | bank = GPIO_BANK(gpio); | |
414 | return _gpio_direction_output(bank, gpio, value); | |
415 | } | |
416 | ||
417 | int gpio_get_value(unsigned int gpio) | |
418 | { | |
419 | struct davinci_gpio *bank; | |
420 | ||
421 | bank = GPIO_BANK(gpio); | |
422 | return _gpio_get_value(bank, gpio); | |
423 | } | |
424 | ||
425 | int gpio_set_value(unsigned int gpio, int value) | |
426 | { | |
427 | struct davinci_gpio *bank; | |
428 | ||
429 | bank = GPIO_BANK(gpio); | |
430 | return _gpio_set_value(bank, gpio, value); | |
431 | } | |
432 | ||
bcee8d67 | 433 | #else /* DM_GPIO */ |
8e51c0f2 AF |
434 | |
435 | static struct davinci_gpio *davinci_get_gpio_bank(struct udevice *dev, unsigned int offset) | |
436 | { | |
437 | struct davinci_gpio_bank *bank = dev_get_priv(dev); | |
94f992d5 | 438 | unsigned long addr; |
8e51c0f2 | 439 | |
1eddf549 AF |
440 | /* |
441 | * The device tree is not broken into banks but the infrastructure is | |
8e51c0f2 AF |
442 | * expecting it this way, so we'll first include the 0x10 offset, then |
443 | * calculate the bank manually based on the offset. | |
1eddf549 | 444 | * Casting 'addr' as Unsigned long is needed to make the math work. |
8e51c0f2 | 445 | */ |
1eddf549 AF |
446 | addr = ((unsigned long)(struct davinci_gpio *)bank->base) + |
447 | 0x10 + (0x28 * (offset >> 5)); | |
448 | return (struct davinci_gpio *)addr; | |
8e51c0f2 AF |
449 | } |
450 | ||
451 | static int davinci_gpio_direction_input(struct udevice *dev, unsigned int offset) | |
452 | { | |
453 | struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); | |
454 | ||
1eddf549 AF |
455 | /* |
456 | * Fetch the address based on GPIO, but only pass the masked low 32-bits | |
457 | */ | |
458 | _gpio_direction_input(base, (offset & 0x1f)); | |
8e51c0f2 AF |
459 | return 0; |
460 | } | |
461 | ||
462 | static int davinci_gpio_direction_output(struct udevice *dev, unsigned int offset, | |
463 | int value) | |
464 | { | |
465 | struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); | |
466 | ||
1eddf549 | 467 | _gpio_direction_output(base, (offset & 0x1f), value); |
8e51c0f2 AF |
468 | return 0; |
469 | } | |
470 | ||
471 | static int davinci_gpio_get_value(struct udevice *dev, unsigned int offset) | |
472 | { | |
473 | struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); | |
474 | ||
1eddf549 | 475 | return _gpio_get_value(base, (offset & 0x1f)); |
8e51c0f2 AF |
476 | } |
477 | ||
478 | static int davinci_gpio_set_value(struct udevice *dev, unsigned int offset, | |
479 | int value) | |
480 | { | |
481 | struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); | |
482 | ||
1eddf549 | 483 | _gpio_set_value(base, (offset & 0x1f), value); |
8e51c0f2 AF |
484 | |
485 | return 0; | |
486 | } | |
487 | ||
488 | static int davinci_gpio_get_function(struct udevice *dev, unsigned int offset) | |
489 | { | |
490 | unsigned int dir; | |
491 | struct davinci_gpio *base = davinci_get_gpio_bank(dev, offset); | |
492 | ||
493 | dir = _gpio_get_dir(base, offset); | |
494 | ||
495 | if (dir) | |
496 | return GPIOF_INPUT; | |
497 | ||
498 | return GPIOF_OUTPUT; | |
499 | } | |
500 | ||
9440b3d3 AF |
501 | static int davinci_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, |
502 | struct ofnode_phandle_args *args) | |
503 | { | |
504 | desc->offset = args->args[0]; | |
505 | ||
506 | if (args->args[1] & GPIO_ACTIVE_LOW) | |
507 | desc->flags = GPIOD_ACTIVE_LOW; | |
508 | else | |
509 | desc->flags = 0; | |
510 | return 0; | |
511 | } | |
512 | ||
8e51c0f2 AF |
513 | static const struct dm_gpio_ops gpio_davinci_ops = { |
514 | .direction_input = davinci_gpio_direction_input, | |
515 | .direction_output = davinci_gpio_direction_output, | |
516 | .get_value = davinci_gpio_get_value, | |
517 | .set_value = davinci_gpio_set_value, | |
518 | .get_function = davinci_gpio_get_function, | |
9440b3d3 | 519 | .xlate = davinci_gpio_xlate, |
8e51c0f2 AF |
520 | }; |
521 | ||
522 | static int davinci_gpio_probe(struct udevice *dev) | |
523 | { | |
524 | struct davinci_gpio_bank *bank = dev_get_priv(dev); | |
8a8d24bd | 525 | struct davinci_gpio_plat *plat = dev_get_plat(dev); |
8e51c0f2 AF |
526 | struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); |
527 | const void *fdt = gd->fdt_blob; | |
528 | int node = dev_of_offset(dev); | |
529 | ||
530 | uc_priv->bank_name = plat->port_name; | |
531 | uc_priv->gpio_count = fdtdec_get_int(fdt, node, "ti,ngpio", -1); | |
532 | bank->base = (struct davinci_gpio *)plat->base; | |
533 | return 0; | |
534 | } | |
535 | ||
536 | static const struct udevice_id davinci_gpio_ids[] = { | |
537 | { .compatible = "ti,dm6441-gpio" }, | |
401d74cb | 538 | { .compatible = "ti,k2g-gpio" }, |
25216d68 | 539 | { .compatible = "ti,keystone-gpio" }, |
8e51c0f2 AF |
540 | { } |
541 | }; | |
542 | ||
d1998a9f | 543 | static int davinci_gpio_of_to_plat(struct udevice *dev) |
8e51c0f2 | 544 | { |
8a8d24bd | 545 | struct davinci_gpio_plat *plat = dev_get_plat(dev); |
8e51c0f2 | 546 | fdt_addr_t addr; |
b6e59617 | 547 | char name[18], *str; |
8e51c0f2 | 548 | |
2548493a | 549 | addr = dev_read_addr(dev); |
8e51c0f2 AF |
550 | if (addr == FDT_ADDR_T_NONE) |
551 | return -EINVAL; | |
552 | ||
553 | plat->base = addr; | |
b6e59617 | 554 | |
555 | sprintf(name, "gpio@%4x_", (unsigned int)plat->base); | |
556 | str = strdup(name); | |
557 | if (!str) | |
558 | return -ENOMEM; | |
559 | plat->port_name = str; | |
560 | ||
8e51c0f2 AF |
561 | return 0; |
562 | } | |
563 | ||
e3e2470f WL |
564 | U_BOOT_DRIVER(ti_dm6441_gpio) = { |
565 | .name = "ti_dm6441_gpio", | |
8e51c0f2 AF |
566 | .id = UCLASS_GPIO, |
567 | .ops = &gpio_davinci_ops, | |
d1998a9f | 568 | .of_to_plat = of_match_ptr(davinci_gpio_of_to_plat), |
8e51c0f2 AF |
569 | .of_match = davinci_gpio_ids, |
570 | .bind = dm_scan_fdt_dev, | |
8a8d24bd | 571 | .plat_auto = sizeof(struct davinci_gpio_plat), |
8e51c0f2 | 572 | .probe = davinci_gpio_probe, |
41575d8e | 573 | .priv_auto = sizeof(struct davinci_gpio_bank), |
8e51c0f2 AF |
574 | }; |
575 | ||
576 | #endif |