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