1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2ea8fbba7SJens Scharsig /*
339b787ecSBo Shen * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
4ea8fbba7SJens Scharsig *
5ea8fbba7SJens Scharsig * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de)
6ea8fbba7SJens Scharsig *
7ea8fbba7SJens Scharsig * Copyright (C) 2005 HP Labs
8ea8fbba7SJens Scharsig */
9ea8fbba7SJens Scharsig
10ea8fbba7SJens Scharsig #include <config.h>
11ea8fbba7SJens Scharsig #include <common.h>
12f2f3c157SWenyou Yang #include <clk.h>
13918354b1SSimon Glass #include <dm.h>
1486592f60SReinhard Meyer #include <asm/io.h>
151ace4022SAlexey Brodkin #include <linux/sizes.h>
16918354b1SSimon Glass #include <asm/gpio.h>
17ea8fbba7SJens Scharsig #include <asm/arch/hardware.h>
18ea8fbba7SJens Scharsig #include <asm/arch/at91_pio.h>
19918354b1SSimon Glass
20918354b1SSimon Glass #define GPIO_PER_BANK 32
21ea8fbba7SJens Scharsig
at91_pio_get_port(unsigned port)224bc9b7a5SBo Shen static struct at91_port *at91_pio_get_port(unsigned port)
234bc9b7a5SBo Shen {
244bc9b7a5SBo Shen switch (port) {
254bc9b7a5SBo Shen case AT91_PIO_PORTA:
264bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOA;
274bc9b7a5SBo Shen case AT91_PIO_PORTB:
284bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOB;
294bc9b7a5SBo Shen case AT91_PIO_PORTC:
304bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOC;
314bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 3)
324bc9b7a5SBo Shen case AT91_PIO_PORTD:
334bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOD;
344bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 4)
354bc9b7a5SBo Shen case AT91_PIO_PORTE:
364bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOE;
374bc9b7a5SBo Shen #endif
384bc9b7a5SBo Shen #endif
394bc9b7a5SBo Shen default:
407d82d897SWu, Josh printf("Error: at91_gpio: Fail to get PIO base!\n");
414bc9b7a5SBo Shen return NULL;
424bc9b7a5SBo Shen }
434bc9b7a5SBo Shen }
444bc9b7a5SBo Shen
at91_set_port_pullup(struct at91_port * at91_port,unsigned offset,int use_pullup)45918354b1SSimon Glass static void at91_set_port_pullup(struct at91_port *at91_port, unsigned offset,
46918354b1SSimon Glass int use_pullup)
47918354b1SSimon Glass {
48918354b1SSimon Glass u32 mask;
49918354b1SSimon Glass
50918354b1SSimon Glass mask = 1 << offset;
51918354b1SSimon Glass if (use_pullup)
52918354b1SSimon Glass writel(mask, &at91_port->puer);
53918354b1SSimon Glass else
54918354b1SSimon Glass writel(mask, &at91_port->pudr);
55918354b1SSimon Glass writel(mask, &at91_port->per);
56918354b1SSimon Glass }
57918354b1SSimon Glass
at91_set_pio_pullup(unsigned port,unsigned pin,int use_pullup)58ea8fbba7SJens Scharsig int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
59ea8fbba7SJens Scharsig {
604bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
61ea8fbba7SJens Scharsig
62918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
63918354b1SSimon Glass at91_set_port_pullup(at91_port, pin, use_pullup);
644bc9b7a5SBo Shen
65ea8fbba7SJens Scharsig return 0;
66ea8fbba7SJens Scharsig }
67ea8fbba7SJens Scharsig
68ea8fbba7SJens Scharsig /*
69ea8fbba7SJens Scharsig * mux the pin to the "GPIO" peripheral role.
70ea8fbba7SJens Scharsig */
at91_set_pio_periph(unsigned port,unsigned pin,int use_pullup)71ea8fbba7SJens Scharsig int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
72ea8fbba7SJens Scharsig {
734bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
74ea8fbba7SJens Scharsig u32 mask;
75ea8fbba7SJens Scharsig
76918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
77ea8fbba7SJens Scharsig mask = 1 << pin;
784bc9b7a5SBo Shen writel(mask, &at91_port->idr);
79ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup);
804bc9b7a5SBo Shen writel(mask, &at91_port->per);
81ea8fbba7SJens Scharsig }
824bc9b7a5SBo Shen
83ea8fbba7SJens Scharsig return 0;
84ea8fbba7SJens Scharsig }
85ea8fbba7SJens Scharsig
86ea8fbba7SJens Scharsig /*
87ea8fbba7SJens Scharsig * mux the pin to the "A" internal peripheral role.
88ea8fbba7SJens Scharsig */
at91_set_a_periph(unsigned port,unsigned pin,int use_pullup)89ea8fbba7SJens Scharsig int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
90ea8fbba7SJens Scharsig {
914bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
92ea8fbba7SJens Scharsig u32 mask;
93ea8fbba7SJens Scharsig
94918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
95ea8fbba7SJens Scharsig mask = 1 << pin;
964bc9b7a5SBo Shen writel(mask, &at91_port->idr);
97ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup);
982dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio2.asr);
994bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
100ea8fbba7SJens Scharsig }
1014bc9b7a5SBo Shen
102ea8fbba7SJens Scharsig return 0;
103ea8fbba7SJens Scharsig }
104ea8fbba7SJens Scharsig
105ea8fbba7SJens Scharsig /*
106ea8fbba7SJens Scharsig * mux the pin to the "B" internal peripheral role.
107ea8fbba7SJens Scharsig */
at91_set_b_periph(unsigned port,unsigned pin,int use_pullup)108ea8fbba7SJens Scharsig int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
109ea8fbba7SJens Scharsig {
1104bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
111ea8fbba7SJens Scharsig u32 mask;
112ea8fbba7SJens Scharsig
113918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
114ea8fbba7SJens Scharsig mask = 1 << pin;
1154bc9b7a5SBo Shen writel(mask, &at91_port->idr);
116ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup);
1172dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio2.bsr);
1184bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
119ea8fbba7SJens Scharsig }
1204bc9b7a5SBo Shen
121ea8fbba7SJens Scharsig return 0;
122ea8fbba7SJens Scharsig }
123ea8fbba7SJens Scharsig
1242b3b1c66SBo Shen /*
1252dc63f73SWenyou Yang * mux the pin to the "A" internal peripheral role.
1262b3b1c66SBo Shen */
at91_pio3_set_a_periph(unsigned port,unsigned pin,int use_pullup)1272dc63f73SWenyou Yang int at91_pio3_set_a_periph(unsigned port, unsigned pin, int use_pullup)
1282b3b1c66SBo Shen {
1294bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
1302b3b1c66SBo Shen u32 mask;
1312b3b1c66SBo Shen
132918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
1332b3b1c66SBo Shen mask = 1 << pin;
1344bc9b7a5SBo Shen writel(mask, &at91_port->idr);
1352b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup);
1362dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask,
1372dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
1382dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask,
1392dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
1402dc63f73SWenyou Yang
1412dc63f73SWenyou Yang writel(mask, &at91_port->pdr);
1422dc63f73SWenyou Yang }
1432dc63f73SWenyou Yang
1442dc63f73SWenyou Yang return 0;
1452dc63f73SWenyou Yang }
1462dc63f73SWenyou Yang
1472dc63f73SWenyou Yang /*
1482dc63f73SWenyou Yang * mux the pin to the "B" internal peripheral role.
1492dc63f73SWenyou Yang */
at91_pio3_set_b_periph(unsigned port,unsigned pin,int use_pullup)1502dc63f73SWenyou Yang int at91_pio3_set_b_periph(unsigned port, unsigned pin, int use_pullup)
1512dc63f73SWenyou Yang {
1522dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
1532dc63f73SWenyou Yang u32 mask;
1542dc63f73SWenyou Yang
1552dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK)) {
1562dc63f73SWenyou Yang mask = 1 << pin;
1572dc63f73SWenyou Yang writel(mask, &at91_port->idr);
1582dc63f73SWenyou Yang at91_set_pio_pullup(port, pin, use_pullup);
1592dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) | mask,
1602dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
1612dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask,
1622dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
1632dc63f73SWenyou Yang
1642dc63f73SWenyou Yang writel(mask, &at91_port->pdr);
1652dc63f73SWenyou Yang }
1662dc63f73SWenyou Yang
1672dc63f73SWenyou Yang return 0;
1682dc63f73SWenyou Yang }
1692dc63f73SWenyou Yang /*
1702dc63f73SWenyou Yang * mux the pin to the "C" internal peripheral role.
1712dc63f73SWenyou Yang */
at91_pio3_set_c_periph(unsigned port,unsigned pin,int use_pullup)1722dc63f73SWenyou Yang int at91_pio3_set_c_periph(unsigned port, unsigned pin, int use_pullup)
1732dc63f73SWenyou Yang {
1742dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
1752dc63f73SWenyou Yang u32 mask;
1762dc63f73SWenyou Yang
1772dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK)) {
1782dc63f73SWenyou Yang mask = 1 << pin;
1792dc63f73SWenyou Yang writel(mask, &at91_port->idr);
1802dc63f73SWenyou Yang at91_set_pio_pullup(port, pin, use_pullup);
1812dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask,
1822dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
1832dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) | mask,
1842dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
1854bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
1862b3b1c66SBo Shen }
1874bc9b7a5SBo Shen
1882b3b1c66SBo Shen return 0;
1892b3b1c66SBo Shen }
1902b3b1c66SBo Shen
1912b3b1c66SBo Shen /*
1922b3b1c66SBo Shen * mux the pin to the "D" internal peripheral role.
1932b3b1c66SBo Shen */
at91_pio3_set_d_periph(unsigned port,unsigned pin,int use_pullup)1942dc63f73SWenyou Yang int at91_pio3_set_d_periph(unsigned port, unsigned pin, int use_pullup)
1952b3b1c66SBo Shen {
1964bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
1972b3b1c66SBo Shen u32 mask;
1982b3b1c66SBo Shen
199918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
2002b3b1c66SBo Shen mask = 1 << pin;
2014bc9b7a5SBo Shen writel(mask, &at91_port->idr);
2022b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup);
2032dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) | mask,
2042dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
2052dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) | mask,
2062dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
2074bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
2082b3b1c66SBo Shen }
2094bc9b7a5SBo Shen
2102b3b1c66SBo Shen return 0;
2112b3b1c66SBo Shen }
2122b3b1c66SBo Shen
213918354b1SSimon Glass #ifdef CONFIG_DM_GPIO
at91_get_port_output(struct at91_port * at91_port,int offset)214918354b1SSimon Glass static bool at91_get_port_output(struct at91_port *at91_port, int offset)
215918354b1SSimon Glass {
216918354b1SSimon Glass u32 mask, val;
217918354b1SSimon Glass
218918354b1SSimon Glass mask = 1 << offset;
219918354b1SSimon Glass val = readl(&at91_port->osr);
220918354b1SSimon Glass return val & mask;
221918354b1SSimon Glass }
222918354b1SSimon Glass #endif
223918354b1SSimon Glass
at91_set_port_input(struct at91_port * at91_port,int offset,int use_pullup)224918354b1SSimon Glass static void at91_set_port_input(struct at91_port *at91_port, int offset,
225918354b1SSimon Glass int use_pullup)
226918354b1SSimon Glass {
227918354b1SSimon Glass u32 mask;
228918354b1SSimon Glass
229918354b1SSimon Glass mask = 1 << offset;
230918354b1SSimon Glass writel(mask, &at91_port->idr);
231918354b1SSimon Glass at91_set_port_pullup(at91_port, offset, use_pullup);
232918354b1SSimon Glass writel(mask, &at91_port->odr);
233918354b1SSimon Glass writel(mask, &at91_port->per);
234918354b1SSimon Glass }
235918354b1SSimon Glass
236ea8fbba7SJens Scharsig /*
237ea8fbba7SJens Scharsig * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
238ea8fbba7SJens Scharsig * configure it for an input.
239ea8fbba7SJens Scharsig */
at91_set_pio_input(unsigned port,u32 pin,int use_pullup)240ea8fbba7SJens Scharsig int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
241ea8fbba7SJens Scharsig {
2424bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
243ea8fbba7SJens Scharsig
244918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
245918354b1SSimon Glass at91_set_port_input(at91_port, pin, use_pullup);
2464bc9b7a5SBo Shen
247ea8fbba7SJens Scharsig return 0;
248ea8fbba7SJens Scharsig }
249ea8fbba7SJens Scharsig
at91_set_port_output(struct at91_port * at91_port,int offset,int value)250918354b1SSimon Glass static void at91_set_port_output(struct at91_port *at91_port, int offset,
251918354b1SSimon Glass int value)
252ea8fbba7SJens Scharsig {
253ea8fbba7SJens Scharsig u32 mask;
254ea8fbba7SJens Scharsig
255918354b1SSimon Glass mask = 1 << offset;
2564bc9b7a5SBo Shen writel(mask, &at91_port->idr);
2574bc9b7a5SBo Shen writel(mask, &at91_port->pudr);
258ea8fbba7SJens Scharsig if (value)
2594bc9b7a5SBo Shen writel(mask, &at91_port->sodr);
260ea8fbba7SJens Scharsig else
2614bc9b7a5SBo Shen writel(mask, &at91_port->codr);
2624bc9b7a5SBo Shen writel(mask, &at91_port->oer);
2634bc9b7a5SBo Shen writel(mask, &at91_port->per);
264ea8fbba7SJens Scharsig }
2654bc9b7a5SBo Shen
266918354b1SSimon Glass /*
267918354b1SSimon Glass * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
268918354b1SSimon Glass * and configure it for an output.
269918354b1SSimon Glass */
at91_set_pio_output(unsigned port,u32 pin,int value)270918354b1SSimon Glass int at91_set_pio_output(unsigned port, u32 pin, int value)
271918354b1SSimon Glass {
272918354b1SSimon Glass struct at91_port *at91_port = at91_pio_get_port(port);
273918354b1SSimon Glass
274918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
275918354b1SSimon Glass at91_set_port_output(at91_port, pin, value);
276918354b1SSimon Glass
277ea8fbba7SJens Scharsig return 0;
278ea8fbba7SJens Scharsig }
279ea8fbba7SJens Scharsig
280ea8fbba7SJens Scharsig /*
281ea8fbba7SJens Scharsig * enable/disable the glitch filter. mostly used with IRQ handling.
282ea8fbba7SJens Scharsig */
at91_set_pio_deglitch(unsigned port,unsigned pin,int is_on)283ea8fbba7SJens Scharsig int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
284ea8fbba7SJens Scharsig {
2854bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
286ea8fbba7SJens Scharsig u32 mask;
287ea8fbba7SJens Scharsig
288918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
289ea8fbba7SJens Scharsig mask = 1 << pin;
2902dc63f73SWenyou Yang if (is_on)
2912dc63f73SWenyou Yang writel(mask, &at91_port->ifer);
2922dc63f73SWenyou Yang else
2932dc63f73SWenyou Yang writel(mask, &at91_port->ifdr);
2942dc63f73SWenyou Yang }
2952dc63f73SWenyou Yang
2962dc63f73SWenyou Yang return 0;
2972dc63f73SWenyou Yang }
2982dc63f73SWenyou Yang
2992dc63f73SWenyou Yang /*
3002dc63f73SWenyou Yang * enable/disable the glitch filter. mostly used with IRQ handling.
3012dc63f73SWenyou Yang */
at91_pio3_set_pio_deglitch(unsigned port,unsigned pin,int is_on)3022dc63f73SWenyou Yang int at91_pio3_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
3032dc63f73SWenyou Yang {
3042dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
3052dc63f73SWenyou Yang u32 mask;
3062dc63f73SWenyou Yang
3072dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK)) {
3082dc63f73SWenyou Yang mask = 1 << pin;
3092b3b1c66SBo Shen if (is_on) {
3102dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ifscdr);
3114bc9b7a5SBo Shen writel(mask, &at91_port->ifer);
3122b3b1c66SBo Shen } else {
3134bc9b7a5SBo Shen writel(mask, &at91_port->ifdr);
314ea8fbba7SJens Scharsig }
3152b3b1c66SBo Shen }
3164bc9b7a5SBo Shen
317ea8fbba7SJens Scharsig return 0;
318ea8fbba7SJens Scharsig }
319ea8fbba7SJens Scharsig
3202b3b1c66SBo Shen /*
3212b3b1c66SBo Shen * enable/disable the debounce filter.
3222b3b1c66SBo Shen */
at91_pio3_set_pio_debounce(unsigned port,unsigned pin,int is_on,int div)3232dc63f73SWenyou Yang int at91_pio3_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
3242b3b1c66SBo Shen {
3254bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
3262b3b1c66SBo Shen u32 mask;
3272b3b1c66SBo Shen
328918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
3292b3b1c66SBo Shen mask = 1 << pin;
3302b3b1c66SBo Shen if (is_on) {
3312dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ifscer);
3322dc63f73SWenyou Yang writel(div & PIO_SCDR_DIV, &at91_port->mux.pio3.scdr);
3334bc9b7a5SBo Shen writel(mask, &at91_port->ifer);
3342b3b1c66SBo Shen } else {
3354bc9b7a5SBo Shen writel(mask, &at91_port->ifdr);
3362b3b1c66SBo Shen }
3372b3b1c66SBo Shen }
3384bc9b7a5SBo Shen
3392b3b1c66SBo Shen return 0;
3402b3b1c66SBo Shen }
3412b3b1c66SBo Shen
3422b3b1c66SBo Shen /*
3432b3b1c66SBo Shen * enable/disable the pull-down.
3442b3b1c66SBo Shen * If pull-up already enabled while calling the function, we disable it.
3452b3b1c66SBo Shen */
at91_pio3_set_pio_pulldown(unsigned port,unsigned pin,int is_on)3462dc63f73SWenyou Yang int at91_pio3_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
3472b3b1c66SBo Shen {
3484bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
3492b3b1c66SBo Shen u32 mask;
3502b3b1c66SBo Shen
351918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
3522b3b1c66SBo Shen mask = 1 << pin;
353152ac5faSMarek Vasut if (is_on) {
354152ac5faSMarek Vasut at91_set_pio_pullup(port, pin, 0);
3552dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ppder);
356152ac5faSMarek Vasut } else
3572dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ppddr);
3582b3b1c66SBo Shen }
3594bc9b7a5SBo Shen
3602b3b1c66SBo Shen return 0;
3612b3b1c66SBo Shen }
3622b3b1c66SBo Shen
at91_pio3_set_pio_pullup(unsigned port,unsigned pin,int use_pullup)3632dc63f73SWenyou Yang int at91_pio3_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
3642dc63f73SWenyou Yang {
3652dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
3662dc63f73SWenyou Yang
3672dc63f73SWenyou Yang if (use_pullup)
3682dc63f73SWenyou Yang at91_pio3_set_pio_pulldown(port, pin, 0);
3692dc63f73SWenyou Yang
3702dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK))
3712dc63f73SWenyou Yang at91_set_port_pullup(at91_port, pin, use_pullup);
3722dc63f73SWenyou Yang
3732dc63f73SWenyou Yang return 0;
3742dc63f73SWenyou Yang }
3752dc63f73SWenyou Yang
3762b3b1c66SBo Shen /*
3772b3b1c66SBo Shen * disable Schmitt trigger
3782b3b1c66SBo Shen */
at91_pio3_set_pio_disable_schmitt_trig(unsigned port,unsigned pin)3792dc63f73SWenyou Yang int at91_pio3_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
3802b3b1c66SBo Shen {
3814bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
3822b3b1c66SBo Shen u32 mask;
3832b3b1c66SBo Shen
384918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
3852b3b1c66SBo Shen mask = 1 << pin;
3864bc9b7a5SBo Shen writel(readl(&at91_port->schmitt) | mask,
3874bc9b7a5SBo Shen &at91_port->schmitt);
3882b3b1c66SBo Shen }
3894bc9b7a5SBo Shen
3902b3b1c66SBo Shen return 0;
3912b3b1c66SBo Shen }
3922b3b1c66SBo Shen
393ea8fbba7SJens Scharsig /*
394ea8fbba7SJens Scharsig * enable/disable the multi-driver. This is only valid for output and
395ea8fbba7SJens Scharsig * allows the output pin to run as an open collector output.
396ea8fbba7SJens Scharsig */
at91_set_pio_multi_drive(unsigned port,unsigned pin,int is_on)397ea8fbba7SJens Scharsig int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
398ea8fbba7SJens Scharsig {
3994bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
400ea8fbba7SJens Scharsig u32 mask;
401ea8fbba7SJens Scharsig
402918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
403ea8fbba7SJens Scharsig mask = 1 << pin;
404ea8fbba7SJens Scharsig if (is_on)
4054bc9b7a5SBo Shen writel(mask, &at91_port->mder);
406ea8fbba7SJens Scharsig else
4074bc9b7a5SBo Shen writel(mask, &at91_port->mddr);
408ea8fbba7SJens Scharsig }
4094bc9b7a5SBo Shen
410ea8fbba7SJens Scharsig return 0;
411ea8fbba7SJens Scharsig }
412ea8fbba7SJens Scharsig
at91_set_port_value(struct at91_port * at91_port,int offset,int value)413918354b1SSimon Glass static void at91_set_port_value(struct at91_port *at91_port, int offset,
414918354b1SSimon Glass int value)
415ea8fbba7SJens Scharsig {
416ea8fbba7SJens Scharsig u32 mask;
417ea8fbba7SJens Scharsig
418918354b1SSimon Glass mask = 1 << offset;
419ea8fbba7SJens Scharsig if (value)
4204bc9b7a5SBo Shen writel(mask, &at91_port->sodr);
421ea8fbba7SJens Scharsig else
4224bc9b7a5SBo Shen writel(mask, &at91_port->codr);
423ea8fbba7SJens Scharsig }
4244bc9b7a5SBo Shen
425918354b1SSimon Glass /*
426918354b1SSimon Glass * assuming the pin is muxed as a gpio output, set its value.
427918354b1SSimon Glass */
at91_set_pio_value(unsigned port,unsigned pin,int value)428918354b1SSimon Glass int at91_set_pio_value(unsigned port, unsigned pin, int value)
429918354b1SSimon Glass {
430918354b1SSimon Glass struct at91_port *at91_port = at91_pio_get_port(port);
431918354b1SSimon Glass
432918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
433918354b1SSimon Glass at91_set_port_value(at91_port, pin, value);
434918354b1SSimon Glass
435ea8fbba7SJens Scharsig return 0;
436ea8fbba7SJens Scharsig }
437ea8fbba7SJens Scharsig
at91_get_port_value(struct at91_port * at91_port,int offset)438918354b1SSimon Glass static int at91_get_port_value(struct at91_port *at91_port, int offset)
439918354b1SSimon Glass {
440918354b1SSimon Glass u32 pdsr = 0, mask;
441918354b1SSimon Glass
442918354b1SSimon Glass mask = 1 << offset;
443918354b1SSimon Glass pdsr = readl(&at91_port->pdsr) & mask;
444918354b1SSimon Glass
445918354b1SSimon Glass return pdsr != 0;
446918354b1SSimon Glass }
447ea8fbba7SJens Scharsig /*
448ea8fbba7SJens Scharsig * read the pin's value (works even if it's not muxed as a gpio).
449ea8fbba7SJens Scharsig */
at91_get_pio_value(unsigned port,unsigned pin)450ea8fbba7SJens Scharsig int at91_get_pio_value(unsigned port, unsigned pin)
451ea8fbba7SJens Scharsig {
4524bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
453ea8fbba7SJens Scharsig
454918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
455918354b1SSimon Glass return at91_get_port_value(at91_port, pin);
456918354b1SSimon Glass
457918354b1SSimon Glass return 0;
458ea8fbba7SJens Scharsig }
4594bc9b7a5SBo Shen
460918354b1SSimon Glass #ifndef CONFIG_DM_GPIO
4616edaea87SBo Shen /* Common GPIO API */
4626edaea87SBo Shen
gpio_request(unsigned gpio,const char * label)4636edaea87SBo Shen int gpio_request(unsigned gpio, const char *label)
4646edaea87SBo Shen {
4656edaea87SBo Shen return 0;
4666edaea87SBo Shen }
4676edaea87SBo Shen
gpio_free(unsigned gpio)4686edaea87SBo Shen int gpio_free(unsigned gpio)
4696edaea87SBo Shen {
4706edaea87SBo Shen return 0;
4716edaea87SBo Shen }
4726edaea87SBo Shen
gpio_direction_input(unsigned gpio)4736edaea87SBo Shen int gpio_direction_input(unsigned gpio)
4746edaea87SBo Shen {
4756edaea87SBo Shen at91_set_pio_input(at91_gpio_to_port(gpio),
4766edaea87SBo Shen at91_gpio_to_pin(gpio), 0);
4776edaea87SBo Shen return 0;
4786edaea87SBo Shen }
4796edaea87SBo Shen
gpio_direction_output(unsigned gpio,int value)4806edaea87SBo Shen int gpio_direction_output(unsigned gpio, int value)
4816edaea87SBo Shen {
4826edaea87SBo Shen at91_set_pio_output(at91_gpio_to_port(gpio),
4836edaea87SBo Shen at91_gpio_to_pin(gpio), value);
4846edaea87SBo Shen return 0;
4856edaea87SBo Shen }
4866edaea87SBo Shen
gpio_get_value(unsigned gpio)4876edaea87SBo Shen int gpio_get_value(unsigned gpio)
4886edaea87SBo Shen {
4896edaea87SBo Shen return at91_get_pio_value(at91_gpio_to_port(gpio),
4906edaea87SBo Shen at91_gpio_to_pin(gpio));
4916edaea87SBo Shen }
4926edaea87SBo Shen
gpio_set_value(unsigned gpio,int value)4936edaea87SBo Shen int gpio_set_value(unsigned gpio, int value)
4946edaea87SBo Shen {
4956edaea87SBo Shen at91_set_pio_value(at91_gpio_to_port(gpio),
4966edaea87SBo Shen at91_gpio_to_pin(gpio), value);
4976edaea87SBo Shen
4986edaea87SBo Shen return 0;
4996edaea87SBo Shen }
500918354b1SSimon Glass #endif
501918354b1SSimon Glass
502918354b1SSimon Glass #ifdef CONFIG_DM_GPIO
503918354b1SSimon Glass
504918354b1SSimon Glass struct at91_port_priv {
505918354b1SSimon Glass struct at91_port *regs;
506918354b1SSimon Glass };
507918354b1SSimon Glass
508918354b1SSimon Glass /* set GPIO pin 'gpio' as an input */
at91_gpio_direction_input(struct udevice * dev,unsigned offset)509918354b1SSimon Glass static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
510918354b1SSimon Glass {
511d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
512918354b1SSimon Glass
513918354b1SSimon Glass at91_set_port_input(port->regs, offset, 0);
514918354b1SSimon Glass
515918354b1SSimon Glass return 0;
516918354b1SSimon Glass }
517918354b1SSimon Glass
518918354b1SSimon Glass /* set GPIO pin 'gpio' as an output, with polarity 'value' */
at91_gpio_direction_output(struct udevice * dev,unsigned offset,int value)519918354b1SSimon Glass static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
520918354b1SSimon Glass int value)
521918354b1SSimon Glass {
522d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
523918354b1SSimon Glass
524918354b1SSimon Glass at91_set_port_output(port->regs, offset, value);
525918354b1SSimon Glass
526918354b1SSimon Glass return 0;
527918354b1SSimon Glass }
528918354b1SSimon Glass
529918354b1SSimon Glass /* read GPIO IN value of pin 'gpio' */
at91_gpio_get_value(struct udevice * dev,unsigned offset)530918354b1SSimon Glass static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
531918354b1SSimon Glass {
532d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
533918354b1SSimon Glass
534918354b1SSimon Glass return at91_get_port_value(port->regs, offset);
535918354b1SSimon Glass }
536918354b1SSimon Glass
537918354b1SSimon Glass /* write GPIO OUT value to pin 'gpio' */
at91_gpio_set_value(struct udevice * dev,unsigned offset,int value)538918354b1SSimon Glass static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
539918354b1SSimon Glass int value)
540918354b1SSimon Glass {
541d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
542918354b1SSimon Glass
543918354b1SSimon Glass at91_set_port_value(port->regs, offset, value);
544918354b1SSimon Glass
545918354b1SSimon Glass return 0;
546918354b1SSimon Glass }
547918354b1SSimon Glass
at91_gpio_get_function(struct udevice * dev,unsigned offset)548918354b1SSimon Glass static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
549918354b1SSimon Glass {
550d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
551918354b1SSimon Glass
552918354b1SSimon Glass /* GPIOF_FUNC is not implemented yet */
553918354b1SSimon Glass if (at91_get_port_output(port->regs, offset))
554918354b1SSimon Glass return GPIOF_OUTPUT;
555918354b1SSimon Glass else
556918354b1SSimon Glass return GPIOF_INPUT;
557918354b1SSimon Glass }
558918354b1SSimon Glass
559918354b1SSimon Glass static const struct dm_gpio_ops gpio_at91_ops = {
560918354b1SSimon Glass .direction_input = at91_gpio_direction_input,
561918354b1SSimon Glass .direction_output = at91_gpio_direction_output,
562918354b1SSimon Glass .get_value = at91_gpio_get_value,
563918354b1SSimon Glass .set_value = at91_gpio_set_value,
564918354b1SSimon Glass .get_function = at91_gpio_get_function,
565918354b1SSimon Glass };
566918354b1SSimon Glass
at91_gpio_probe(struct udevice * dev)567918354b1SSimon Glass static int at91_gpio_probe(struct udevice *dev)
568918354b1SSimon Glass {
569918354b1SSimon Glass struct at91_port_priv *port = dev_get_priv(dev);
570918354b1SSimon Glass struct at91_port_platdata *plat = dev_get_platdata(dev);
571e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
572f2f3c157SWenyou Yang struct clk clk;
573f2f3c157SWenyou Yang int ret;
574f2f3c157SWenyou Yang
575f2f3c157SWenyou Yang ret = clk_get_by_index(dev, 0, &clk);
576f2f3c157SWenyou Yang if (ret)
577f2f3c157SWenyou Yang return ret;
578f2f3c157SWenyou Yang
579f2f3c157SWenyou Yang ret = clk_enable(&clk);
580f2f3c157SWenyou Yang if (ret)
581f2f3c157SWenyou Yang return ret;
582f2f3c157SWenyou Yang
583f2f3c157SWenyou Yang clk_free(&clk);
584918354b1SSimon Glass
585918354b1SSimon Glass uc_priv->bank_name = plat->bank_name;
586918354b1SSimon Glass uc_priv->gpio_count = GPIO_PER_BANK;
587cf468880SWenyou Yang
588cf468880SWenyou Yang #if CONFIG_IS_ENABLED(OF_CONTROL)
589a821c4afSSimon Glass plat->base_addr = (uint32_t)devfdt_get_addr_ptr(dev);
590cf468880SWenyou Yang #endif
591918354b1SSimon Glass port->regs = (struct at91_port *)plat->base_addr;
592918354b1SSimon Glass
593918354b1SSimon Glass return 0;
594918354b1SSimon Glass }
595918354b1SSimon Glass
596cf468880SWenyou Yang #if CONFIG_IS_ENABLED(OF_CONTROL)
597cf468880SWenyou Yang static const struct udevice_id at91_gpio_ids[] = {
598cf468880SWenyou Yang { .compatible = "atmel,at91rm9200-gpio" },
599cf468880SWenyou Yang { }
600cf468880SWenyou Yang };
601cf468880SWenyou Yang #endif
602cf468880SWenyou Yang
603918354b1SSimon Glass U_BOOT_DRIVER(gpio_at91) = {
604918354b1SSimon Glass .name = "gpio_at91",
605918354b1SSimon Glass .id = UCLASS_GPIO,
606cf468880SWenyou Yang #if CONFIG_IS_ENABLED(OF_CONTROL)
607cf468880SWenyou Yang .of_match = at91_gpio_ids,
608cf468880SWenyou Yang .platdata_auto_alloc_size = sizeof(struct at91_port_platdata),
609cf468880SWenyou Yang #endif
610918354b1SSimon Glass .ops = &gpio_at91_ops,
611918354b1SSimon Glass .probe = at91_gpio_probe,
612918354b1SSimon Glass .priv_auto_alloc_size = sizeof(struct at91_port_priv),
613918354b1SSimon Glass };
614918354b1SSimon Glass #endif
615