xref: /openbmc/u-boot/drivers/gpio/at91_gpio.c (revision 6f6ea814)
1 /*
2  * Memory Setup stuff - taken from blob memsetup.S
3  *
4  * Copyright (C) 2009 Jens Scharsig (js_at_ng@scharsoft.de)
5  *
6  *  Copyright (C) 2005 HP Labs
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26 
27 /*
28  * WARNING:
29  *
30  * As the code is right now, it expects all PIO ports A,B,C,...
31  * to be evenly spaced in the memory map:
32  * ATMEL_BASE_PIOA + port * sizeof at91pio_t
33  * This might not necessaryly be true in future Atmel SoCs.
34  * This code should be fixed to use a pointer array to the ports.
35  */
36 
37 #include <config.h>
38 #include <common.h>
39 #include <asm/io.h>
40 #include <asm/sizes.h>
41 #include <asm/arch/hardware.h>
42 #include <asm/arch/at91_pio.h>
43 
44 int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
45 {
46 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
47 	u32		mask;
48 
49 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
50 		mask = 1 << pin;
51 		if (use_pullup)
52 			writel(1 << pin, &pio->port[port].puer);
53 		else
54 			writel(1 << pin, &pio->port[port].pudr);
55 		writel(mask, &pio->port[port].per);
56 	}
57 	return 0;
58 }
59 
60 /*
61  * mux the pin to the "GPIO" peripheral role.
62  */
63 int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
64 {
65 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
66 	u32		mask;
67 
68 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
69 		mask = 1 << pin;
70 		writel(mask, &pio->port[port].idr);
71 		at91_set_pio_pullup(port, pin, use_pullup);
72 		writel(mask, &pio->port[port].per);
73 	}
74 	return 0;
75 }
76 
77 /*
78  * mux the pin to the "A" internal peripheral role.
79  */
80 int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
81 {
82 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
83 	u32		mask;
84 
85 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
86 		mask = 1 << pin;
87 		writel(mask, &pio->port[port].idr);
88 		at91_set_pio_pullup(port, pin, use_pullup);
89 #if defined(CPU_HAS_PIO3)
90 		writel(readl(&pio->port[port].abcdsr1) & ~mask,
91 			&pio->port[port].abcdsr1);
92 		writel(readl(&pio->port[port].abcdsr2) & ~mask,
93 			&pio->port[port].abcdsr2);
94 #else
95 		writel(mask, &pio->port[port].asr);
96 #endif
97 		writel(mask, &pio->port[port].pdr);
98 	}
99 	return 0;
100 }
101 
102 /*
103  * mux the pin to the "B" internal peripheral role.
104  */
105 int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
106 {
107 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
108 	u32		mask;
109 
110 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
111 		mask = 1 << pin;
112 		writel(mask, &pio->port[port].idr);
113 		at91_set_pio_pullup(port, pin, use_pullup);
114 #if defined(CPU_HAS_PIO3)
115 		writel(readl(&pio->port[port].abcdsr1) | mask,
116 			&pio->port[port].abcdsr1);
117 		writel(readl(&pio->port[port].abcdsr2) & ~mask,
118 			&pio->port[port].abcdsr2);
119 #else
120 		writel(mask, &pio->port[port].bsr);
121 #endif
122 		writel(mask, &pio->port[port].pdr);
123 	}
124 	return 0;
125 }
126 
127 #if defined(CPU_HAS_PIO3)
128 /*
129  * mux the pin to the "C" internal peripheral role.
130  */
131 int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
132 {
133 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
134 	u32		mask;
135 
136 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
137 		mask = 1 << pin;
138 		writel(mask, &pio->port[port].idr);
139 		at91_set_pio_pullup(port, pin, use_pullup);
140 		writel(readl(&pio->port[port].abcdsr1) & ~mask,
141 			&pio->port[port].abcdsr1);
142 		writel(readl(&pio->port[port].abcdsr2) | mask,
143 			&pio->port[port].abcdsr2);
144 		writel(mask, &pio->port[port].pdr);
145 	}
146 	return 0;
147 }
148 
149 /*
150  * mux the pin to the "D" internal peripheral role.
151  */
152 int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
153 {
154 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
155 	u32		mask;
156 
157 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
158 		mask = 1 << pin;
159 		writel(mask, &pio->port[port].idr);
160 		at91_set_pio_pullup(port, pin, use_pullup);
161 		writel(readl(&pio->port[port].abcdsr1) | mask,
162 			&pio->port[port].abcdsr1);
163 		writel(readl(&pio->port[port].abcdsr2) | mask,
164 			&pio->port[port].abcdsr2);
165 		writel(mask, &pio->port[port].pdr);
166 	}
167 	return 0;
168 }
169 #endif
170 
171 /*
172  * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
173  * configure it for an input.
174  */
175 int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
176 {
177 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
178 	u32		mask;
179 
180 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
181 		mask = 1 << pin;
182 		writel(mask, &pio->port[port].idr);
183 		at91_set_pio_pullup(port, pin, use_pullup);
184 		writel(mask, &pio->port[port].odr);
185 		writel(mask, &pio->port[port].per);
186 	}
187 	return 0;
188 }
189 
190 /*
191  * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
192  * and configure it for an output.
193  */
194 int at91_set_pio_output(unsigned port, u32 pin, int value)
195 {
196 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
197 	u32		mask;
198 
199 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
200 		mask = 1 << pin;
201 		writel(mask, &pio->port[port].idr);
202 		writel(mask, &pio->port[port].pudr);
203 		if (value)
204 			writel(mask, &pio->port[port].sodr);
205 		else
206 			writel(mask, &pio->port[port].codr);
207 		writel(mask, &pio->port[port].oer);
208 		writel(mask, &pio->port[port].per);
209 	}
210 	return 0;
211 }
212 
213 /*
214  * enable/disable the glitch filter. mostly used with IRQ handling.
215  */
216 int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
217 {
218 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
219 	u32		mask;
220 
221 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
222 		mask = 1 << pin;
223 		if (is_on) {
224 #if defined(CPU_HAS_PIO3)
225 			writel(mask, &pio->port[port].ifscdr);
226 #endif
227 			writel(mask, &pio->port[port].ifer);
228 		} else {
229 			writel(mask, &pio->port[port].ifdr);
230 		}
231 	}
232 	return 0;
233 }
234 
235 #if defined(CPU_HAS_PIO3)
236 /*
237  * enable/disable the debounce filter.
238  */
239 int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
240 {
241 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
242 	u32		mask;
243 
244 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
245 		mask = 1 << pin;
246 		if (is_on) {
247 			writel(mask, &pio->port[port].ifscer);
248 			writel(div & PIO_SCDR_DIV, &pio->port[port].scdr);
249 			writel(mask, &pio->port[port].ifer);
250 		} else {
251 			writel(mask, &pio->port[port].ifdr);
252 		}
253 	}
254 	return 0;
255 }
256 
257 /*
258  * enable/disable the pull-down.
259  * If pull-up already enabled while calling the function, we disable it.
260  */
261 int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
262 {
263 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
264 	u32		mask;
265 
266 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
267 		mask = 1 << pin;
268 		writel(mask, &pio->port[port].pudr);
269 		if (is_on)
270 			writel(mask, &pio->port[port].ppder);
271 		else
272 			writel(mask, &pio->port[port].ppddr);
273 	}
274 	return 0;
275 }
276 
277 /*
278  * disable Schmitt trigger
279  */
280 int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
281 {
282 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
283 	u32		mask;
284 
285 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
286 		mask = 1 << pin;
287 		writel(readl(&pio->port[port].schmitt) | mask,
288 			&pio->port[port].schmitt);
289 	}
290 	return 0;
291 }
292 #endif
293 
294 /*
295  * enable/disable the multi-driver. This is only valid for output and
296  * allows the output pin to run as an open collector output.
297  */
298 int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
299 {
300 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
301 	u32		mask;
302 
303 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
304 		mask = 1 << pin;
305 		if (is_on)
306 			writel(mask, &pio->port[port].mder);
307 		else
308 			writel(mask, &pio->port[port].mddr);
309 	}
310 	return 0;
311 }
312 
313 /*
314  * assuming the pin is muxed as a gpio output, set its value.
315  */
316 int at91_set_pio_value(unsigned port, unsigned pin, int value)
317 {
318 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
319 	u32		mask;
320 
321 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
322 		mask = 1 << pin;
323 		if (value)
324 			writel(mask, &pio->port[port].sodr);
325 		else
326 			writel(mask, &pio->port[port].codr);
327 	}
328 	return 0;
329 }
330 
331 /*
332  * read the pin's value (works even if it's not muxed as a gpio).
333  */
334 int at91_get_pio_value(unsigned port, unsigned pin)
335 {
336 	u32		pdsr = 0;
337 	at91_pio_t	*pio = (at91_pio_t *) ATMEL_BASE_PIOA;
338 	u32		mask;
339 
340 	if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
341 		mask = 1 << pin;
342 		pdsr = readl(&pio->port[port].pdsr) & mask;
343 	}
344 	return pdsr != 0;
345 }
346