]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/st-ericsson/u8500/gpio.c
armv7: Add support for ST-Ericsson U8500 href platform
[people/ms/u-boot.git] / board / st-ericsson / u8500 / gpio.c
CommitLineData
afbf8899
JR
1/*
2 * Copyright (C) ST-Ericsson SA 2009
3 *
4 * See file CREDITS for list of people who contributed to this
5 * project.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23#include <common.h>
24#include <asm/arch/gpio.h>
25
26static struct gpio_register *addr_gpio_register[] = {
27 (void *)U8500_GPIO_0_BASE,
28 (void *)U8500_GPIO_1_BASE,
29 (void *)U8500_GPIO_2_BASE,
30 (void *)U8500_GPIO_3_BASE,
31 (void *)U8500_GPIO_4_BASE,
32 (void *)U8500_GPIO_5_BASE,
33 (void *)U8500_GPIO_6_BASE,
34 (void *)U8500_GPIO_7_BASE,
35 (void *)U8500_GPIO_8_BASE,
36};
37
38struct gpio_altfun_data altfun_table[] = {
39 {
40 .altfun = GPIO_ALT_I2C_0,
41 .start = 147,
42 .end = 148,
43 .cont = 0,
44 .type = GPIO_ALTF_A,
45 },
46 {
47 .altfun = GPIO_ALT_I2C_1,
48 .start = 16,
49 .end = 17,
50 .cont = 0,
51 .type = GPIO_ALTF_B,
52 },
53 {
54 .altfun = GPIO_ALT_I2C_2,
55 .start = 10,
56 .end = 11,
57 .cont = 0,
58 .type = GPIO_ALTF_B,
59 },
60 {
61 .altfun = GPIO_ALT_I2C_3,
62 .start = 229,
63 .end = 230,
64 .cont = 0,
65 .type = GPIO_ALTF_C,
66 },
67 {
68 .altfun = GPIO_ALT_UART_0_MODEM,
69 .start = 0,
70 .end = 3,
71 .cont = 1,
72 .type = GPIO_ALTF_A,
73 },
74 {
75 .altfun = GPIO_ALT_UART_0_MODEM,
76 .start = 33,
77 .end = 36,
78 .cont = 0,
79 .type = GPIO_ALTF_C,
80 },
81 {
82 .altfun = GPIO_ALT_UART_1,
83 .start = 4,
84 .end = 7,
85 .cont = 0,
86 .type =
87 GPIO_ALTF_A,
88 },
89 {
90 .altfun = GPIO_ALT_UART_2,
91 .start = 18,
92 .end = 19,
93 .cont = 1,
94 .type = GPIO_ALTF_B,
95 },
96 {
97 .altfun = GPIO_ALT_UART_2,
98 .start = 29,
99 .end = 32,
100 .cont = 0,
101 .type = GPIO_ALTF_C,
102 },
103 {
104 .altfun = GPIO_ALT_MSP_0,
105 .start = 12,
106 .end = 17,
107 .cont = 1,
108 .type = GPIO_ALTF_A,
109 },
110 {
111 .altfun = GPIO_ALT_MSP_0,
112 .start = 21,
113 .end = 21,
114 .cont = 0,
115 .type = GPIO_ALTF_B,
116 },
117 {
118 .altfun = GPIO_ALT_MSP_1,
119 .start = 33,
120 .end = 36,
121 .cont = 0,
122 .type = GPIO_ALTF_A,
123 },
124 {
125 .altfun = GPIO_ALT_MSP_2,
126 .start = 192,
127 .end = 196,
128 .cont = 0,
129 .type = GPIO_ALTF_A,
130 },
131 {
132 .altfun = GPIO_ALT_LCD_PANEL,
133 .start = 64,
134 .end = 93,
135 .cont = 1,
136 .type = GPIO_ALTF_A,
137 },
138 {
139 .altfun = GPIO_ALT_LCD_PANEL,
140 .start = 150,
141 .end = 171,
142 .cont = 0,
143 .type = GPIO_ALTF_B,
144 },
145 {
146 .altfun = GPIO_ALT_SD_CARD0,
147 .start = 18,
148 .end = 28,
149 .cont = 0,
150 .type = GPIO_ALTF_A,
151 },
152 {
153 .altfun = GPIO_ALT_MM_CARD0,
154 .start = 18,
155 .end = 32,
156 .cont = 0,
157 .type = GPIO_ALTF_A,
158 },
159 {
160 .altfun = GPIO_ALT_USB_OTG,
161 .start = 256,
162 .end = 267,
163 .cont = 0,
164 .type = GPIO_ALTF_A,
165 },
166 {
167 .altfun = GPIO_ALT_EMMC,
168 .start = 197,
169 .end = 207,
170 .cont = 0,
171 .type = GPIO_ALTF_A,
172 },
173 {
174 .altfun = GPIO_ALT_POP_EMMC,
175 .start = 128,
176 .end = 138,
177 .cont = 0,
178 .type = GPIO_ALTF_A,
179 },
180};
181
182/*
183 * Static Function declarations
184 */
185enum gpio_error gpio_setpinconfig(int pin_id, struct gpio_config *config)
186{
187 struct gpio_register *p_gpio_register =
188 addr_gpio_register[GPIO_BLOCK(pin_id)];
189 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
190 enum gpio_error error = GPIO_OK;
191 u32 temp_reg;
192
193 switch (config->mode) {
194 case GPIO_ALTF_A:
195 temp_reg = readl(&p_gpio_register->gpio_afsa);
196 temp_reg |= mask;
197 writel(temp_reg, &p_gpio_register->gpio_afsa);
198 temp_reg = readl(&p_gpio_register->gpio_afsb);
199 temp_reg &= ~mask;
200 writel(temp_reg, &p_gpio_register->gpio_afsb);
201 break;
202 case GPIO_ALTF_B:
203 temp_reg = readl(&p_gpio_register->gpio_afsa);
204 temp_reg &= ~mask;
205 writel(temp_reg, &p_gpio_register->gpio_afsa);
206 temp_reg = readl(&p_gpio_register->gpio_afsb);
207 temp_reg |= mask;
208 writel(temp_reg, &p_gpio_register->gpio_afsb);
209 break;
210 case GPIO_ALTF_C:
211 temp_reg = readl(&p_gpio_register->gpio_afsa);
212 temp_reg |= mask;
213 writel(temp_reg, &p_gpio_register->gpio_afsa);
214 temp_reg = readl(&p_gpio_register->gpio_afsb);
215 temp_reg |= mask;
216 writel(temp_reg, &p_gpio_register->gpio_afsb);
217 break;
218 case GPIO_MODE_SOFTWARE:
219 temp_reg = readl(&p_gpio_register->gpio_afsa);
220 temp_reg &= ~mask;
221 writel(temp_reg, &p_gpio_register->gpio_afsa);
222 temp_reg = readl(&p_gpio_register->gpio_afsb);
223 temp_reg &= ~mask;
224 writel(temp_reg, &p_gpio_register->gpio_afsb);
225
226 switch (config->direction) {
227 case GPIO_DIR_INPUT:
228 writel(mask, &p_gpio_register->gpio_dirc);
229 break;
230 case GPIO_DIR_OUTPUT:
231 writel(mask, &p_gpio_register->gpio_dirs);
232 break;
233 case GPIO_DIR_LEAVE_UNCHANGED:
234 break;
235 default:
236 return GPIO_INVALID_PARAMETER;
237 }
238
239 break;
240 case GPIO_MODE_LEAVE_UNCHANGED:
241 break;
242 default:
243 return GPIO_INVALID_PARAMETER;
244 }
245 return error;
246}
247
248enum gpio_error gpio_resetgpiopin(int pin_id, char *dev_name)
249{
250 struct gpio_register *p_gpio_register =
251 addr_gpio_register[GPIO_BLOCK(pin_id)];
252 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
253 enum gpio_error error = GPIO_OK;
254 u32 temp_reg;
255
256 temp_reg = readl(&p_gpio_register->gpio_afsa);
257 temp_reg &= ~mask;
258 writel(temp_reg, &p_gpio_register->gpio_afsa);
259 temp_reg = readl(&p_gpio_register->gpio_afsb);
260 temp_reg &= ~mask;
261 writel(temp_reg, &p_gpio_register->gpio_afsb);
262 writel(mask, &p_gpio_register->gpio_dirc);
263
264 return error;
265}
266
267struct gpio_config altfun_pinconfig;
268enum gpio_error gpio_altfunction(enum gpio_alt_function alt_func,
269 int which_altfunc, char *dev_name)
270{
271 int i, j, start, end;
272 enum gpio_error error = -1;
273
274 for (i = 0; i < ARRAY_SIZE(altfun_table); i++) {
275 if (altfun_table[i].altfun != alt_func)
276 continue;
277
278 start = altfun_table[i].start;
279 end = altfun_table[i].end;
280 for (j = start; j <= end; j++) {
281 if (which_altfunc == GPIO_ALTF_FIND)
282 altfun_pinconfig.mode = altfun_table[i].type;
283 else
284 altfun_pinconfig.mode = which_altfunc;
285 altfun_pinconfig.direction = GPIO_DIR_OUTPUT;
286 altfun_pinconfig.dev_name = dev_name;
287
288 if (which_altfunc != GPIO_ALTF_DISABLE)
289 error = gpio_setpinconfig(j, &altfun_pinconfig);
290 else
291 error = gpio_resetgpiopin(j, dev_name);
292 if (!error)
293 continue;
294 printf("GPIO %d configuration failure (nmdk_error:%d)",
295 j, error);
296 error = GPIO_INVALID_PARAMETER;
297 return error;
298 }
299
300 if (!altfun_table[i].cont)
301 break;
302 }
303 return error;
304}
305
306int gpio_writepin(int pin_id, enum gpio_data value, char *dev_name)
307{
308 struct gpio_register *p_gpio_register =
309 addr_gpio_register[GPIO_BLOCK(pin_id)];
310 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
311
312 switch (value) {
313 case GPIO_DATA_HIGH:
314 writel(mask, &p_gpio_register->gpio_dats);
315 break;
316 case GPIO_DATA_LOW:
317 writel(mask, &p_gpio_register->gpio_datc);
318 break;
319 default:
320 printf("Invalid value passed in %s", __FUNCTION__);
321 return GPIO_INVALID_PARAMETER;
322 }
323 return GPIO_OK;
324}
325
326int gpio_readpin(int pin_id, enum gpio_data *rv)
327{
328 struct gpio_register *p_gpio_register =
329 addr_gpio_register[GPIO_BLOCK(pin_id)];
330 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
331
332 if ((readl(&p_gpio_register->gpio_dat) & mask) != 0)
333 *rv = GPIO_DATA_HIGH;
334 else
335 *rv = GPIO_DATA_LOW;
336 return GPIO_OK;
337}
338
339int gpio_altfuncenable(enum gpio_alt_function altfunc, char *dev_name)
340{
341 return (int)gpio_altfunction(altfunc, GPIO_ALTF_FIND, dev_name);
342}
343
344int gpio_altfuncdisable(enum gpio_alt_function altfunc, char *dev_name)
345{
346 return (int)gpio_altfunction(altfunc, GPIO_ALTF_DISABLE, dev_name);
347}