blob: 8b766665c689727081eea1e4311498726c2287df [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
3 *
4 * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de)
5 *
6 * Copyright (C) 2005 HP Labs
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11#include <config.h>
12#include <common.h>
13#include <asm/io.h>
14#include <asm/sizes.h>
15#include <asm/arch/hardware.h>
16#include <asm/arch/at91_pio.h>
17#include <asm/arch/gpio.h>
18
19static struct at91_port *at91_pio_get_port(unsigned port)
20{
21 switch (port) {
22 case AT91_PIO_PORTA:
23 return (struct at91_port *)ATMEL_BASE_PIOA;
24 case AT91_PIO_PORTB:
25 return (struct at91_port *)ATMEL_BASE_PIOB;
26 case AT91_PIO_PORTC:
27 return (struct at91_port *)ATMEL_BASE_PIOC;
28#if (ATMEL_PIO_PORTS > 3)
29 case AT91_PIO_PORTD:
30 return (struct at91_port *)ATMEL_BASE_PIOD;
31#if (ATMEL_PIO_PORTS > 4)
32 case AT91_PIO_PORTE:
33 return (struct at91_port *)ATMEL_BASE_PIOE;
34#endif
35#endif
36 default:
37 return NULL;
38 }
39}
40
41int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
42{
43 struct at91_port *at91_port = at91_pio_get_port(port);
44 u32 mask;
45
46 if (at91_port && (pin < 32)) {
47 mask = 1 << pin;
48 if (use_pullup)
49 writel(1 << pin, &at91_port->puer);
50 else
51 writel(1 << pin, &at91_port->pudr);
52 writel(mask, &at91_port->per);
53 }
54
55 return 0;
56}
57
58/*
59 * mux the pin to the "GPIO" peripheral role.
60 */
61int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
62{
63 struct at91_port *at91_port = at91_pio_get_port(port);
64 u32 mask;
65
66 if (at91_port && (pin < 32)) {
67 mask = 1 << pin;
68 writel(mask, &at91_port->idr);
69 at91_set_pio_pullup(port, pin, use_pullup);
70 writel(mask, &at91_port->per);
71 }
72
73 return 0;
74}
75
76/*
77 * mux the pin to the "A" internal peripheral role.
78 */
79int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
80{
81 struct at91_port *at91_port = at91_pio_get_port(port);
82 u32 mask;
83
84 if (at91_port && (pin < 32)) {
85 mask = 1 << pin;
86 writel(mask, &at91_port->idr);
87 at91_set_pio_pullup(port, pin, use_pullup);
88#if defined(CPU_HAS_PIO3)
89 writel(readl(&at91_port->abcdsr1) & ~mask,
90 &at91_port->abcdsr1);
91 writel(readl(&at91_port->abcdsr2) & ~mask,
92 &at91_port->abcdsr2);
93#else
94 writel(mask, &at91_port->asr);
95#endif
96 writel(mask, &at91_port->pdr);
97 }
98
99 return 0;
100}
101
102/*
103 * mux the pin to the "B" internal peripheral role.
104 */
105int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
106{
107 struct at91_port *at91_port = at91_pio_get_port(port);
108 u32 mask;
109
110 if (at91_port && (pin < 32)) {
111 mask = 1 << pin;
112 writel(mask, &at91_port->idr);
113 at91_set_pio_pullup(port, pin, use_pullup);
114#if defined(CPU_HAS_PIO3)
115 writel(readl(&at91_port->abcdsr1) | mask,
116 &at91_port->abcdsr1);
117 writel(readl(&at91_port->abcdsr2) & ~mask,
118 &at91_port->abcdsr2);
119#else
120 writel(mask, &at91_port->bsr);
121#endif
122 writel(mask, &at91_port->pdr);
123 }
124
125 return 0;
126}
127
128#if defined(CPU_HAS_PIO3)
129/*
130 * mux the pin to the "C" internal peripheral role.
131 */
132int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
133{
134 struct at91_port *at91_port = at91_pio_get_port(port);
135 u32 mask;
136
137 if (at91_port && (pin < 32)) {
138 mask = 1 << pin;
139 writel(mask, &at91_port->idr);
140 at91_set_pio_pullup(port, pin, use_pullup);
141 writel(readl(&at91_port->abcdsr1) & ~mask,
142 &at91_port->abcdsr1);
143 writel(readl(&at91_port->abcdsr2) | mask,
144 &at91_port->abcdsr2);
145 writel(mask, &at91_port->pdr);
146 }
147
148 return 0;
149}
150
151/*
152 * mux the pin to the "D" internal peripheral role.
153 */
154int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
155{
156 struct at91_port *at91_port = at91_pio_get_port(port);
157 u32 mask;
158
159 if (at91_port && (pin < 32)) {
160 mask = 1 << pin;
161 writel(mask, &at91_port->idr);
162 at91_set_pio_pullup(port, pin, use_pullup);
163 writel(readl(&at91_port->abcdsr1) | mask,
164 &at91_port->abcdsr1);
165 writel(readl(&at91_port->abcdsr2) | mask,
166 &at91_port->abcdsr2);
167 writel(mask, &at91_port->pdr);
168 }
169
170 return 0;
171}
172#endif
173
174/*
175 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
176 * configure it for an input.
177 */
178int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
179{
180 struct at91_port *at91_port = at91_pio_get_port(port);
181 u32 mask;
182
183 if (at91_port && (pin < 32)) {
184 mask = 1 << pin;
185 writel(mask, &at91_port->idr);
186 at91_set_pio_pullup(port, pin, use_pullup);
187 writel(mask, &at91_port->odr);
188 writel(mask, &at91_port->per);
189 }
190
191 return 0;
192}
193
194/*
195 * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
196 * and configure it for an output.
197 */
198int at91_set_pio_output(unsigned port, u32 pin, int value)
199{
200 struct at91_port *at91_port = at91_pio_get_port(port);
201 u32 mask;
202
203 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
204 mask = 1 << pin;
205 writel(mask, &at91_port->idr);
206 writel(mask, &at91_port->pudr);
207 if (value)
208 writel(mask, &at91_port->sodr);
209 else
210 writel(mask, &at91_port->codr);
211 writel(mask, &at91_port->oer);
212 writel(mask, &at91_port->per);
213 }
214
215 return 0;
216}
217
218/*
219 * enable/disable the glitch filter. mostly used with IRQ handling.
220 */
221int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
222{
223 struct at91_port *at91_port = at91_pio_get_port(port);
224 u32 mask;
225
226 if (at91_port && (pin < 32)) {
227 mask = 1 << pin;
228 if (is_on) {
229#if defined(CPU_HAS_PIO3)
230 writel(mask, &at91_port->ifscdr);
231#endif
232 writel(mask, &at91_port->ifer);
233 } else {
234 writel(mask, &at91_port->ifdr);
235 }
236 }
237
238 return 0;
239}
240
241#if defined(CPU_HAS_PIO3)
242/*
243 * enable/disable the debounce filter.
244 */
245int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
246{
247 struct at91_port *at91_port = at91_pio_get_port(port);
248 u32 mask;
249
250 if (at91_port && (pin < 32)) {
251 mask = 1 << pin;
252 if (is_on) {
253 writel(mask, &at91_port->ifscer);
254 writel(div & PIO_SCDR_DIV, &at91_port->scdr);
255 writel(mask, &at91_port->ifer);
256 } else {
257 writel(mask, &at91_port->ifdr);
258 }
259 }
260
261 return 0;
262}
263
264/*
265 * enable/disable the pull-down.
266 * If pull-up already enabled while calling the function, we disable it.
267 */
268int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
269{
270 struct at91_port *at91_port = at91_pio_get_port(port);
271 u32 mask;
272
273 if (at91_port && (pin < 32)) {
274 mask = 1 << pin;
275 writel(mask, &at91_port->pudr);
276 if (is_on)
277 writel(mask, &at91_port->ppder);
278 else
279 writel(mask, &at91_port->ppddr);
280 }
281
282 return 0;
283}
284
285/*
286 * disable Schmitt trigger
287 */
288int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
289{
290 struct at91_port *at91_port = at91_pio_get_port(port);
291 u32 mask;
292
293 if (at91_port && (pin < 32)) {
294 mask = 1 << pin;
295 writel(readl(&at91_port->schmitt) | mask,
296 &at91_port->schmitt);
297 }
298
299 return 0;
300}
301#endif
302
303/*
304 * enable/disable the multi-driver. This is only valid for output and
305 * allows the output pin to run as an open collector output.
306 */
307int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
308{
309 struct at91_port *at91_port = at91_pio_get_port(port);
310 u32 mask;
311
312 if (at91_port && (pin < 32)) {
313 mask = 1 << pin;
314 if (is_on)
315 writel(mask, &at91_port->mder);
316 else
317 writel(mask, &at91_port->mddr);
318 }
319
320 return 0;
321}
322
323/*
324 * assuming the pin is muxed as a gpio output, set its value.
325 */
326int at91_set_pio_value(unsigned port, unsigned pin, int value)
327{
328 struct at91_port *at91_port = at91_pio_get_port(port);
329 u32 mask;
330
331 if (at91_port && (pin < 32)) {
332 mask = 1 << pin;
333 if (value)
334 writel(mask, &at91_port->sodr);
335 else
336 writel(mask, &at91_port->codr);
337 }
338
339 return 0;
340}
341
342/*
343 * read the pin's value (works even if it's not muxed as a gpio).
344 */
345int at91_get_pio_value(unsigned port, unsigned pin)
346{
347 struct at91_port *at91_port = at91_pio_get_port(port);
348 u32 pdsr = 0, mask;
349
350 if (at91_port && (pin < 32)) {
351 mask = 1 << pin;
352 pdsr = readl(&at91_port->pdsr) & mask;
353 }
354
355 return pdsr != 0;
356}
357
358/* Common GPIO API */
359
360int gpio_request(unsigned gpio, const char *label)
361{
362 return 0;
363}
364
365int gpio_free(unsigned gpio)
366{
367 return 0;
368}
369
370int gpio_direction_input(unsigned gpio)
371{
372 at91_set_pio_input(at91_gpio_to_port(gpio),
373 at91_gpio_to_pin(gpio), 0);
374 return 0;
375}
376
377int gpio_direction_output(unsigned gpio, int value)
378{
379 at91_set_pio_output(at91_gpio_to_port(gpio),
380 at91_gpio_to_pin(gpio), value);
381 return 0;
382}
383
384int gpio_get_value(unsigned gpio)
385{
386 return at91_get_pio_value(at91_gpio_to_port(gpio),
387 at91_gpio_to_pin(gpio));
388}
389
390int gpio_set_value(unsigned gpio, int value)
391{
392 at91_set_pio_value(at91_gpio_to_port(gpio),
393 at91_gpio_to_pin(gpio), value);
394
395 return 0;
396}