xref: /rk3399_rockchip-uboot/drivers/gpio/at91_gpio.c (revision 4bc9b7a56036f7ecf402842e5c381c0ed3bdca4c)
1ea8fbba7SJens Scharsig /*
2ea8fbba7SJens Scharsig  * Memory Setup stuff - taken from blob memsetup.S
3ea8fbba7SJens Scharsig  *
4ea8fbba7SJens Scharsig  * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de)
5ea8fbba7SJens Scharsig  *
6ea8fbba7SJens Scharsig  *  Copyright (C) 2005 HP Labs
7ea8fbba7SJens Scharsig  *
81a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
9ea8fbba7SJens Scharsig  */
10ea8fbba7SJens Scharsig 
11ea8fbba7SJens Scharsig #include <config.h>
12ea8fbba7SJens Scharsig #include <common.h>
1386592f60SReinhard Meyer #include <asm/io.h>
14ea8fbba7SJens Scharsig #include <asm/sizes.h>
15ea8fbba7SJens Scharsig #include <asm/arch/hardware.h>
16ea8fbba7SJens Scharsig #include <asm/arch/at91_pio.h>
17ea8fbba7SJens Scharsig 
18*4bc9b7a5SBo Shen static struct at91_port *at91_pio_get_port(unsigned port)
19*4bc9b7a5SBo Shen {
20*4bc9b7a5SBo Shen 	switch (port) {
21*4bc9b7a5SBo Shen 	case AT91_PIO_PORTA:
22*4bc9b7a5SBo Shen 		return (struct at91_port *)ATMEL_BASE_PIOA;
23*4bc9b7a5SBo Shen 	case AT91_PIO_PORTB:
24*4bc9b7a5SBo Shen 		return (struct at91_port *)ATMEL_BASE_PIOB;
25*4bc9b7a5SBo Shen 	case AT91_PIO_PORTC:
26*4bc9b7a5SBo Shen 		return (struct at91_port *)ATMEL_BASE_PIOC;
27*4bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 3)
28*4bc9b7a5SBo Shen 	case AT91_PIO_PORTD:
29*4bc9b7a5SBo Shen 		return (struct at91_port *)ATMEL_BASE_PIOD;
30*4bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 4)
31*4bc9b7a5SBo Shen 	case AT91_PIO_PORTE:
32*4bc9b7a5SBo Shen 		return (struct at91_port *)ATMEL_BASE_PIOE;
33*4bc9b7a5SBo Shen #endif
34*4bc9b7a5SBo Shen #endif
35*4bc9b7a5SBo Shen 	default:
36*4bc9b7a5SBo Shen 		return NULL;
37*4bc9b7a5SBo Shen 	}
38*4bc9b7a5SBo Shen }
39*4bc9b7a5SBo Shen 
40ea8fbba7SJens Scharsig int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
41ea8fbba7SJens Scharsig {
42*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
43ea8fbba7SJens Scharsig 	u32 mask;
44ea8fbba7SJens Scharsig 
45*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
46ea8fbba7SJens Scharsig 		mask = 1 << pin;
47ea8fbba7SJens Scharsig 		if (use_pullup)
48*4bc9b7a5SBo Shen 			writel(1 << pin, &at91_port->puer);
49ea8fbba7SJens Scharsig 		else
50*4bc9b7a5SBo Shen 			writel(1 << pin, &at91_port->pudr);
51*4bc9b7a5SBo Shen 		writel(mask, &at91_port->per);
52ea8fbba7SJens Scharsig 	}
53*4bc9b7a5SBo Shen 
54ea8fbba7SJens Scharsig 	return 0;
55ea8fbba7SJens Scharsig }
56ea8fbba7SJens Scharsig 
57ea8fbba7SJens Scharsig /*
58ea8fbba7SJens Scharsig  * mux the pin to the "GPIO" peripheral role.
59ea8fbba7SJens Scharsig  */
60ea8fbba7SJens Scharsig int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
61ea8fbba7SJens Scharsig {
62*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
63ea8fbba7SJens Scharsig 	u32 mask;
64ea8fbba7SJens Scharsig 
65*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
66ea8fbba7SJens Scharsig 		mask = 1 << pin;
67*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
68ea8fbba7SJens Scharsig 		at91_set_pio_pullup(port, pin, use_pullup);
69*4bc9b7a5SBo Shen 		writel(mask, &at91_port->per);
70ea8fbba7SJens Scharsig 	}
71*4bc9b7a5SBo Shen 
72ea8fbba7SJens Scharsig 	return 0;
73ea8fbba7SJens Scharsig }
74ea8fbba7SJens Scharsig 
75ea8fbba7SJens Scharsig /*
76ea8fbba7SJens Scharsig  * mux the pin to the "A" internal peripheral role.
77ea8fbba7SJens Scharsig  */
78ea8fbba7SJens Scharsig int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
79ea8fbba7SJens Scharsig {
80*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
81ea8fbba7SJens Scharsig 	u32 mask;
82ea8fbba7SJens Scharsig 
83*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
84ea8fbba7SJens Scharsig 		mask = 1 << pin;
85*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
86ea8fbba7SJens Scharsig 		at91_set_pio_pullup(port, pin, use_pullup);
872b3b1c66SBo Shen #if defined(CPU_HAS_PIO3)
88*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr1) & ~mask,
89*4bc9b7a5SBo Shen 		       &at91_port->abcdsr1);
90*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr2) & ~mask,
91*4bc9b7a5SBo Shen 		       &at91_port->abcdsr2);
922b3b1c66SBo Shen #else
93*4bc9b7a5SBo Shen 		writel(mask, &at91_port->asr);
942b3b1c66SBo Shen #endif
95*4bc9b7a5SBo Shen 		writel(mask, &at91_port->pdr);
96ea8fbba7SJens Scharsig 	}
97*4bc9b7a5SBo Shen 
98ea8fbba7SJens Scharsig 	return 0;
99ea8fbba7SJens Scharsig }
100ea8fbba7SJens Scharsig 
101ea8fbba7SJens Scharsig /*
102ea8fbba7SJens Scharsig  * mux the pin to the "B" internal peripheral role.
103ea8fbba7SJens Scharsig  */
104ea8fbba7SJens Scharsig int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
105ea8fbba7SJens Scharsig {
106*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
107ea8fbba7SJens Scharsig 	u32 mask;
108ea8fbba7SJens Scharsig 
109*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
110ea8fbba7SJens Scharsig 		mask = 1 << pin;
111*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
112ea8fbba7SJens Scharsig 		at91_set_pio_pullup(port, pin, use_pullup);
1132b3b1c66SBo Shen #if defined(CPU_HAS_PIO3)
114*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr1) | mask,
115*4bc9b7a5SBo Shen 		       &at91_port->abcdsr1);
116*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr2) & ~mask,
117*4bc9b7a5SBo Shen 		       &at91_port->abcdsr2);
1182b3b1c66SBo Shen #else
119*4bc9b7a5SBo Shen 		writel(mask, &at91_port->bsr);
1202b3b1c66SBo Shen #endif
121*4bc9b7a5SBo Shen 		writel(mask, &at91_port->pdr);
122ea8fbba7SJens Scharsig 	}
123*4bc9b7a5SBo Shen 
124ea8fbba7SJens Scharsig 	return 0;
125ea8fbba7SJens Scharsig }
126ea8fbba7SJens Scharsig 
1272b3b1c66SBo Shen #if defined(CPU_HAS_PIO3)
1282b3b1c66SBo Shen /*
1292b3b1c66SBo Shen  * mux the pin to the "C" internal peripheral role.
1302b3b1c66SBo Shen  */
1312b3b1c66SBo Shen int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
1322b3b1c66SBo Shen {
133*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
1342b3b1c66SBo Shen 	u32 mask;
1352b3b1c66SBo Shen 
136*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
1372b3b1c66SBo Shen 		mask = 1 << pin;
138*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
1392b3b1c66SBo Shen 		at91_set_pio_pullup(port, pin, use_pullup);
140*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr1) & ~mask,
141*4bc9b7a5SBo Shen 		       &at91_port->abcdsr1);
142*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr2) | mask,
143*4bc9b7a5SBo Shen 		       &at91_port->abcdsr2);
144*4bc9b7a5SBo Shen 		writel(mask, &at91_port->pdr);
1452b3b1c66SBo Shen 	}
146*4bc9b7a5SBo Shen 
1472b3b1c66SBo Shen 	return 0;
1482b3b1c66SBo Shen }
1492b3b1c66SBo Shen 
1502b3b1c66SBo Shen /*
1512b3b1c66SBo Shen  * mux the pin to the "D" internal peripheral role.
1522b3b1c66SBo Shen  */
1532b3b1c66SBo Shen int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
1542b3b1c66SBo Shen {
155*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
1562b3b1c66SBo Shen 	u32 mask;
1572b3b1c66SBo Shen 
158*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
1592b3b1c66SBo Shen 		mask = 1 << pin;
160*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
1612b3b1c66SBo Shen 		at91_set_pio_pullup(port, pin, use_pullup);
162*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr1) | mask,
163*4bc9b7a5SBo Shen 		       &at91_port->abcdsr1);
164*4bc9b7a5SBo Shen 		writel(readl(&at91_port->abcdsr2) | mask,
165*4bc9b7a5SBo Shen 		       &at91_port->abcdsr2);
166*4bc9b7a5SBo Shen 		writel(mask, &at91_port->pdr);
1672b3b1c66SBo Shen 	}
168*4bc9b7a5SBo Shen 
1692b3b1c66SBo Shen 	return 0;
1702b3b1c66SBo Shen }
1712b3b1c66SBo Shen #endif
1722b3b1c66SBo Shen 
173ea8fbba7SJens Scharsig /*
174ea8fbba7SJens Scharsig  * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
175ea8fbba7SJens Scharsig  * configure it for an input.
176ea8fbba7SJens Scharsig  */
177ea8fbba7SJens Scharsig int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
178ea8fbba7SJens Scharsig {
179*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
180ea8fbba7SJens Scharsig 	u32 mask;
181ea8fbba7SJens Scharsig 
182*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
183ea8fbba7SJens Scharsig 		mask = 1 << pin;
184*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
185ea8fbba7SJens Scharsig 		at91_set_pio_pullup(port, pin, use_pullup);
186*4bc9b7a5SBo Shen 		writel(mask, &at91_port->odr);
187*4bc9b7a5SBo Shen 		writel(mask, &at91_port->per);
188ea8fbba7SJens Scharsig 	}
189*4bc9b7a5SBo Shen 
190ea8fbba7SJens Scharsig 	return 0;
191ea8fbba7SJens Scharsig }
192ea8fbba7SJens Scharsig 
193ea8fbba7SJens Scharsig /*
194ea8fbba7SJens Scharsig  * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
195ea8fbba7SJens Scharsig  * and configure it for an output.
196ea8fbba7SJens Scharsig  */
197ea8fbba7SJens Scharsig int at91_set_pio_output(unsigned port, u32 pin, int value)
198ea8fbba7SJens Scharsig {
199*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
200ea8fbba7SJens Scharsig 	u32 mask;
201ea8fbba7SJens Scharsig 
202372f2783SReinhard Meyer 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
203ea8fbba7SJens Scharsig 		mask = 1 << pin;
204*4bc9b7a5SBo Shen 		writel(mask, &at91_port->idr);
205*4bc9b7a5SBo Shen 		writel(mask, &at91_port->pudr);
206ea8fbba7SJens Scharsig 		if (value)
207*4bc9b7a5SBo Shen 			writel(mask, &at91_port->sodr);
208ea8fbba7SJens Scharsig 		else
209*4bc9b7a5SBo Shen 			writel(mask, &at91_port->codr);
210*4bc9b7a5SBo Shen 		writel(mask, &at91_port->oer);
211*4bc9b7a5SBo Shen 		writel(mask, &at91_port->per);
212ea8fbba7SJens Scharsig 	}
213*4bc9b7a5SBo Shen 
214ea8fbba7SJens Scharsig 	return 0;
215ea8fbba7SJens Scharsig }
216ea8fbba7SJens Scharsig 
217ea8fbba7SJens Scharsig /*
218ea8fbba7SJens Scharsig  * enable/disable the glitch filter. mostly used with IRQ handling.
219ea8fbba7SJens Scharsig  */
220ea8fbba7SJens Scharsig int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
221ea8fbba7SJens Scharsig {
222*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
223ea8fbba7SJens Scharsig 	u32 mask;
224ea8fbba7SJens Scharsig 
225*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
226ea8fbba7SJens Scharsig 		mask = 1 << pin;
2272b3b1c66SBo Shen 		if (is_on) {
2282b3b1c66SBo Shen #if defined(CPU_HAS_PIO3)
229*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ifscdr);
2302b3b1c66SBo Shen #endif
231*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ifer);
2322b3b1c66SBo Shen 		} else {
233*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ifdr);
234ea8fbba7SJens Scharsig 		}
2352b3b1c66SBo Shen 	}
236*4bc9b7a5SBo Shen 
237ea8fbba7SJens Scharsig 	return 0;
238ea8fbba7SJens Scharsig }
239ea8fbba7SJens Scharsig 
2402b3b1c66SBo Shen #if defined(CPU_HAS_PIO3)
2412b3b1c66SBo Shen /*
2422b3b1c66SBo Shen  * enable/disable the debounce filter.
2432b3b1c66SBo Shen  */
2442b3b1c66SBo Shen int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
2452b3b1c66SBo Shen {
246*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
2472b3b1c66SBo Shen 	u32 mask;
2482b3b1c66SBo Shen 
249*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
2502b3b1c66SBo Shen 		mask = 1 << pin;
2512b3b1c66SBo Shen 		if (is_on) {
252*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ifscer);
253*4bc9b7a5SBo Shen 			writel(div & PIO_SCDR_DIV, &at91_port->scdr);
254*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ifer);
2552b3b1c66SBo Shen 		} else {
256*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ifdr);
2572b3b1c66SBo Shen 		}
2582b3b1c66SBo Shen 	}
259*4bc9b7a5SBo Shen 
2602b3b1c66SBo Shen 	return 0;
2612b3b1c66SBo Shen }
2622b3b1c66SBo Shen 
2632b3b1c66SBo Shen /*
2642b3b1c66SBo Shen  * enable/disable the pull-down.
2652b3b1c66SBo Shen  * If pull-up already enabled while calling the function, we disable it.
2662b3b1c66SBo Shen  */
2672b3b1c66SBo Shen int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
2682b3b1c66SBo Shen {
269*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
2702b3b1c66SBo Shen 	u32 mask;
2712b3b1c66SBo Shen 
272*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
2732b3b1c66SBo Shen 		mask = 1 << pin;
274*4bc9b7a5SBo Shen 		writel(mask, &at91_port->pudr);
2752b3b1c66SBo Shen 		if (is_on)
276*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ppder);
2772b3b1c66SBo Shen 		else
278*4bc9b7a5SBo Shen 			writel(mask, &at91_port->ppddr);
2792b3b1c66SBo Shen 	}
280*4bc9b7a5SBo Shen 
2812b3b1c66SBo Shen 	return 0;
2822b3b1c66SBo Shen }
2832b3b1c66SBo Shen 
2842b3b1c66SBo Shen /*
2852b3b1c66SBo Shen  * disable Schmitt trigger
2862b3b1c66SBo Shen  */
2872b3b1c66SBo Shen int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
2882b3b1c66SBo Shen {
289*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
2902b3b1c66SBo Shen 	u32 mask;
2912b3b1c66SBo Shen 
292*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
2932b3b1c66SBo Shen 		mask = 1 << pin;
294*4bc9b7a5SBo Shen 		writel(readl(&at91_port->schmitt) | mask,
295*4bc9b7a5SBo Shen 		       &at91_port->schmitt);
2962b3b1c66SBo Shen 	}
297*4bc9b7a5SBo Shen 
2982b3b1c66SBo Shen 	return 0;
2992b3b1c66SBo Shen }
3002b3b1c66SBo Shen #endif
3012b3b1c66SBo Shen 
302ea8fbba7SJens Scharsig /*
303ea8fbba7SJens Scharsig  * enable/disable the multi-driver. This is only valid for output and
304ea8fbba7SJens Scharsig  * allows the output pin to run as an open collector output.
305ea8fbba7SJens Scharsig  */
306ea8fbba7SJens Scharsig int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
307ea8fbba7SJens Scharsig {
308*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
309ea8fbba7SJens Scharsig 	u32 mask;
310ea8fbba7SJens Scharsig 
311*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
312ea8fbba7SJens Scharsig 		mask = 1 << pin;
313ea8fbba7SJens Scharsig 		if (is_on)
314*4bc9b7a5SBo Shen 			writel(mask, &at91_port->mder);
315ea8fbba7SJens Scharsig 		else
316*4bc9b7a5SBo Shen 			writel(mask, &at91_port->mddr);
317ea8fbba7SJens Scharsig 	}
318*4bc9b7a5SBo Shen 
319ea8fbba7SJens Scharsig 	return 0;
320ea8fbba7SJens Scharsig }
321ea8fbba7SJens Scharsig 
322ea8fbba7SJens Scharsig /*
323ea8fbba7SJens Scharsig  * assuming the pin is muxed as a gpio output, set its value.
324ea8fbba7SJens Scharsig  */
325ea8fbba7SJens Scharsig int at91_set_pio_value(unsigned port, unsigned pin, int value)
326ea8fbba7SJens Scharsig {
327*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
328ea8fbba7SJens Scharsig 	u32 mask;
329ea8fbba7SJens Scharsig 
330*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
331ea8fbba7SJens Scharsig 		mask = 1 << pin;
332ea8fbba7SJens Scharsig 		if (value)
333*4bc9b7a5SBo Shen 			writel(mask, &at91_port->sodr);
334ea8fbba7SJens Scharsig 		else
335*4bc9b7a5SBo Shen 			writel(mask, &at91_port->codr);
336ea8fbba7SJens Scharsig 	}
337*4bc9b7a5SBo Shen 
338ea8fbba7SJens Scharsig 	return 0;
339ea8fbba7SJens Scharsig }
340ea8fbba7SJens Scharsig 
341ea8fbba7SJens Scharsig /*
342ea8fbba7SJens Scharsig  * read the pin's value (works even if it's not muxed as a gpio).
343ea8fbba7SJens Scharsig  */
344ea8fbba7SJens Scharsig int at91_get_pio_value(unsigned port, unsigned pin)
345ea8fbba7SJens Scharsig {
346*4bc9b7a5SBo Shen 	struct at91_port *at91_port = at91_pio_get_port(port);
347*4bc9b7a5SBo Shen 	u32 pdsr = 0, mask;
348ea8fbba7SJens Scharsig 
349*4bc9b7a5SBo Shen 	if (at91_port && (pin < 32)) {
350ea8fbba7SJens Scharsig 		mask = 1 << pin;
351*4bc9b7a5SBo Shen 		pdsr = readl(&at91_port->pdsr) & mask;
352ea8fbba7SJens Scharsig 	}
353*4bc9b7a5SBo Shen 
354ea8fbba7SJens Scharsig 	return pdsr != 0;
355ea8fbba7SJens Scharsig }
356