blob: 1409db5dc115fdb8dc2c1d674075d27a6552a994 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Jens Scharsigea8fbba2010-02-03 22:46:16 +01002/*
Bo Shen39b787e2013-08-13 14:38:32 +08003 * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com>
Jens Scharsigea8fbba2010-02-03 22:46:16 +01004 *
5 * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de)
6 *
7 * Copyright (C) 2005 HP Labs
Jens Scharsigea8fbba2010-02-03 22:46:16 +01008 */
9
10#include <config.h>
11#include <common.h>
Wenyou Yangf2f3c152017-03-23 12:46:21 +080012#include <clk.h>
Simon Glass918354b2014-10-29 13:08:57 -060013#include <dm.h>
Simon Glass336d4612020-02-03 07:36:16 -070014#include <malloc.h>
Reinhard Meyer86592f62010-11-07 13:26:14 +010015#include <asm/io.h>
Alexey Brodkin1ace4022014-02-26 17:47:58 +040016#include <linux/sizes.h>
Simon Glass918354b2014-10-29 13:08:57 -060017#include <asm/gpio.h>
Jens Scharsigea8fbba2010-02-03 22:46:16 +010018#include <asm/arch/hardware.h>
Jens Scharsigea8fbba2010-02-03 22:46:16 +010019#include <asm/arch/at91_pio.h>
Simon Glass918354b2014-10-29 13:08:57 -060020
21#define GPIO_PER_BANK 32
Jens Scharsigea8fbba2010-02-03 22:46:16 +010022
Bo Shen4bc9b7a2013-08-22 15:24:40 +080023static 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:
Wu, Josh7d82d892014-05-07 16:50:45 +080041 printf("Error: at91_gpio: Fail to get PIO base!\n");
Bo Shen4bc9b7a2013-08-22 15:24:40 +080042 return NULL;
43 }
44}
45
Simon Glass918354b2014-10-29 13:08:57 -060046static 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
Jens Scharsigea8fbba2010-02-03 22:46:16 +010059int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
60{
Bo Shen4bc9b7a2013-08-22 15:24:40 +080061 struct at91_port *at91_port = at91_pio_get_port(port);
Jens Scharsigea8fbba2010-02-03 22:46:16 +010062
Simon Glass918354b2014-10-29 13:08:57 -060063 if (at91_port && (pin < GPIO_PER_BANK))
64 at91_set_port_pullup(at91_port, pin, use_pullup);
Bo Shen4bc9b7a2013-08-22 15:24:40 +080065
Jens Scharsigea8fbba2010-02-03 22:46:16 +010066 return 0;
67}
68
69/*
70 * mux the pin to the "GPIO" peripheral role.
71 */
72int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
73{
Bo Shen4bc9b7a2013-08-22 15:24:40 +080074 struct at91_port *at91_port = at91_pio_get_port(port);
75 u32 mask;
Jens Scharsigea8fbba2010-02-03 22:46:16 +010076
Simon Glass918354b2014-10-29 13:08:57 -060077 if (at91_port && (pin < GPIO_PER_BANK)) {
Jens Scharsigea8fbba2010-02-03 22:46:16 +010078 mask = 1 << pin;
Bo Shen4bc9b7a2013-08-22 15:24:40 +080079 writel(mask, &at91_port->idr);
Jens Scharsigea8fbba2010-02-03 22:46:16 +010080 at91_set_pio_pullup(port, pin, use_pullup);
Bo Shen4bc9b7a2013-08-22 15:24:40 +080081 writel(mask, &at91_port->per);
Jens Scharsigea8fbba2010-02-03 22:46:16 +010082 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +080083
Jens Scharsigea8fbba2010-02-03 22:46:16 +010084 return 0;
85}
86
87/*
88 * mux the pin to the "A" internal peripheral role.
89 */
90int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
91{
Bo Shen4bc9b7a2013-08-22 15:24:40 +080092 struct at91_port *at91_port = at91_pio_get_port(port);
93 u32 mask;
Jens Scharsigea8fbba2010-02-03 22:46:16 +010094
Simon Glass918354b2014-10-29 13:08:57 -060095 if (at91_port && (pin < GPIO_PER_BANK)) {
Jens Scharsigea8fbba2010-02-03 22:46:16 +010096 mask = 1 << pin;
Bo Shen4bc9b7a2013-08-22 15:24:40 +080097 writel(mask, &at91_port->idr);
Jens Scharsigea8fbba2010-02-03 22:46:16 +010098 at91_set_pio_pullup(port, pin, use_pullup);
Wenyou Yang2dc63f72017-03-23 12:44:36 +080099 writel(mask, &at91_port->mux.pio2.asr);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800100 writel(mask, &at91_port->pdr);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100101 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800102
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100103 return 0;
104}
105
106/*
107 * mux the pin to the "B" internal peripheral role.
108 */
109int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
110{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800111 struct at91_port *at91_port = at91_pio_get_port(port);
112 u32 mask;
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100113
Simon Glass918354b2014-10-29 13:08:57 -0600114 if (at91_port && (pin < GPIO_PER_BANK)) {
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100115 mask = 1 << pin;
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800116 writel(mask, &at91_port->idr);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100117 at91_set_pio_pullup(port, pin, use_pullup);
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800118 writel(mask, &at91_port->mux.pio2.bsr);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800119 writel(mask, &at91_port->pdr);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100120 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800121
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100122 return 0;
123}
124
Bo Shen2b3b1c62012-05-20 15:50:00 +0000125/*
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800126 * mux the pin to the "A" internal peripheral role.
Bo Shen2b3b1c62012-05-20 15:50:00 +0000127 */
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800128int at91_pio3_set_a_periph(unsigned port, unsigned pin, int use_pullup)
Bo Shen2b3b1c62012-05-20 15:50:00 +0000129{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800130 struct at91_port *at91_port = at91_pio_get_port(port);
131 u32 mask;
Bo Shen2b3b1c62012-05-20 15:50:00 +0000132
Simon Glass918354b2014-10-29 13:08:57 -0600133 if (at91_port && (pin < GPIO_PER_BANK)) {
Bo Shen2b3b1c62012-05-20 15:50:00 +0000134 mask = 1 << pin;
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800135 writel(mask, &at91_port->idr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000136 at91_set_pio_pullup(port, pin, use_pullup);
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800137 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 */
151int 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}
170/*
171 * mux the pin to the "C" internal peripheral role.
172 */
173int at91_pio3_set_c_periph(unsigned port, unsigned pin, int use_pullup)
174{
175 struct at91_port *at91_port = at91_pio_get_port(port);
176 u32 mask;
177
178 if (at91_port && (pin < GPIO_PER_BANK)) {
179 mask = 1 << pin;
180 writel(mask, &at91_port->idr);
181 at91_set_pio_pullup(port, pin, use_pullup);
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);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800186 writel(mask, &at91_port->pdr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000187 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800188
Bo Shen2b3b1c62012-05-20 15:50:00 +0000189 return 0;
190}
191
192/*
193 * mux the pin to the "D" internal peripheral role.
194 */
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800195int at91_pio3_set_d_periph(unsigned port, unsigned pin, int use_pullup)
Bo Shen2b3b1c62012-05-20 15:50:00 +0000196{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800197 struct at91_port *at91_port = at91_pio_get_port(port);
198 u32 mask;
Bo Shen2b3b1c62012-05-20 15:50:00 +0000199
Simon Glass918354b2014-10-29 13:08:57 -0600200 if (at91_port && (pin < GPIO_PER_BANK)) {
Bo Shen2b3b1c62012-05-20 15:50:00 +0000201 mask = 1 << pin;
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800202 writel(mask, &at91_port->idr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000203 at91_set_pio_pullup(port, pin, use_pullup);
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800204 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);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800208 writel(mask, &at91_port->pdr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000209 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800210
Bo Shen2b3b1c62012-05-20 15:50:00 +0000211 return 0;
212}
Bo Shen2b3b1c62012-05-20 15:50:00 +0000213
Simon Glassbcee8d62019-12-06 21:41:35 -0700214#if CONFIG_IS_ENABLED(DM_GPIO)
Simon Glass918354b2014-10-29 13:08:57 -0600215static 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
225static 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
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100237/*
238 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
239 * configure it for an input.
240 */
241int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
242{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800243 struct at91_port *at91_port = at91_pio_get_port(port);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100244
Simon Glass918354b2014-10-29 13:08:57 -0600245 if (at91_port && (pin < GPIO_PER_BANK))
246 at91_set_port_input(at91_port, pin, use_pullup);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800247
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100248 return 0;
249}
250
Simon Glass918354b2014-10-29 13:08:57 -0600251static 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
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100267/*
268 * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
269 * and configure it for an output.
270 */
271int at91_set_pio_output(unsigned port, u32 pin, int value)
272{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800273 struct at91_port *at91_port = at91_pio_get_port(port);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100274
Simon Glass918354b2014-10-29 13:08:57 -0600275 if (at91_port && (pin < GPIO_PER_BANK))
276 at91_set_port_output(at91_port, pin, value);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800277
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100278 return 0;
279}
280
281/*
282 * enable/disable the glitch filter. mostly used with IRQ handling.
283 */
284int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
285{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800286 struct at91_port *at91_port = at91_pio_get_port(port);
287 u32 mask;
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100288
Simon Glass918354b2014-10-29 13:08:57 -0600289 if (at91_port && (pin < GPIO_PER_BANK)) {
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100290 mask = 1 << pin;
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800291 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 */
303int 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
308 if (at91_port && (pin < GPIO_PER_BANK)) {
309 mask = 1 << pin;
Bo Shen2b3b1c62012-05-20 15:50:00 +0000310 if (is_on) {
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800311 writel(mask, &at91_port->mux.pio3.ifscdr);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800312 writel(mask, &at91_port->ifer);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000313 } else {
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800314 writel(mask, &at91_port->ifdr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000315 }
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100316 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800317
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100318 return 0;
319}
320
Bo Shen2b3b1c62012-05-20 15:50:00 +0000321/*
322 * enable/disable the debounce filter.
323 */
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800324int at91_pio3_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
Bo Shen2b3b1c62012-05-20 15:50:00 +0000325{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800326 struct at91_port *at91_port = at91_pio_get_port(port);
327 u32 mask;
Bo Shen2b3b1c62012-05-20 15:50:00 +0000328
Simon Glass918354b2014-10-29 13:08:57 -0600329 if (at91_port && (pin < GPIO_PER_BANK)) {
Bo Shen2b3b1c62012-05-20 15:50:00 +0000330 mask = 1 << pin;
331 if (is_on) {
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800332 writel(mask, &at91_port->mux.pio3.ifscer);
333 writel(div & PIO_SCDR_DIV, &at91_port->mux.pio3.scdr);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800334 writel(mask, &at91_port->ifer);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000335 } else {
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800336 writel(mask, &at91_port->ifdr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000337 }
338 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800339
Bo Shen2b3b1c62012-05-20 15:50:00 +0000340 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 */
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800347int at91_pio3_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
Bo Shen2b3b1c62012-05-20 15:50:00 +0000348{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800349 struct at91_port *at91_port = at91_pio_get_port(port);
350 u32 mask;
Bo Shen2b3b1c62012-05-20 15:50:00 +0000351
Simon Glass918354b2014-10-29 13:08:57 -0600352 if (at91_port && (pin < GPIO_PER_BANK)) {
Bo Shen2b3b1c62012-05-20 15:50:00 +0000353 mask = 1 << pin;
Marek Vasut152ac5f2016-05-04 23:05:23 +0200354 if (is_on) {
355 at91_set_pio_pullup(port, pin, 0);
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800356 writel(mask, &at91_port->mux.pio3.ppder);
Marek Vasut152ac5f2016-05-04 23:05:23 +0200357 } else
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800358 writel(mask, &at91_port->mux.pio3.ppddr);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000359 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800360
Bo Shen2b3b1c62012-05-20 15:50:00 +0000361 return 0;
362}
363
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800364int 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
Bo Shen2b3b1c62012-05-20 15:50:00 +0000377/*
378 * disable Schmitt trigger
379 */
Wenyou Yang2dc63f72017-03-23 12:44:36 +0800380int at91_pio3_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
Bo Shen2b3b1c62012-05-20 15:50:00 +0000381{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800382 struct at91_port *at91_port = at91_pio_get_port(port);
383 u32 mask;
Bo Shen2b3b1c62012-05-20 15:50:00 +0000384
Simon Glass918354b2014-10-29 13:08:57 -0600385 if (at91_port && (pin < GPIO_PER_BANK)) {
Bo Shen2b3b1c62012-05-20 15:50:00 +0000386 mask = 1 << pin;
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800387 writel(readl(&at91_port->schmitt) | mask,
388 &at91_port->schmitt);
Bo Shen2b3b1c62012-05-20 15:50:00 +0000389 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800390
Bo Shen2b3b1c62012-05-20 15:50:00 +0000391 return 0;
392}
Bo Shen2b3b1c62012-05-20 15:50:00 +0000393
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100394/*
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 */
398int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
399{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800400 struct at91_port *at91_port = at91_pio_get_port(port);
401 u32 mask;
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100402
Simon Glass918354b2014-10-29 13:08:57 -0600403 if (at91_port && (pin < GPIO_PER_BANK)) {
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100404 mask = 1 << pin;
405 if (is_on)
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800406 writel(mask, &at91_port->mder);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100407 else
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800408 writel(mask, &at91_port->mddr);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100409 }
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800410
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100411 return 0;
412}
413
Simon Glass918354b2014-10-29 13:08:57 -0600414static 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
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100426/*
427 * assuming the pin is muxed as a gpio output, set its value.
428 */
429int at91_set_pio_value(unsigned port, unsigned pin, int value)
430{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800431 struct at91_port *at91_port = at91_pio_get_port(port);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100432
Simon Glass918354b2014-10-29 13:08:57 -0600433 if (at91_port && (pin < GPIO_PER_BANK))
434 at91_set_port_value(at91_port, pin, value);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800435
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100436 return 0;
437}
438
Simon Glass918354b2014-10-29 13:08:57 -0600439static 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}
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100448/*
449 * read the pin's value (works even if it's not muxed as a gpio).
450 */
451int at91_get_pio_value(unsigned port, unsigned pin)
452{
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800453 struct at91_port *at91_port = at91_pio_get_port(port);
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100454
Simon Glass918354b2014-10-29 13:08:57 -0600455 if (at91_port && (pin < GPIO_PER_BANK))
456 return at91_get_port_value(at91_port, pin);
Bo Shen4bc9b7a2013-08-22 15:24:40 +0800457
Simon Glass918354b2014-10-29 13:08:57 -0600458 return 0;
Jens Scharsigea8fbba2010-02-03 22:46:16 +0100459}
Bo Shen6edaea82013-08-13 14:38:31 +0800460
Simon Glassbcee8d62019-12-06 21:41:35 -0700461#if !CONFIG_IS_ENABLED(DM_GPIO)
Bo Shen6edaea82013-08-13 14:38:31 +0800462/* Common GPIO API */
463
Bo Shen6edaea82013-08-13 14:38:31 +0800464int gpio_request(unsigned gpio, const char *label)
465{
466 return 0;
467}
468
469int gpio_free(unsigned gpio)
470{
471 return 0;
472}
473
474int 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
481int 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
488int 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
494int 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}
Simon Glass918354b2014-10-29 13:08:57 -0600501#endif
502
Simon Glassbcee8d62019-12-06 21:41:35 -0700503#if CONFIG_IS_ENABLED(DM_GPIO)
Simon Glass918354b2014-10-29 13:08:57 -0600504
505struct at91_port_priv {
506 struct at91_port *regs;
507};
508
509/* set GPIO pin 'gpio' as an input */
510static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
511{
Axel Lind8958212015-01-31 14:47:34 +0800512 struct at91_port_priv *port = dev_get_priv(dev);
Simon Glass918354b2014-10-29 13:08:57 -0600513
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' */
520static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
521 int value)
522{
Axel Lind8958212015-01-31 14:47:34 +0800523 struct at91_port_priv *port = dev_get_priv(dev);
Simon Glass918354b2014-10-29 13:08:57 -0600524
525 at91_set_port_output(port->regs, offset, value);
526
527 return 0;
528}
529
530/* read GPIO IN value of pin 'gpio' */
531static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
532{
Axel Lind8958212015-01-31 14:47:34 +0800533 struct at91_port_priv *port = dev_get_priv(dev);
Simon Glass918354b2014-10-29 13:08:57 -0600534
535 return at91_get_port_value(port->regs, offset);
536}
537
538/* write GPIO OUT value to pin 'gpio' */
539static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
540 int value)
541{
Axel Lind8958212015-01-31 14:47:34 +0800542 struct at91_port_priv *port = dev_get_priv(dev);
Simon Glass918354b2014-10-29 13:08:57 -0600543
544 at91_set_port_value(port->regs, offset, value);
545
546 return 0;
547}
548
549static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
550{
Axel Lind8958212015-01-31 14:47:34 +0800551 struct at91_port_priv *port = dev_get_priv(dev);
Simon Glass918354b2014-10-29 13:08:57 -0600552
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
James Byrnef3510e92019-11-26 11:52:04 +0000560static const char *at91_get_bank_name(uint32_t base_addr)
561{
562 switch (base_addr) {
563 case ATMEL_BASE_PIOA:
564 return "PIOA";
565 case ATMEL_BASE_PIOB:
566 return "PIOB";
567 case ATMEL_BASE_PIOC:
568 return "PIOC";
569#if (ATMEL_PIO_PORTS > 3)
570 case ATMEL_BASE_PIOD:
571 return "PIOD";
572#if (ATMEL_PIO_PORTS > 4)
573 case ATMEL_BASE_PIOE:
574 return "PIOE";
575#endif
576#endif
577 }
578
579 return "undefined";
580}
581
Simon Glass918354b2014-10-29 13:08:57 -0600582static const struct dm_gpio_ops gpio_at91_ops = {
583 .direction_input = at91_gpio_direction_input,
584 .direction_output = at91_gpio_direction_output,
585 .get_value = at91_gpio_get_value,
586 .set_value = at91_gpio_set_value,
587 .get_function = at91_gpio_get_function,
588};
589
590static int at91_gpio_probe(struct udevice *dev)
591{
592 struct at91_port_priv *port = dev_get_priv(dev);
Simon Glass8a8d24b2020-12-03 16:55:23 -0700593 struct at91_port_plat *plat = dev_get_plat(dev);
Simon Glasse564f052015-03-05 12:25:20 -0700594 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
Wenyou Yangf2f3c152017-03-23 12:46:21 +0800595 struct clk clk;
596 int ret;
597
598 ret = clk_get_by_index(dev, 0, &clk);
599 if (ret)
600 return ret;
601
602 ret = clk_enable(&clk);
603 if (ret)
604 return ret;
605
606 clk_free(&clk);
Simon Glass918354b2014-10-29 13:08:57 -0600607
Wenyou Yangcf468882017-03-23 12:46:20 +0800608#if CONFIG_IS_ENABLED(OF_CONTROL)
Masahiro Yamada0cbf3e02020-08-04 14:14:41 +0900609 plat->base_addr = dev_read_addr(dev);
Wenyou Yangcf468882017-03-23 12:46:20 +0800610#endif
James Byrnef3510e92019-11-26 11:52:04 +0000611 plat->bank_name = at91_get_bank_name(plat->base_addr);
Simon Glass918354b2014-10-29 13:08:57 -0600612 port->regs = (struct at91_port *)plat->base_addr;
613
James Byrnef3510e92019-11-26 11:52:04 +0000614 uc_priv->bank_name = plat->bank_name;
615 uc_priv->gpio_count = GPIO_PER_BANK;
616
Simon Glass918354b2014-10-29 13:08:57 -0600617 return 0;
618}
619
Wenyou Yangcf468882017-03-23 12:46:20 +0800620#if CONFIG_IS_ENABLED(OF_CONTROL)
621static const struct udevice_id at91_gpio_ids[] = {
622 { .compatible = "atmel,at91rm9200-gpio" },
623 { }
624};
625#endif
626
Walter Lozanoe3e24702020-06-25 01:10:04 -0300627U_BOOT_DRIVER(atmel_at91rm9200_gpio) = {
628 .name = "atmel_at91rm9200_gpio",
Simon Glass918354b2014-10-29 13:08:57 -0600629 .id = UCLASS_GPIO,
Wenyou Yangcf468882017-03-23 12:46:20 +0800630#if CONFIG_IS_ENABLED(OF_CONTROL)
631 .of_match = at91_gpio_ids,
Simon Glass8a8d24b2020-12-03 16:55:23 -0700632 .plat_auto = sizeof(struct at91_port_plat),
Wenyou Yangcf468882017-03-23 12:46:20 +0800633#endif
Simon Glass918354b2014-10-29 13:08:57 -0600634 .ops = &gpio_at91_ops,
635 .probe = at91_gpio_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700636 .priv_auto = sizeof(struct at91_port_priv),
Simon Glass918354b2014-10-29 13:08:57 -0600637};
638#endif