]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
ea8fbba7 | 2 | /* |
39b787ec | 3 | * Copyright (C) 2013 Bo Shen <[email protected]> |
ea8fbba7 JS |
4 | * |
5 | * Copyright (C) 2009 Jens Scharsig ([email protected]) | |
6 | * | |
7 | * Copyright (C) 2005 HP Labs | |
ea8fbba7 JS |
8 | */ |
9 | ||
10 | #include <config.h> | |
11 | #include <common.h> | |
f2f3c157 | 12 | #include <clk.h> |
918354b1 | 13 | #include <dm.h> |
86592f60 | 14 | #include <asm/io.h> |
1ace4022 | 15 | #include <linux/sizes.h> |
918354b1 | 16 | #include <asm/gpio.h> |
ea8fbba7 | 17 | #include <asm/arch/hardware.h> |
ea8fbba7 | 18 | #include <asm/arch/at91_pio.h> |
918354b1 SG |
19 | |
20 | #define GPIO_PER_BANK 32 | |
ea8fbba7 | 21 | |
4bc9b7a5 BS |
22 | static struct at91_port *at91_pio_get_port(unsigned port) |
23 | { | |
24 | switch (port) { | |
25 | case AT91_PIO_PORTA: | |
26 | return (struct at91_port *)ATMEL_BASE_PIOA; | |
27 | case AT91_PIO_PORTB: | |
28 | return (struct at91_port *)ATMEL_BASE_PIOB; | |
29 | case AT91_PIO_PORTC: | |
30 | return (struct at91_port *)ATMEL_BASE_PIOC; | |
31 | #if (ATMEL_PIO_PORTS > 3) | |
32 | case AT91_PIO_PORTD: | |
33 | return (struct at91_port *)ATMEL_BASE_PIOD; | |
34 | #if (ATMEL_PIO_PORTS > 4) | |
35 | case AT91_PIO_PORTE: | |
36 | return (struct at91_port *)ATMEL_BASE_PIOE; | |
37 | #endif | |
38 | #endif | |
39 | default: | |
7d82d897 | 40 | printf("Error: at91_gpio: Fail to get PIO base!\n"); |
4bc9b7a5 BS |
41 | return NULL; |
42 | } | |
43 | } | |
44 | ||
918354b1 SG |
45 | static void at91_set_port_pullup(struct at91_port *at91_port, unsigned offset, |
46 | int use_pullup) | |
47 | { | |
48 | u32 mask; | |
49 | ||
50 | mask = 1 << offset; | |
51 | if (use_pullup) | |
52 | writel(mask, &at91_port->puer); | |
53 | else | |
54 | writel(mask, &at91_port->pudr); | |
55 | writel(mask, &at91_port->per); | |
56 | } | |
57 | ||
ea8fbba7 JS |
58 | int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) |
59 | { | |
4bc9b7a5 | 60 | struct at91_port *at91_port = at91_pio_get_port(port); |
ea8fbba7 | 61 | |
918354b1 SG |
62 | if (at91_port && (pin < GPIO_PER_BANK)) |
63 | at91_set_port_pullup(at91_port, pin, use_pullup); | |
4bc9b7a5 | 64 | |
ea8fbba7 JS |
65 | return 0; |
66 | } | |
67 | ||
68 | /* | |
69 | * mux the pin to the "GPIO" peripheral role. | |
70 | */ | |
71 | int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup) | |
72 | { | |
4bc9b7a5 BS |
73 | struct at91_port *at91_port = at91_pio_get_port(port); |
74 | u32 mask; | |
ea8fbba7 | 75 | |
918354b1 | 76 | if (at91_port && (pin < GPIO_PER_BANK)) { |
ea8fbba7 | 77 | mask = 1 << pin; |
4bc9b7a5 | 78 | writel(mask, &at91_port->idr); |
ea8fbba7 | 79 | at91_set_pio_pullup(port, pin, use_pullup); |
4bc9b7a5 | 80 | writel(mask, &at91_port->per); |
ea8fbba7 | 81 | } |
4bc9b7a5 | 82 | |
ea8fbba7 JS |
83 | return 0; |
84 | } | |
85 | ||
86 | /* | |
87 | * mux the pin to the "A" internal peripheral role. | |
88 | */ | |
89 | int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup) | |
90 | { | |
4bc9b7a5 BS |
91 | struct at91_port *at91_port = at91_pio_get_port(port); |
92 | u32 mask; | |
ea8fbba7 | 93 | |
918354b1 | 94 | if (at91_port && (pin < GPIO_PER_BANK)) { |
ea8fbba7 | 95 | mask = 1 << pin; |
4bc9b7a5 | 96 | writel(mask, &at91_port->idr); |
ea8fbba7 | 97 | at91_set_pio_pullup(port, pin, use_pullup); |
2dc63f73 | 98 | writel(mask, &at91_port->mux.pio2.asr); |
4bc9b7a5 | 99 | writel(mask, &at91_port->pdr); |
ea8fbba7 | 100 | } |
4bc9b7a5 | 101 | |
ea8fbba7 JS |
102 | return 0; |
103 | } | |
104 | ||
105 | /* | |
106 | * mux the pin to the "B" internal peripheral role. | |
107 | */ | |
108 | int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup) | |
109 | { | |
4bc9b7a5 BS |
110 | struct at91_port *at91_port = at91_pio_get_port(port); |
111 | u32 mask; | |
ea8fbba7 | 112 | |
918354b1 | 113 | if (at91_port && (pin < GPIO_PER_BANK)) { |
ea8fbba7 | 114 | mask = 1 << pin; |
4bc9b7a5 | 115 | writel(mask, &at91_port->idr); |
ea8fbba7 | 116 | at91_set_pio_pullup(port, pin, use_pullup); |
2dc63f73 | 117 | writel(mask, &at91_port->mux.pio2.bsr); |
4bc9b7a5 | 118 | writel(mask, &at91_port->pdr); |
ea8fbba7 | 119 | } |
4bc9b7a5 | 120 | |
ea8fbba7 JS |
121 | return 0; |
122 | } | |
123 | ||
2dc63f73 WY |
124 | /* |
125 | * mux the pin to the "A" internal peripheral role. | |
126 | */ | |
127 | int at91_pio3_set_a_periph(unsigned port, unsigned pin, int use_pullup) | |
128 | { | |
129 | struct at91_port *at91_port = at91_pio_get_port(port); | |
130 | u32 mask; | |
131 | ||
132 | if (at91_port && (pin < GPIO_PER_BANK)) { | |
133 | mask = 1 << pin; | |
134 | writel(mask, &at91_port->idr); | |
135 | at91_set_pio_pullup(port, pin, use_pullup); | |
136 | writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask, | |
137 | &at91_port->mux.pio3.abcdsr1); | |
138 | writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask, | |
139 | &at91_port->mux.pio3.abcdsr2); | |
140 | ||
141 | writel(mask, &at91_port->pdr); | |
142 | } | |
143 | ||
144 | return 0; | |
145 | } | |
146 | ||
147 | /* | |
148 | * mux the pin to the "B" internal peripheral role. | |
149 | */ | |
150 | int at91_pio3_set_b_periph(unsigned port, unsigned pin, int use_pullup) | |
151 | { | |
152 | struct at91_port *at91_port = at91_pio_get_port(port); | |
153 | u32 mask; | |
154 | ||
155 | if (at91_port && (pin < GPIO_PER_BANK)) { | |
156 | mask = 1 << pin; | |
157 | writel(mask, &at91_port->idr); | |
158 | at91_set_pio_pullup(port, pin, use_pullup); | |
159 | writel(readl(&at91_port->mux.pio3.abcdsr1) | mask, | |
160 | &at91_port->mux.pio3.abcdsr1); | |
161 | writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask, | |
162 | &at91_port->mux.pio3.abcdsr2); | |
163 | ||
164 | writel(mask, &at91_port->pdr); | |
165 | } | |
166 | ||
167 | return 0; | |
168 | } | |
2b3b1c66 BS |
169 | /* |
170 | * mux the pin to the "C" internal peripheral role. | |
171 | */ | |
2dc63f73 | 172 | int at91_pio3_set_c_periph(unsigned port, unsigned pin, int use_pullup) |
2b3b1c66 | 173 | { |
4bc9b7a5 BS |
174 | struct at91_port *at91_port = at91_pio_get_port(port); |
175 | u32 mask; | |
2b3b1c66 | 176 | |
918354b1 | 177 | if (at91_port && (pin < GPIO_PER_BANK)) { |
2b3b1c66 | 178 | mask = 1 << pin; |
4bc9b7a5 | 179 | writel(mask, &at91_port->idr); |
2b3b1c66 | 180 | at91_set_pio_pullup(port, pin, use_pullup); |
2dc63f73 WY |
181 | writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask, |
182 | &at91_port->mux.pio3.abcdsr1); | |
183 | writel(readl(&at91_port->mux.pio3.abcdsr2) | mask, | |
184 | &at91_port->mux.pio3.abcdsr2); | |
4bc9b7a5 | 185 | writel(mask, &at91_port->pdr); |
2b3b1c66 | 186 | } |
4bc9b7a5 | 187 | |
2b3b1c66 BS |
188 | return 0; |
189 | } | |
190 | ||
191 | /* | |
192 | * mux the pin to the "D" internal peripheral role. | |
193 | */ | |
2dc63f73 | 194 | int at91_pio3_set_d_periph(unsigned port, unsigned pin, int use_pullup) |
2b3b1c66 | 195 | { |
4bc9b7a5 BS |
196 | struct at91_port *at91_port = at91_pio_get_port(port); |
197 | u32 mask; | |
2b3b1c66 | 198 | |
918354b1 | 199 | if (at91_port && (pin < GPIO_PER_BANK)) { |
2b3b1c66 | 200 | mask = 1 << pin; |
4bc9b7a5 | 201 | writel(mask, &at91_port->idr); |
2b3b1c66 | 202 | at91_set_pio_pullup(port, pin, use_pullup); |
2dc63f73 WY |
203 | writel(readl(&at91_port->mux.pio3.abcdsr1) | mask, |
204 | &at91_port->mux.pio3.abcdsr1); | |
205 | writel(readl(&at91_port->mux.pio3.abcdsr2) | mask, | |
206 | &at91_port->mux.pio3.abcdsr2); | |
4bc9b7a5 | 207 | writel(mask, &at91_port->pdr); |
2b3b1c66 | 208 | } |
4bc9b7a5 | 209 | |
2b3b1c66 BS |
210 | return 0; |
211 | } | |
2b3b1c66 | 212 | |
918354b1 SG |
213 | #ifdef CONFIG_DM_GPIO |
214 | static bool at91_get_port_output(struct at91_port *at91_port, int offset) | |
215 | { | |
216 | u32 mask, val; | |
217 | ||
218 | mask = 1 << offset; | |
219 | val = readl(&at91_port->osr); | |
220 | return val & mask; | |
221 | } | |
222 | #endif | |
223 | ||
224 | static void at91_set_port_input(struct at91_port *at91_port, int offset, | |
225 | int use_pullup) | |
226 | { | |
227 | u32 mask; | |
228 | ||
229 | mask = 1 << offset; | |
230 | writel(mask, &at91_port->idr); | |
231 | at91_set_port_pullup(at91_port, offset, use_pullup); | |
232 | writel(mask, &at91_port->odr); | |
233 | writel(mask, &at91_port->per); | |
234 | } | |
235 | ||
ea8fbba7 JS |
236 | /* |
237 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and | |
238 | * configure it for an input. | |
239 | */ | |
240 | int at91_set_pio_input(unsigned port, u32 pin, int use_pullup) | |
241 | { | |
4bc9b7a5 | 242 | struct at91_port *at91_port = at91_pio_get_port(port); |
ea8fbba7 | 243 | |
918354b1 SG |
244 | if (at91_port && (pin < GPIO_PER_BANK)) |
245 | at91_set_port_input(at91_port, pin, use_pullup); | |
4bc9b7a5 | 246 | |
ea8fbba7 JS |
247 | return 0; |
248 | } | |
249 | ||
918354b1 SG |
250 | static void at91_set_port_output(struct at91_port *at91_port, int offset, |
251 | int value) | |
252 | { | |
253 | u32 mask; | |
254 | ||
255 | mask = 1 << offset; | |
256 | writel(mask, &at91_port->idr); | |
257 | writel(mask, &at91_port->pudr); | |
258 | if (value) | |
259 | writel(mask, &at91_port->sodr); | |
260 | else | |
261 | writel(mask, &at91_port->codr); | |
262 | writel(mask, &at91_port->oer); | |
263 | writel(mask, &at91_port->per); | |
264 | } | |
265 | ||
ea8fbba7 JS |
266 | /* |
267 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), | |
268 | * and configure it for an output. | |
269 | */ | |
270 | int at91_set_pio_output(unsigned port, u32 pin, int value) | |
271 | { | |
4bc9b7a5 | 272 | struct at91_port *at91_port = at91_pio_get_port(port); |
ea8fbba7 | 273 | |
918354b1 SG |
274 | if (at91_port && (pin < GPIO_PER_BANK)) |
275 | at91_set_port_output(at91_port, pin, value); | |
4bc9b7a5 | 276 | |
ea8fbba7 JS |
277 | return 0; |
278 | } | |
279 | ||
280 | /* | |
281 | * enable/disable the glitch filter. mostly used with IRQ handling. | |
282 | */ | |
283 | int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on) | |
284 | { | |
4bc9b7a5 BS |
285 | struct at91_port *at91_port = at91_pio_get_port(port); |
286 | u32 mask; | |
ea8fbba7 | 287 | |
2dc63f73 WY |
288 | if (at91_port && (pin < GPIO_PER_BANK)) { |
289 | mask = 1 << pin; | |
290 | if (is_on) | |
291 | writel(mask, &at91_port->ifer); | |
292 | else | |
293 | writel(mask, &at91_port->ifdr); | |
294 | } | |
295 | ||
296 | return 0; | |
297 | } | |
298 | ||
299 | /* | |
300 | * enable/disable the glitch filter. mostly used with IRQ handling. | |
301 | */ | |
302 | int at91_pio3_set_pio_deglitch(unsigned port, unsigned pin, int is_on) | |
303 | { | |
304 | struct at91_port *at91_port = at91_pio_get_port(port); | |
305 | u32 mask; | |
306 | ||
918354b1 | 307 | if (at91_port && (pin < GPIO_PER_BANK)) { |
ea8fbba7 | 308 | mask = 1 << pin; |
2b3b1c66 | 309 | if (is_on) { |
2dc63f73 | 310 | writel(mask, &at91_port->mux.pio3.ifscdr); |
4bc9b7a5 | 311 | writel(mask, &at91_port->ifer); |
2b3b1c66 | 312 | } else { |
4bc9b7a5 | 313 | writel(mask, &at91_port->ifdr); |
2b3b1c66 BS |
314 | } |
315 | } | |
4bc9b7a5 | 316 | |
2b3b1c66 BS |
317 | return 0; |
318 | } | |
319 | ||
2b3b1c66 BS |
320 | /* |
321 | * enable/disable the debounce filter. | |
322 | */ | |
2dc63f73 | 323 | int at91_pio3_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) |
2b3b1c66 | 324 | { |
4bc9b7a5 BS |
325 | struct at91_port *at91_port = at91_pio_get_port(port); |
326 | u32 mask; | |
2b3b1c66 | 327 | |
918354b1 | 328 | if (at91_port && (pin < GPIO_PER_BANK)) { |
2b3b1c66 BS |
329 | mask = 1 << pin; |
330 | if (is_on) { | |
2dc63f73 WY |
331 | writel(mask, &at91_port->mux.pio3.ifscer); |
332 | writel(div & PIO_SCDR_DIV, &at91_port->mux.pio3.scdr); | |
4bc9b7a5 | 333 | writel(mask, &at91_port->ifer); |
2b3b1c66 | 334 | } else { |
4bc9b7a5 | 335 | writel(mask, &at91_port->ifdr); |
2b3b1c66 BS |
336 | } |
337 | } | |
4bc9b7a5 | 338 | |
2b3b1c66 BS |
339 | return 0; |
340 | } | |
341 | ||
342 | /* | |
343 | * enable/disable the pull-down. | |
344 | * If pull-up already enabled while calling the function, we disable it. | |
345 | */ | |
2dc63f73 | 346 | int at91_pio3_set_pio_pulldown(unsigned port, unsigned pin, int is_on) |
2b3b1c66 | 347 | { |
4bc9b7a5 BS |
348 | struct at91_port *at91_port = at91_pio_get_port(port); |
349 | u32 mask; | |
2b3b1c66 | 350 | |
918354b1 | 351 | if (at91_port && (pin < GPIO_PER_BANK)) { |
2b3b1c66 | 352 | mask = 1 << pin; |
152ac5fa MV |
353 | if (is_on) { |
354 | at91_set_pio_pullup(port, pin, 0); | |
2dc63f73 | 355 | writel(mask, &at91_port->mux.pio3.ppder); |
152ac5fa | 356 | } else |
2dc63f73 | 357 | writel(mask, &at91_port->mux.pio3.ppddr); |
2b3b1c66 | 358 | } |
4bc9b7a5 | 359 | |
2b3b1c66 BS |
360 | return 0; |
361 | } | |
362 | ||
2dc63f73 WY |
363 | int at91_pio3_set_pio_pullup(unsigned port, unsigned pin, int use_pullup) |
364 | { | |
365 | struct at91_port *at91_port = at91_pio_get_port(port); | |
366 | ||
367 | if (use_pullup) | |
368 | at91_pio3_set_pio_pulldown(port, pin, 0); | |
369 | ||
370 | if (at91_port && (pin < GPIO_PER_BANK)) | |
371 | at91_set_port_pullup(at91_port, pin, use_pullup); | |
372 | ||
373 | return 0; | |
374 | } | |
375 | ||
2b3b1c66 BS |
376 | /* |
377 | * disable Schmitt trigger | |
378 | */ | |
2dc63f73 | 379 | int at91_pio3_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) |
2b3b1c66 | 380 | { |
4bc9b7a5 BS |
381 | struct at91_port *at91_port = at91_pio_get_port(port); |
382 | u32 mask; | |
2b3b1c66 | 383 | |
918354b1 | 384 | if (at91_port && (pin < GPIO_PER_BANK)) { |
2b3b1c66 | 385 | mask = 1 << pin; |
4bc9b7a5 BS |
386 | writel(readl(&at91_port->schmitt) | mask, |
387 | &at91_port->schmitt); | |
ea8fbba7 | 388 | } |
4bc9b7a5 | 389 | |
ea8fbba7 JS |
390 | return 0; |
391 | } | |
392 | ||
393 | /* | |
394 | * enable/disable the multi-driver. This is only valid for output and | |
395 | * allows the output pin to run as an open collector output. | |
396 | */ | |
397 | int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) | |
398 | { | |
4bc9b7a5 BS |
399 | struct at91_port *at91_port = at91_pio_get_port(port); |
400 | u32 mask; | |
ea8fbba7 | 401 | |
918354b1 | 402 | if (at91_port && (pin < GPIO_PER_BANK)) { |
ea8fbba7 JS |
403 | mask = 1 << pin; |
404 | if (is_on) | |
4bc9b7a5 | 405 | writel(mask, &at91_port->mder); |
ea8fbba7 | 406 | else |
4bc9b7a5 | 407 | writel(mask, &at91_port->mddr); |
ea8fbba7 | 408 | } |
4bc9b7a5 | 409 | |
ea8fbba7 JS |
410 | return 0; |
411 | } | |
412 | ||
918354b1 SG |
413 | static void at91_set_port_value(struct at91_port *at91_port, int offset, |
414 | int value) | |
415 | { | |
416 | u32 mask; | |
417 | ||
418 | mask = 1 << offset; | |
419 | if (value) | |
420 | writel(mask, &at91_port->sodr); | |
421 | else | |
422 | writel(mask, &at91_port->codr); | |
423 | } | |
424 | ||
ea8fbba7 JS |
425 | /* |
426 | * assuming the pin is muxed as a gpio output, set its value. | |
427 | */ | |
428 | int at91_set_pio_value(unsigned port, unsigned pin, int value) | |
429 | { | |
4bc9b7a5 | 430 | struct at91_port *at91_port = at91_pio_get_port(port); |
ea8fbba7 | 431 | |
918354b1 SG |
432 | if (at91_port && (pin < GPIO_PER_BANK)) |
433 | at91_set_port_value(at91_port, pin, value); | |
4bc9b7a5 | 434 | |
ea8fbba7 JS |
435 | return 0; |
436 | } | |
437 | ||
918354b1 SG |
438 | static int at91_get_port_value(struct at91_port *at91_port, int offset) |
439 | { | |
440 | u32 pdsr = 0, mask; | |
441 | ||
442 | mask = 1 << offset; | |
443 | pdsr = readl(&at91_port->pdsr) & mask; | |
444 | ||
445 | return pdsr != 0; | |
446 | } | |
ea8fbba7 JS |
447 | /* |
448 | * read the pin's value (works even if it's not muxed as a gpio). | |
449 | */ | |
450 | int at91_get_pio_value(unsigned port, unsigned pin) | |
451 | { | |
4bc9b7a5 | 452 | struct at91_port *at91_port = at91_pio_get_port(port); |
ea8fbba7 | 453 | |
918354b1 SG |
454 | if (at91_port && (pin < GPIO_PER_BANK)) |
455 | return at91_get_port_value(at91_port, pin); | |
4bc9b7a5 | 456 | |
918354b1 | 457 | return 0; |
ea8fbba7 | 458 | } |
6edaea87 | 459 | |
918354b1 | 460 | #ifndef CONFIG_DM_GPIO |
6edaea87 BS |
461 | /* Common GPIO API */ |
462 | ||
6edaea87 BS |
463 | int gpio_request(unsigned gpio, const char *label) |
464 | { | |
465 | return 0; | |
466 | } | |
467 | ||
468 | int gpio_free(unsigned gpio) | |
469 | { | |
470 | return 0; | |
471 | } | |
472 | ||
473 | int gpio_direction_input(unsigned gpio) | |
474 | { | |
475 | at91_set_pio_input(at91_gpio_to_port(gpio), | |
476 | at91_gpio_to_pin(gpio), 0); | |
477 | return 0; | |
478 | } | |
479 | ||
480 | int gpio_direction_output(unsigned gpio, int value) | |
481 | { | |
482 | at91_set_pio_output(at91_gpio_to_port(gpio), | |
483 | at91_gpio_to_pin(gpio), value); | |
484 | return 0; | |
485 | } | |
486 | ||
487 | int gpio_get_value(unsigned gpio) | |
488 | { | |
489 | return at91_get_pio_value(at91_gpio_to_port(gpio), | |
490 | at91_gpio_to_pin(gpio)); | |
491 | } | |
492 | ||
493 | int gpio_set_value(unsigned gpio, int value) | |
494 | { | |
495 | at91_set_pio_value(at91_gpio_to_port(gpio), | |
496 | at91_gpio_to_pin(gpio), value); | |
497 | ||
498 | return 0; | |
499 | } | |
918354b1 SG |
500 | #endif |
501 | ||
502 | #ifdef CONFIG_DM_GPIO | |
503 | ||
504 | struct at91_port_priv { | |
505 | struct at91_port *regs; | |
506 | }; | |
507 | ||
508 | /* set GPIO pin 'gpio' as an input */ | |
509 | static int at91_gpio_direction_input(struct udevice *dev, unsigned offset) | |
510 | { | |
d895821f | 511 | struct at91_port_priv *port = dev_get_priv(dev); |
918354b1 SG |
512 | |
513 | at91_set_port_input(port->regs, offset, 0); | |
514 | ||
515 | return 0; | |
516 | } | |
517 | ||
518 | /* set GPIO pin 'gpio' as an output, with polarity 'value' */ | |
519 | static int at91_gpio_direction_output(struct udevice *dev, unsigned offset, | |
520 | int value) | |
521 | { | |
d895821f | 522 | struct at91_port_priv *port = dev_get_priv(dev); |
918354b1 SG |
523 | |
524 | at91_set_port_output(port->regs, offset, value); | |
525 | ||
526 | return 0; | |
527 | } | |
528 | ||
529 | /* read GPIO IN value of pin 'gpio' */ | |
530 | static int at91_gpio_get_value(struct udevice *dev, unsigned offset) | |
531 | { | |
d895821f | 532 | struct at91_port_priv *port = dev_get_priv(dev); |
918354b1 SG |
533 | |
534 | return at91_get_port_value(port->regs, offset); | |
535 | } | |
536 | ||
537 | /* write GPIO OUT value to pin 'gpio' */ | |
538 | static int at91_gpio_set_value(struct udevice *dev, unsigned offset, | |
539 | int value) | |
540 | { | |
d895821f | 541 | struct at91_port_priv *port = dev_get_priv(dev); |
918354b1 SG |
542 | |
543 | at91_set_port_value(port->regs, offset, value); | |
544 | ||
545 | return 0; | |
546 | } | |
547 | ||
548 | static int at91_gpio_get_function(struct udevice *dev, unsigned offset) | |
549 | { | |
d895821f | 550 | struct at91_port_priv *port = dev_get_priv(dev); |
918354b1 SG |
551 | |
552 | /* GPIOF_FUNC is not implemented yet */ | |
553 | if (at91_get_port_output(port->regs, offset)) | |
554 | return GPIOF_OUTPUT; | |
555 | else | |
556 | return GPIOF_INPUT; | |
557 | } | |
558 | ||
559 | static const struct dm_gpio_ops gpio_at91_ops = { | |
560 | .direction_input = at91_gpio_direction_input, | |
561 | .direction_output = at91_gpio_direction_output, | |
562 | .get_value = at91_gpio_get_value, | |
563 | .set_value = at91_gpio_set_value, | |
564 | .get_function = at91_gpio_get_function, | |
565 | }; | |
566 | ||
567 | static int at91_gpio_probe(struct udevice *dev) | |
568 | { | |
569 | struct at91_port_priv *port = dev_get_priv(dev); | |
570 | struct at91_port_platdata *plat = dev_get_platdata(dev); | |
e564f054 | 571 | struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); |
f2f3c157 WY |
572 | struct clk clk; |
573 | int ret; | |
574 | ||
575 | ret = clk_get_by_index(dev, 0, &clk); | |
576 | if (ret) | |
577 | return ret; | |
578 | ||
579 | ret = clk_enable(&clk); | |
580 | if (ret) | |
581 | return ret; | |
582 | ||
583 | clk_free(&clk); | |
918354b1 SG |
584 | |
585 | uc_priv->bank_name = plat->bank_name; | |
586 | uc_priv->gpio_count = GPIO_PER_BANK; | |
cf468880 WY |
587 | |
588 | #if CONFIG_IS_ENABLED(OF_CONTROL) | |
a821c4af | 589 | plat->base_addr = (uint32_t)devfdt_get_addr_ptr(dev); |
cf468880 | 590 | #endif |
918354b1 SG |
591 | port->regs = (struct at91_port *)plat->base_addr; |
592 | ||
593 | return 0; | |
594 | } | |
595 | ||
cf468880 WY |
596 | #if CONFIG_IS_ENABLED(OF_CONTROL) |
597 | static const struct udevice_id at91_gpio_ids[] = { | |
598 | { .compatible = "atmel,at91rm9200-gpio" }, | |
599 | { } | |
600 | }; | |
601 | #endif | |
602 | ||
918354b1 SG |
603 | U_BOOT_DRIVER(gpio_at91) = { |
604 | .name = "gpio_at91", | |
605 | .id = UCLASS_GPIO, | |
cf468880 WY |
606 | #if CONFIG_IS_ENABLED(OF_CONTROL) |
607 | .of_match = at91_gpio_ids, | |
608 | .platdata_auto_alloc_size = sizeof(struct at91_port_platdata), | |
609 | #endif | |
918354b1 SG |
610 | .ops = &gpio_at91_ops, |
611 | .probe = at91_gpio_probe, | |
612 | .priv_auto_alloc_size = sizeof(struct at91_port_priv), | |
613 | }; | |
614 | #endif |