blob: be2a0268e849a89f103d4877f4551f3e9b20d2c0 [file] [log] [blame]
Jens Scharsig8d065462010-02-03 22:46:16 +01001/*
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
Reinhard Meyerda480402010-11-03 15:47:20 +010027/*
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
Jens Scharsig8d065462010-02-03 22:46:16 +010037#include <config.h>
38#include <common.h>
Reinhard Meyerb06208c2010-11-07 13:26:14 +010039#include <asm/io.h>
Jens Scharsig8d065462010-02-03 22:46:16 +010040#include <asm/sizes.h>
41#include <asm/arch/hardware.h>
Jens Scharsig8d065462010-02-03 22:46:16 +010042#include <asm/arch/at91_pio.h>
43
44int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
45{
Reinhard Meyerda480402010-11-03 15:47:20 +010046 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +010047 u32 mask;
48
Reinhard Meyerda480402010-11-03 15:47:20 +010049 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +010050 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 */
63int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
64{
Reinhard Meyerda480402010-11-03 15:47:20 +010065 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +010066 u32 mask;
67
Reinhard Meyerda480402010-11-03 15:47:20 +010068 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +010069 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 */
80int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
81{
Reinhard Meyerda480402010-11-03 15:47:20 +010082 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +010083 u32 mask;
84
Reinhard Meyerda480402010-11-03 15:47:20 +010085 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +010086 mask = 1 << pin;
87 writel(mask, &pio->port[port].idr);
88 at91_set_pio_pullup(port, pin, use_pullup);
89 writel(mask, &pio->port[port].asr);
90 writel(mask, &pio->port[port].pdr);
91 }
92 return 0;
93}
94
95/*
96 * mux the pin to the "B" internal peripheral role.
97 */
98int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
99{
Reinhard Meyerda480402010-11-03 15:47:20 +0100100 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100101 u32 mask;
102
Reinhard Meyerda480402010-11-03 15:47:20 +0100103 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100104 mask = 1 << pin;
105 writel(mask, &pio->port[port].idr);
106 at91_set_pio_pullup(port, pin, use_pullup);
107 writel(mask, &pio->port[port].bsr);
108 writel(mask, &pio->port[port].pdr);
109 }
110 return 0;
111}
112
113/*
114 * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
115 * configure it for an input.
116 */
117int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
118{
Reinhard Meyerda480402010-11-03 15:47:20 +0100119 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100120 u32 mask;
121
Reinhard Meyerda480402010-11-03 15:47:20 +0100122 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100123 mask = 1 << pin;
124 writel(mask, &pio->port[port].idr);
125 at91_set_pio_pullup(port, pin, use_pullup);
126 writel(mask, &pio->port[port].odr);
127 writel(mask, &pio->port[port].per);
128 }
129 return 0;
130}
131
132/*
133 * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
134 * and configure it for an output.
135 */
136int at91_set_pio_output(unsigned port, u32 pin, int value)
137{
Reinhard Meyerda480402010-11-03 15:47:20 +0100138 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100139 u32 mask;
140
Reinhard Meyerda480402010-11-03 15:47:20 +0100141 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100142 mask = 1 << pin;
143 writel(mask, &pio->port[port].idr);
144 writel(mask, &pio->port[port].pudr);
145 if (value)
146 writel(mask, &pio->port[port].sodr);
147 else
148 writel(mask, &pio->port[port].codr);
149 writel(mask, &pio->port[port].oer);
150 writel(mask, &pio->port[port].per);
151 }
152 return 0;
153}
154
155/*
156 * enable/disable the glitch filter. mostly used with IRQ handling.
157 */
158int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
159{
Reinhard Meyerda480402010-11-03 15:47:20 +0100160 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100161 u32 mask;
162
Reinhard Meyerda480402010-11-03 15:47:20 +0100163 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100164 mask = 1 << pin;
165 if (is_on)
166 writel(mask, &pio->port[port].ifer);
167 else
168 writel(mask, &pio->port[port].ifdr);
169 }
170 return 0;
171}
172
173/*
174 * enable/disable the multi-driver. This is only valid for output and
175 * allows the output pin to run as an open collector output.
176 */
177int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
178{
Reinhard Meyerda480402010-11-03 15:47:20 +0100179 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100180 u32 mask;
181
Reinhard Meyerda480402010-11-03 15:47:20 +0100182 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100183 mask = 1 << pin;
184 if (is_on)
185 writel(mask, &pio->port[port].mder);
186 else
187 writel(mask, &pio->port[port].mddr);
188 }
189 return 0;
190}
191
192/*
193 * assuming the pin is muxed as a gpio output, set its value.
194 */
195int at91_set_pio_value(unsigned port, unsigned pin, int value)
196{
Reinhard Meyerda480402010-11-03 15:47:20 +0100197 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100198 u32 mask;
199
Reinhard Meyerda480402010-11-03 15:47:20 +0100200 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100201 mask = 1 << pin;
202 if (value)
203 writel(mask, &pio->port[port].sodr);
204 else
205 writel(mask, &pio->port[port].codr);
206 }
207 return 0;
208}
209
210/*
211 * read the pin's value (works even if it's not muxed as a gpio).
212 */
213int at91_get_pio_value(unsigned port, unsigned pin)
214{
Reinhard Meyerda480402010-11-03 15:47:20 +0100215 u32 pdsr = 0;
216 at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA;
Jens Scharsig8d065462010-02-03 22:46:16 +0100217 u32 mask;
218
Reinhard Meyerda480402010-11-03 15:47:20 +0100219 if ((port < ATMEL_PIO_PORTS) && (pin < 32)) {
Jens Scharsig8d065462010-02-03 22:46:16 +0100220 mask = 1 << pin;
221 pdsr = readl(&pio->port[port].pdsr) & mask;
222 }
223 return pdsr != 0;
224}