1ea8fbba7SJens Scharsig /*
239b787ecSBo Shen * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
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>
13f2f3c157SWenyou Yang #include <clk.h>
14918354b1SSimon Glass #include <dm.h>
1586592f60SReinhard Meyer #include <asm/io.h>
161ace4022SAlexey Brodkin #include <linux/sizes.h>
17918354b1SSimon Glass #include <asm/gpio.h>
18ea8fbba7SJens Scharsig #include <asm/arch/hardware.h>
19ea8fbba7SJens Scharsig #include <asm/arch/at91_pio.h>
20918354b1SSimon Glass
21918354b1SSimon Glass #define GPIO_PER_BANK 32
22ea8fbba7SJens Scharsig
at91_pio_get_port(unsigned port)234bc9b7a5SBo Shen static struct at91_port *at91_pio_get_port(unsigned port)
244bc9b7a5SBo Shen {
254bc9b7a5SBo Shen switch (port) {
264bc9b7a5SBo Shen case AT91_PIO_PORTA:
274bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOA;
284bc9b7a5SBo Shen case AT91_PIO_PORTB:
294bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOB;
304bc9b7a5SBo Shen case AT91_PIO_PORTC:
314bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOC;
324bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 3)
334bc9b7a5SBo Shen case AT91_PIO_PORTD:
344bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOD;
354bc9b7a5SBo Shen #if (ATMEL_PIO_PORTS > 4)
364bc9b7a5SBo Shen case AT91_PIO_PORTE:
374bc9b7a5SBo Shen return (struct at91_port *)ATMEL_BASE_PIOE;
384bc9b7a5SBo Shen #endif
394bc9b7a5SBo Shen #endif
404bc9b7a5SBo Shen default:
417d82d897SWu, Josh printf("Error: at91_gpio: Fail to get PIO base!\n");
424bc9b7a5SBo Shen return NULL;
434bc9b7a5SBo Shen }
444bc9b7a5SBo Shen }
454bc9b7a5SBo Shen
at91_set_port_pullup(struct at91_port * at91_port,unsigned offset,int use_pullup)46918354b1SSimon Glass static void at91_set_port_pullup(struct at91_port *at91_port, unsigned offset,
47918354b1SSimon Glass int use_pullup)
48918354b1SSimon Glass {
49918354b1SSimon Glass u32 mask;
50918354b1SSimon Glass
51918354b1SSimon Glass mask = 1 << offset;
52918354b1SSimon Glass if (use_pullup)
53918354b1SSimon Glass writel(mask, &at91_port->puer);
54918354b1SSimon Glass else
55918354b1SSimon Glass writel(mask, &at91_port->pudr);
56918354b1SSimon Glass writel(mask, &at91_port->per);
57918354b1SSimon Glass }
58918354b1SSimon Glass
at91_set_pio_pullup(unsigned port,unsigned pin,int use_pullup)59ea8fbba7SJens Scharsig int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
60ea8fbba7SJens Scharsig {
614bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
62ea8fbba7SJens Scharsig
63918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
64918354b1SSimon Glass at91_set_port_pullup(at91_port, pin, use_pullup);
654bc9b7a5SBo Shen
66ea8fbba7SJens Scharsig return 0;
67ea8fbba7SJens Scharsig }
68ea8fbba7SJens Scharsig
69ea8fbba7SJens Scharsig /*
70ea8fbba7SJens Scharsig * mux the pin to the "GPIO" peripheral role.
71ea8fbba7SJens Scharsig */
at91_set_pio_periph(unsigned port,unsigned pin,int use_pullup)72ea8fbba7SJens Scharsig int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
73ea8fbba7SJens Scharsig {
744bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
75ea8fbba7SJens Scharsig u32 mask;
76ea8fbba7SJens Scharsig
77918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
78ea8fbba7SJens Scharsig mask = 1 << pin;
794bc9b7a5SBo Shen writel(mask, &at91_port->idr);
80ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup);
814bc9b7a5SBo Shen writel(mask, &at91_port->per);
82ea8fbba7SJens Scharsig }
834bc9b7a5SBo Shen
84ea8fbba7SJens Scharsig return 0;
85ea8fbba7SJens Scharsig }
86ea8fbba7SJens Scharsig
87ea8fbba7SJens Scharsig /*
88ea8fbba7SJens Scharsig * mux the pin to the "A" internal peripheral role.
89ea8fbba7SJens Scharsig */
at91_set_a_periph(unsigned port,unsigned pin,int use_pullup)90ea8fbba7SJens Scharsig int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
91ea8fbba7SJens Scharsig {
924bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
93ea8fbba7SJens Scharsig u32 mask;
94ea8fbba7SJens Scharsig
95918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
96ea8fbba7SJens Scharsig mask = 1 << pin;
974bc9b7a5SBo Shen writel(mask, &at91_port->idr);
98ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup);
992dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio2.asr);
1004bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
101ea8fbba7SJens Scharsig }
1024bc9b7a5SBo Shen
103ea8fbba7SJens Scharsig return 0;
104ea8fbba7SJens Scharsig }
105ea8fbba7SJens Scharsig
106ea8fbba7SJens Scharsig /*
107ea8fbba7SJens Scharsig * mux the pin to the "B" internal peripheral role.
108ea8fbba7SJens Scharsig */
at91_set_b_periph(unsigned port,unsigned pin,int use_pullup)109ea8fbba7SJens Scharsig int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
110ea8fbba7SJens Scharsig {
1114bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
112ea8fbba7SJens Scharsig u32 mask;
113ea8fbba7SJens Scharsig
114918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
115ea8fbba7SJens Scharsig mask = 1 << pin;
1164bc9b7a5SBo Shen writel(mask, &at91_port->idr);
117ea8fbba7SJens Scharsig at91_set_pio_pullup(port, pin, use_pullup);
1182dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio2.bsr);
1194bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
120ea8fbba7SJens Scharsig }
1214bc9b7a5SBo Shen
122ea8fbba7SJens Scharsig return 0;
123ea8fbba7SJens Scharsig }
124ea8fbba7SJens Scharsig
1252b3b1c66SBo Shen /*
1262dc63f73SWenyou Yang * mux the pin to the "A" internal peripheral role.
1272b3b1c66SBo Shen */
at91_pio3_set_a_periph(unsigned port,unsigned pin,int use_pullup)1282dc63f73SWenyou Yang int at91_pio3_set_a_periph(unsigned port, unsigned pin, int use_pullup)
1292b3b1c66SBo Shen {
1304bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
1312b3b1c66SBo Shen u32 mask;
1322b3b1c66SBo Shen
133918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
1342b3b1c66SBo Shen mask = 1 << pin;
1354bc9b7a5SBo Shen writel(mask, &at91_port->idr);
1362b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup);
1372dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask,
1382dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
1392dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask,
1402dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
1412dc63f73SWenyou Yang
1422dc63f73SWenyou Yang writel(mask, &at91_port->pdr);
1432dc63f73SWenyou Yang }
1442dc63f73SWenyou Yang
1452dc63f73SWenyou Yang return 0;
1462dc63f73SWenyou Yang }
1472dc63f73SWenyou Yang
1482dc63f73SWenyou Yang /*
1492dc63f73SWenyou Yang * mux the pin to the "B" internal peripheral role.
1502dc63f73SWenyou Yang */
at91_pio3_set_b_periph(unsigned port,unsigned pin,int use_pullup)1512dc63f73SWenyou Yang int at91_pio3_set_b_periph(unsigned port, unsigned pin, int use_pullup)
1522dc63f73SWenyou Yang {
1532dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
1542dc63f73SWenyou Yang u32 mask;
1552dc63f73SWenyou Yang
1562dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK)) {
1572dc63f73SWenyou Yang mask = 1 << pin;
1582dc63f73SWenyou Yang writel(mask, &at91_port->idr);
1592dc63f73SWenyou Yang at91_set_pio_pullup(port, pin, use_pullup);
1602dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) | mask,
1612dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
1622dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) & ~mask,
1632dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
1642dc63f73SWenyou Yang
1652dc63f73SWenyou Yang writel(mask, &at91_port->pdr);
1662dc63f73SWenyou Yang }
1672dc63f73SWenyou Yang
1682dc63f73SWenyou Yang return 0;
1692dc63f73SWenyou Yang }
1702dc63f73SWenyou Yang /*
1712dc63f73SWenyou Yang * mux the pin to the "C" internal peripheral role.
1722dc63f73SWenyou Yang */
at91_pio3_set_c_periph(unsigned port,unsigned pin,int use_pullup)1732dc63f73SWenyou Yang int at91_pio3_set_c_periph(unsigned port, unsigned pin, int use_pullup)
1742dc63f73SWenyou Yang {
1752dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
1762dc63f73SWenyou Yang u32 mask;
1772dc63f73SWenyou Yang
1782dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK)) {
1792dc63f73SWenyou Yang mask = 1 << pin;
1802dc63f73SWenyou Yang writel(mask, &at91_port->idr);
1812dc63f73SWenyou Yang at91_set_pio_pullup(port, pin, use_pullup);
1822dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) & ~mask,
1832dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
1842dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) | mask,
1852dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
1864bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
1872b3b1c66SBo Shen }
1884bc9b7a5SBo Shen
1892b3b1c66SBo Shen return 0;
1902b3b1c66SBo Shen }
1912b3b1c66SBo Shen
1922b3b1c66SBo Shen /*
1932b3b1c66SBo Shen * mux the pin to the "D" internal peripheral role.
1942b3b1c66SBo Shen */
at91_pio3_set_d_periph(unsigned port,unsigned pin,int use_pullup)1952dc63f73SWenyou Yang int at91_pio3_set_d_periph(unsigned port, unsigned pin, int use_pullup)
1962b3b1c66SBo Shen {
1974bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
1982b3b1c66SBo Shen u32 mask;
1992b3b1c66SBo Shen
200918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
2012b3b1c66SBo Shen mask = 1 << pin;
2024bc9b7a5SBo Shen writel(mask, &at91_port->idr);
2032b3b1c66SBo Shen at91_set_pio_pullup(port, pin, use_pullup);
2042dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr1) | mask,
2052dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr1);
2062dc63f73SWenyou Yang writel(readl(&at91_port->mux.pio3.abcdsr2) | mask,
2072dc63f73SWenyou Yang &at91_port->mux.pio3.abcdsr2);
2084bc9b7a5SBo Shen writel(mask, &at91_port->pdr);
2092b3b1c66SBo Shen }
2104bc9b7a5SBo Shen
2112b3b1c66SBo Shen return 0;
2122b3b1c66SBo Shen }
2132b3b1c66SBo Shen
214918354b1SSimon Glass #ifdef CONFIG_DM_GPIO
at91_get_port_output(struct at91_port * at91_port,int offset)215918354b1SSimon Glass static bool at91_get_port_output(struct at91_port *at91_port, int offset)
216918354b1SSimon Glass {
217918354b1SSimon Glass u32 mask, val;
218918354b1SSimon Glass
219918354b1SSimon Glass mask = 1 << offset;
220918354b1SSimon Glass val = readl(&at91_port->osr);
221918354b1SSimon Glass return val & mask;
222918354b1SSimon Glass }
223918354b1SSimon Glass #endif
224918354b1SSimon Glass
at91_set_port_input(struct at91_port * at91_port,int offset,int use_pullup)225918354b1SSimon Glass static void at91_set_port_input(struct at91_port *at91_port, int offset,
226918354b1SSimon Glass int use_pullup)
227918354b1SSimon Glass {
228918354b1SSimon Glass u32 mask;
229918354b1SSimon Glass
230918354b1SSimon Glass mask = 1 << offset;
231918354b1SSimon Glass writel(mask, &at91_port->idr);
232918354b1SSimon Glass at91_set_port_pullup(at91_port, offset, use_pullup);
233918354b1SSimon Glass writel(mask, &at91_port->odr);
234918354b1SSimon Glass writel(mask, &at91_port->per);
235918354b1SSimon Glass }
236918354b1SSimon Glass
237ea8fbba7SJens Scharsig /*
238ea8fbba7SJens Scharsig * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
239ea8fbba7SJens Scharsig * configure it for an input.
240ea8fbba7SJens Scharsig */
at91_set_pio_input(unsigned port,u32 pin,int use_pullup)241ea8fbba7SJens Scharsig int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
242ea8fbba7SJens Scharsig {
2434bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
244ea8fbba7SJens Scharsig
245918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
246918354b1SSimon Glass at91_set_port_input(at91_port, pin, use_pullup);
2474bc9b7a5SBo Shen
248ea8fbba7SJens Scharsig return 0;
249ea8fbba7SJens Scharsig }
250ea8fbba7SJens Scharsig
at91_set_port_output(struct at91_port * at91_port,int offset,int value)251918354b1SSimon Glass static void at91_set_port_output(struct at91_port *at91_port, int offset,
252918354b1SSimon Glass int value)
253ea8fbba7SJens Scharsig {
254ea8fbba7SJens Scharsig u32 mask;
255ea8fbba7SJens Scharsig
256918354b1SSimon Glass mask = 1 << offset;
2574bc9b7a5SBo Shen writel(mask, &at91_port->idr);
2584bc9b7a5SBo Shen writel(mask, &at91_port->pudr);
259ea8fbba7SJens Scharsig if (value)
2604bc9b7a5SBo Shen writel(mask, &at91_port->sodr);
261ea8fbba7SJens Scharsig else
2624bc9b7a5SBo Shen writel(mask, &at91_port->codr);
2634bc9b7a5SBo Shen writel(mask, &at91_port->oer);
2644bc9b7a5SBo Shen writel(mask, &at91_port->per);
265ea8fbba7SJens Scharsig }
2664bc9b7a5SBo Shen
267918354b1SSimon Glass /*
268918354b1SSimon Glass * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
269918354b1SSimon Glass * and configure it for an output.
270918354b1SSimon Glass */
at91_set_pio_output(unsigned port,u32 pin,int value)271918354b1SSimon Glass int at91_set_pio_output(unsigned port, u32 pin, int value)
272918354b1SSimon Glass {
273918354b1SSimon Glass struct at91_port *at91_port = at91_pio_get_port(port);
274918354b1SSimon Glass
275918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
276918354b1SSimon Glass at91_set_port_output(at91_port, pin, value);
277918354b1SSimon Glass
278ea8fbba7SJens Scharsig return 0;
279ea8fbba7SJens Scharsig }
280ea8fbba7SJens Scharsig
281ea8fbba7SJens Scharsig /*
282ea8fbba7SJens Scharsig * enable/disable the glitch filter. mostly used with IRQ handling.
283ea8fbba7SJens Scharsig */
at91_set_pio_deglitch(unsigned port,unsigned pin,int is_on)284ea8fbba7SJens Scharsig int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
285ea8fbba7SJens Scharsig {
2864bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
287ea8fbba7SJens Scharsig u32 mask;
288ea8fbba7SJens Scharsig
289918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
290ea8fbba7SJens Scharsig mask = 1 << pin;
2912dc63f73SWenyou Yang if (is_on)
2922dc63f73SWenyou Yang writel(mask, &at91_port->ifer);
2932dc63f73SWenyou Yang else
2942dc63f73SWenyou Yang writel(mask, &at91_port->ifdr);
2952dc63f73SWenyou Yang }
2962dc63f73SWenyou Yang
2972dc63f73SWenyou Yang return 0;
2982dc63f73SWenyou Yang }
2992dc63f73SWenyou Yang
3002dc63f73SWenyou Yang /*
3012dc63f73SWenyou Yang * enable/disable the glitch filter. mostly used with IRQ handling.
3022dc63f73SWenyou Yang */
at91_pio3_set_pio_deglitch(unsigned port,unsigned pin,int is_on)3032dc63f73SWenyou Yang int at91_pio3_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
3042dc63f73SWenyou Yang {
3052dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
3062dc63f73SWenyou Yang u32 mask;
3072dc63f73SWenyou Yang
3082dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK)) {
3092dc63f73SWenyou Yang mask = 1 << pin;
3102b3b1c66SBo Shen if (is_on) {
3112dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ifscdr);
3124bc9b7a5SBo Shen writel(mask, &at91_port->ifer);
3132b3b1c66SBo Shen } else {
3144bc9b7a5SBo Shen writel(mask, &at91_port->ifdr);
315ea8fbba7SJens Scharsig }
3162b3b1c66SBo Shen }
3174bc9b7a5SBo Shen
318ea8fbba7SJens Scharsig return 0;
319ea8fbba7SJens Scharsig }
320ea8fbba7SJens Scharsig
3212b3b1c66SBo Shen /*
3222b3b1c66SBo Shen * enable/disable the debounce filter.
3232b3b1c66SBo Shen */
at91_pio3_set_pio_debounce(unsigned port,unsigned pin,int is_on,int div)3242dc63f73SWenyou Yang int at91_pio3_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
3252b3b1c66SBo Shen {
3264bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
3272b3b1c66SBo Shen u32 mask;
3282b3b1c66SBo Shen
329918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
3302b3b1c66SBo Shen mask = 1 << pin;
3312b3b1c66SBo Shen if (is_on) {
3322dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ifscer);
3332dc63f73SWenyou Yang writel(div & PIO_SCDR_DIV, &at91_port->mux.pio3.scdr);
3344bc9b7a5SBo Shen writel(mask, &at91_port->ifer);
3352b3b1c66SBo Shen } else {
3364bc9b7a5SBo Shen writel(mask, &at91_port->ifdr);
3372b3b1c66SBo Shen }
3382b3b1c66SBo Shen }
3394bc9b7a5SBo Shen
3402b3b1c66SBo Shen return 0;
3412b3b1c66SBo Shen }
3422b3b1c66SBo Shen
3432b3b1c66SBo Shen /*
3442b3b1c66SBo Shen * enable/disable the pull-down.
3452b3b1c66SBo Shen * If pull-up already enabled while calling the function, we disable it.
3462b3b1c66SBo Shen */
at91_pio3_set_pio_pulldown(unsigned port,unsigned pin,int is_on)3472dc63f73SWenyou Yang int at91_pio3_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
3482b3b1c66SBo Shen {
3494bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
3502b3b1c66SBo Shen u32 mask;
3512b3b1c66SBo Shen
352918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
3532b3b1c66SBo Shen mask = 1 << pin;
354152ac5faSMarek Vasut if (is_on) {
355152ac5faSMarek Vasut at91_set_pio_pullup(port, pin, 0);
3562dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ppder);
357152ac5faSMarek Vasut } else
3582dc63f73SWenyou Yang writel(mask, &at91_port->mux.pio3.ppddr);
3592b3b1c66SBo Shen }
3604bc9b7a5SBo Shen
3612b3b1c66SBo Shen return 0;
3622b3b1c66SBo Shen }
3632b3b1c66SBo Shen
at91_pio3_set_pio_pullup(unsigned port,unsigned pin,int use_pullup)3642dc63f73SWenyou Yang int at91_pio3_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
3652dc63f73SWenyou Yang {
3662dc63f73SWenyou Yang struct at91_port *at91_port = at91_pio_get_port(port);
3672dc63f73SWenyou Yang
3682dc63f73SWenyou Yang if (use_pullup)
3692dc63f73SWenyou Yang at91_pio3_set_pio_pulldown(port, pin, 0);
3702dc63f73SWenyou Yang
3712dc63f73SWenyou Yang if (at91_port && (pin < GPIO_PER_BANK))
3722dc63f73SWenyou Yang at91_set_port_pullup(at91_port, pin, use_pullup);
3732dc63f73SWenyou Yang
3742dc63f73SWenyou Yang return 0;
3752dc63f73SWenyou Yang }
3762dc63f73SWenyou Yang
3772b3b1c66SBo Shen /*
3782b3b1c66SBo Shen * disable Schmitt trigger
3792b3b1c66SBo Shen */
at91_pio3_set_pio_disable_schmitt_trig(unsigned port,unsigned pin)3802dc63f73SWenyou Yang int at91_pio3_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
3812b3b1c66SBo Shen {
3824bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
3832b3b1c66SBo Shen u32 mask;
3842b3b1c66SBo Shen
385918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
3862b3b1c66SBo Shen mask = 1 << pin;
3874bc9b7a5SBo Shen writel(readl(&at91_port->schmitt) | mask,
3884bc9b7a5SBo Shen &at91_port->schmitt);
3892b3b1c66SBo Shen }
3904bc9b7a5SBo Shen
3912b3b1c66SBo Shen return 0;
3922b3b1c66SBo Shen }
3932b3b1c66SBo Shen
394ea8fbba7SJens Scharsig /*
395ea8fbba7SJens Scharsig * enable/disable the multi-driver. This is only valid for output and
396ea8fbba7SJens Scharsig * allows the output pin to run as an open collector output.
397ea8fbba7SJens Scharsig */
at91_set_pio_multi_drive(unsigned port,unsigned pin,int is_on)398ea8fbba7SJens Scharsig int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
399ea8fbba7SJens Scharsig {
4004bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
401ea8fbba7SJens Scharsig u32 mask;
402ea8fbba7SJens Scharsig
403918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK)) {
404ea8fbba7SJens Scharsig mask = 1 << pin;
405ea8fbba7SJens Scharsig if (is_on)
4064bc9b7a5SBo Shen writel(mask, &at91_port->mder);
407ea8fbba7SJens Scharsig else
4084bc9b7a5SBo Shen writel(mask, &at91_port->mddr);
409ea8fbba7SJens Scharsig }
4104bc9b7a5SBo Shen
411ea8fbba7SJens Scharsig return 0;
412ea8fbba7SJens Scharsig }
413ea8fbba7SJens Scharsig
at91_set_port_value(struct at91_port * at91_port,int offset,int value)414918354b1SSimon Glass static void at91_set_port_value(struct at91_port *at91_port, int offset,
415918354b1SSimon Glass int value)
416ea8fbba7SJens Scharsig {
417ea8fbba7SJens Scharsig u32 mask;
418ea8fbba7SJens Scharsig
419918354b1SSimon Glass mask = 1 << offset;
420ea8fbba7SJens Scharsig if (value)
4214bc9b7a5SBo Shen writel(mask, &at91_port->sodr);
422ea8fbba7SJens Scharsig else
4234bc9b7a5SBo Shen writel(mask, &at91_port->codr);
424ea8fbba7SJens Scharsig }
4254bc9b7a5SBo Shen
426918354b1SSimon Glass /*
427918354b1SSimon Glass * assuming the pin is muxed as a gpio output, set its value.
428918354b1SSimon Glass */
at91_set_pio_value(unsigned port,unsigned pin,int value)429918354b1SSimon Glass int at91_set_pio_value(unsigned port, unsigned pin, int value)
430918354b1SSimon Glass {
431918354b1SSimon Glass struct at91_port *at91_port = at91_pio_get_port(port);
432918354b1SSimon Glass
433918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
434918354b1SSimon Glass at91_set_port_value(at91_port, pin, value);
435918354b1SSimon Glass
436ea8fbba7SJens Scharsig return 0;
437ea8fbba7SJens Scharsig }
438ea8fbba7SJens Scharsig
at91_get_port_value(struct at91_port * at91_port,int offset)439918354b1SSimon Glass static int at91_get_port_value(struct at91_port *at91_port, int offset)
440918354b1SSimon Glass {
441918354b1SSimon Glass u32 pdsr = 0, mask;
442918354b1SSimon Glass
443918354b1SSimon Glass mask = 1 << offset;
444918354b1SSimon Glass pdsr = readl(&at91_port->pdsr) & mask;
445918354b1SSimon Glass
446918354b1SSimon Glass return pdsr != 0;
447918354b1SSimon Glass }
448ea8fbba7SJens Scharsig /*
449ea8fbba7SJens Scharsig * read the pin's value (works even if it's not muxed as a gpio).
450ea8fbba7SJens Scharsig */
at91_get_pio_value(unsigned port,unsigned pin)451ea8fbba7SJens Scharsig int at91_get_pio_value(unsigned port, unsigned pin)
452ea8fbba7SJens Scharsig {
4534bc9b7a5SBo Shen struct at91_port *at91_port = at91_pio_get_port(port);
454ea8fbba7SJens Scharsig
455918354b1SSimon Glass if (at91_port && (pin < GPIO_PER_BANK))
456918354b1SSimon Glass return at91_get_port_value(at91_port, pin);
457918354b1SSimon Glass
458918354b1SSimon Glass return 0;
459ea8fbba7SJens Scharsig }
4604bc9b7a5SBo Shen
461918354b1SSimon Glass #ifndef CONFIG_DM_GPIO
4626edaea87SBo Shen /* Common GPIO API */
4636edaea87SBo Shen
gpio_request(unsigned gpio,const char * label)4646edaea87SBo Shen int gpio_request(unsigned gpio, const char *label)
4656edaea87SBo Shen {
4666edaea87SBo Shen return 0;
4676edaea87SBo Shen }
4686edaea87SBo Shen
gpio_free(unsigned gpio)4696edaea87SBo Shen int gpio_free(unsigned gpio)
4706edaea87SBo Shen {
4716edaea87SBo Shen return 0;
4726edaea87SBo Shen }
4736edaea87SBo Shen
gpio_direction_input(unsigned gpio)4746edaea87SBo Shen int gpio_direction_input(unsigned gpio)
4756edaea87SBo Shen {
4766edaea87SBo Shen at91_set_pio_input(at91_gpio_to_port(gpio),
4776edaea87SBo Shen at91_gpio_to_pin(gpio), 0);
4786edaea87SBo Shen return 0;
4796edaea87SBo Shen }
4806edaea87SBo Shen
gpio_direction_output(unsigned gpio,int value)4816edaea87SBo Shen int gpio_direction_output(unsigned gpio, int value)
4826edaea87SBo Shen {
4836edaea87SBo Shen at91_set_pio_output(at91_gpio_to_port(gpio),
4846edaea87SBo Shen at91_gpio_to_pin(gpio), value);
4856edaea87SBo Shen return 0;
4866edaea87SBo Shen }
4876edaea87SBo Shen
gpio_get_value(unsigned gpio)4886edaea87SBo Shen int gpio_get_value(unsigned gpio)
4896edaea87SBo Shen {
4906edaea87SBo Shen return at91_get_pio_value(at91_gpio_to_port(gpio),
4916edaea87SBo Shen at91_gpio_to_pin(gpio));
4926edaea87SBo Shen }
4936edaea87SBo Shen
gpio_set_value(unsigned gpio,int value)4946edaea87SBo Shen int gpio_set_value(unsigned gpio, int value)
4956edaea87SBo Shen {
4966edaea87SBo Shen at91_set_pio_value(at91_gpio_to_port(gpio),
4976edaea87SBo Shen at91_gpio_to_pin(gpio), value);
4986edaea87SBo Shen
4996edaea87SBo Shen return 0;
5006edaea87SBo Shen }
501918354b1SSimon Glass #endif
502918354b1SSimon Glass
503918354b1SSimon Glass #ifdef CONFIG_DM_GPIO
504918354b1SSimon Glass
505918354b1SSimon Glass struct at91_port_priv {
506918354b1SSimon Glass struct at91_port *regs;
507918354b1SSimon Glass };
508918354b1SSimon Glass
509918354b1SSimon Glass /* set GPIO pin 'gpio' as an input */
at91_gpio_direction_input(struct udevice * dev,unsigned offset)510918354b1SSimon Glass static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
511918354b1SSimon Glass {
512d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
513918354b1SSimon Glass
514918354b1SSimon Glass at91_set_port_input(port->regs, offset, 0);
515918354b1SSimon Glass
516918354b1SSimon Glass return 0;
517918354b1SSimon Glass }
518918354b1SSimon Glass
519918354b1SSimon Glass /* set GPIO pin 'gpio' as an output, with polarity 'value' */
at91_gpio_direction_output(struct udevice * dev,unsigned offset,int value)520918354b1SSimon Glass static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
521918354b1SSimon Glass int value)
522918354b1SSimon Glass {
523d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
524918354b1SSimon Glass
525918354b1SSimon Glass at91_set_port_output(port->regs, offset, value);
526918354b1SSimon Glass
527918354b1SSimon Glass return 0;
528918354b1SSimon Glass }
529918354b1SSimon Glass
530918354b1SSimon Glass /* read GPIO IN value of pin 'gpio' */
at91_gpio_get_value(struct udevice * dev,unsigned offset)531918354b1SSimon Glass static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
532918354b1SSimon Glass {
533d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
534918354b1SSimon Glass
535918354b1SSimon Glass return at91_get_port_value(port->regs, offset);
536918354b1SSimon Glass }
537918354b1SSimon Glass
538918354b1SSimon Glass /* write GPIO OUT value to pin 'gpio' */
at91_gpio_set_value(struct udevice * dev,unsigned offset,int value)539918354b1SSimon Glass static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
540918354b1SSimon Glass int value)
541918354b1SSimon Glass {
542d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
543918354b1SSimon Glass
544918354b1SSimon Glass at91_set_port_value(port->regs, offset, value);
545918354b1SSimon Glass
546918354b1SSimon Glass return 0;
547918354b1SSimon Glass }
548918354b1SSimon Glass
at91_gpio_get_function(struct udevice * dev,unsigned offset)549918354b1SSimon Glass static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
550918354b1SSimon Glass {
551d895821fSAxel Lin struct at91_port_priv *port = dev_get_priv(dev);
552918354b1SSimon Glass
553918354b1SSimon Glass /* GPIOF_FUNC is not implemented yet */
554918354b1SSimon Glass if (at91_get_port_output(port->regs, offset))
555918354b1SSimon Glass return GPIOF_OUTPUT;
556918354b1SSimon Glass else
557918354b1SSimon Glass return GPIOF_INPUT;
558918354b1SSimon Glass }
559918354b1SSimon Glass
560918354b1SSimon Glass static const struct dm_gpio_ops gpio_at91_ops = {
561918354b1SSimon Glass .direction_input = at91_gpio_direction_input,
562918354b1SSimon Glass .direction_output = at91_gpio_direction_output,
563918354b1SSimon Glass .get_value = at91_gpio_get_value,
564918354b1SSimon Glass .set_value = at91_gpio_set_value,
565918354b1SSimon Glass .get_function = at91_gpio_get_function,
566918354b1SSimon Glass };
567918354b1SSimon Glass
at91_gpio_probe(struct udevice * dev)568918354b1SSimon Glass static int at91_gpio_probe(struct udevice *dev)
569918354b1SSimon Glass {
570918354b1SSimon Glass struct at91_port_priv *port = dev_get_priv(dev);
571918354b1SSimon Glass struct at91_port_platdata *plat = dev_get_platdata(dev);
572e564f054SSimon Glass struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
573f2f3c157SWenyou Yang struct clk clk;
574f2f3c157SWenyou Yang int ret;
575f2f3c157SWenyou Yang
576f2f3c157SWenyou Yang ret = clk_get_by_index(dev, 0, &clk);
577f2f3c157SWenyou Yang if (ret)
578f2f3c157SWenyou Yang return ret;
579f2f3c157SWenyou Yang
580f2f3c157SWenyou Yang ret = clk_enable(&clk);
581f2f3c157SWenyou Yang if (ret)
582f2f3c157SWenyou Yang return ret;
583f2f3c157SWenyou Yang
584f2f3c157SWenyou Yang clk_free(&clk);
585918354b1SSimon Glass
586918354b1SSimon Glass uc_priv->bank_name = plat->bank_name;
587918354b1SSimon Glass uc_priv->gpio_count = GPIO_PER_BANK;
588cf468880SWenyou Yang
589cf468880SWenyou Yang #if CONFIG_IS_ENABLED(OF_CONTROL)
590*a821c4afSSimon Glass plat->base_addr = (uint32_t)devfdt_get_addr_ptr(dev);
591cf468880SWenyou Yang #endif
592918354b1SSimon Glass port->regs = (struct at91_port *)plat->base_addr;
593918354b1SSimon Glass
594918354b1SSimon Glass return 0;
595918354b1SSimon Glass }
596918354b1SSimon Glass
597cf468880SWenyou Yang #if CONFIG_IS_ENABLED(OF_CONTROL)
598cf468880SWenyou Yang static const struct udevice_id at91_gpio_ids[] = {
599cf468880SWenyou Yang { .compatible = "atmel,at91rm9200-gpio" },
600cf468880SWenyou Yang { }
601cf468880SWenyou Yang };
602cf468880SWenyou Yang #endif
603cf468880SWenyou Yang
604918354b1SSimon Glass U_BOOT_DRIVER(gpio_at91) = {
605918354b1SSimon Glass .name = "gpio_at91",
606918354b1SSimon Glass .id = UCLASS_GPIO,
607cf468880SWenyou Yang #if CONFIG_IS_ENABLED(OF_CONTROL)
608cf468880SWenyou Yang .of_match = at91_gpio_ids,
609cf468880SWenyou Yang .platdata_auto_alloc_size = sizeof(struct at91_port_platdata),
610cf468880SWenyou Yang #endif
611918354b1SSimon Glass .ops = &gpio_at91_ops,
612918354b1SSimon Glass .probe = at91_gpio_probe,
613918354b1SSimon Glass .priv_auto_alloc_size = sizeof(struct at91_port_priv),
614918354b1SSimon Glass };
615918354b1SSimon Glass #endif
616