blob: 2ddc7af48b88079e7dbb90d16cdd67f70f39b07b [file] [log] [blame]
John Rigby25a33622011-04-19 10:42:42 +00001/*
2 * Copyright (C) ST-Ericsson SA 2009
3 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
John Rigby25a33622011-04-19 10:42:42 +00005 */
6
7#include <common.h>
8#include <asm/arch/gpio.h>
9
10static struct gpio_register *addr_gpio_register[] = {
11 (void *)U8500_GPIO_0_BASE,
12 (void *)U8500_GPIO_1_BASE,
13 (void *)U8500_GPIO_2_BASE,
14 (void *)U8500_GPIO_3_BASE,
15 (void *)U8500_GPIO_4_BASE,
16 (void *)U8500_GPIO_5_BASE,
17 (void *)U8500_GPIO_6_BASE,
18 (void *)U8500_GPIO_7_BASE,
19 (void *)U8500_GPIO_8_BASE,
20};
21
22struct gpio_altfun_data altfun_table[] = {
23 {
24 .altfun = GPIO_ALT_I2C_0,
25 .start = 147,
26 .end = 148,
27 .cont = 0,
28 .type = GPIO_ALTF_A,
29 },
30 {
31 .altfun = GPIO_ALT_I2C_1,
32 .start = 16,
33 .end = 17,
34 .cont = 0,
35 .type = GPIO_ALTF_B,
36 },
37 {
38 .altfun = GPIO_ALT_I2C_2,
39 .start = 10,
40 .end = 11,
41 .cont = 0,
42 .type = GPIO_ALTF_B,
43 },
44 {
45 .altfun = GPIO_ALT_I2C_3,
46 .start = 229,
47 .end = 230,
48 .cont = 0,
49 .type = GPIO_ALTF_C,
50 },
51 {
52 .altfun = GPIO_ALT_UART_0_MODEM,
53 .start = 0,
54 .end = 3,
55 .cont = 1,
56 .type = GPIO_ALTF_A,
57 },
58 {
59 .altfun = GPIO_ALT_UART_0_MODEM,
60 .start = 33,
61 .end = 36,
62 .cont = 0,
63 .type = GPIO_ALTF_C,
64 },
65 {
66 .altfun = GPIO_ALT_UART_1,
67 .start = 4,
68 .end = 7,
69 .cont = 0,
70 .type =
71 GPIO_ALTF_A,
72 },
73 {
74 .altfun = GPIO_ALT_UART_2,
75 .start = 18,
76 .end = 19,
77 .cont = 1,
78 .type = GPIO_ALTF_B,
79 },
80 {
81 .altfun = GPIO_ALT_UART_2,
82 .start = 29,
83 .end = 32,
84 .cont = 0,
85 .type = GPIO_ALTF_C,
86 },
87 {
88 .altfun = GPIO_ALT_MSP_0,
89 .start = 12,
90 .end = 17,
91 .cont = 1,
92 .type = GPIO_ALTF_A,
93 },
94 {
95 .altfun = GPIO_ALT_MSP_0,
96 .start = 21,
97 .end = 21,
98 .cont = 0,
99 .type = GPIO_ALTF_B,
100 },
101 {
102 .altfun = GPIO_ALT_MSP_1,
103 .start = 33,
104 .end = 36,
105 .cont = 0,
106 .type = GPIO_ALTF_A,
107 },
108 {
109 .altfun = GPIO_ALT_MSP_2,
110 .start = 192,
111 .end = 196,
112 .cont = 0,
113 .type = GPIO_ALTF_A,
114 },
115 {
116 .altfun = GPIO_ALT_LCD_PANEL,
117 .start = 64,
118 .end = 93,
119 .cont = 1,
120 .type = GPIO_ALTF_A,
121 },
122 {
123 .altfun = GPIO_ALT_LCD_PANEL,
124 .start = 150,
125 .end = 171,
126 .cont = 0,
127 .type = GPIO_ALTF_B,
128 },
129 {
130 .altfun = GPIO_ALT_SD_CARD0,
131 .start = 18,
132 .end = 28,
133 .cont = 0,
134 .type = GPIO_ALTF_A,
135 },
136 {
137 .altfun = GPIO_ALT_MM_CARD0,
138 .start = 18,
139 .end = 32,
140 .cont = 0,
141 .type = GPIO_ALTF_A,
142 },
143 {
144 .altfun = GPIO_ALT_USB_OTG,
145 .start = 256,
146 .end = 267,
147 .cont = 0,
148 .type = GPIO_ALTF_A,
149 },
150 {
151 .altfun = GPIO_ALT_EMMC,
152 .start = 197,
153 .end = 207,
154 .cont = 0,
155 .type = GPIO_ALTF_A,
156 },
157 {
158 .altfun = GPIO_ALT_POP_EMMC,
159 .start = 128,
160 .end = 138,
161 .cont = 0,
162 .type = GPIO_ALTF_A,
163 },
164};
165
166/*
167 * Static Function declarations
168 */
169enum gpio_error gpio_setpinconfig(int pin_id, struct gpio_config *config)
170{
171 struct gpio_register *p_gpio_register =
172 addr_gpio_register[GPIO_BLOCK(pin_id)];
173 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
174 enum gpio_error error = GPIO_OK;
175 u32 temp_reg;
176
177 switch (config->mode) {
178 case GPIO_ALTF_A:
179 temp_reg = readl(&p_gpio_register->gpio_afsa);
180 temp_reg |= mask;
181 writel(temp_reg, &p_gpio_register->gpio_afsa);
182 temp_reg = readl(&p_gpio_register->gpio_afsb);
183 temp_reg &= ~mask;
184 writel(temp_reg, &p_gpio_register->gpio_afsb);
185 break;
186 case GPIO_ALTF_B:
187 temp_reg = readl(&p_gpio_register->gpio_afsa);
188 temp_reg &= ~mask;
189 writel(temp_reg, &p_gpio_register->gpio_afsa);
190 temp_reg = readl(&p_gpio_register->gpio_afsb);
191 temp_reg |= mask;
192 writel(temp_reg, &p_gpio_register->gpio_afsb);
193 break;
194 case GPIO_ALTF_C:
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_MODE_SOFTWARE:
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
210 switch (config->direction) {
211 case GPIO_DIR_INPUT:
212 writel(mask, &p_gpio_register->gpio_dirc);
213 break;
214 case GPIO_DIR_OUTPUT:
215 writel(mask, &p_gpio_register->gpio_dirs);
216 break;
217 case GPIO_DIR_LEAVE_UNCHANGED:
218 break;
219 default:
220 return GPIO_INVALID_PARAMETER;
221 }
222
223 break;
224 case GPIO_MODE_LEAVE_UNCHANGED:
225 break;
226 default:
227 return GPIO_INVALID_PARAMETER;
228 }
229 return error;
230}
231
232enum gpio_error gpio_resetgpiopin(int pin_id, char *dev_name)
233{
234 struct gpio_register *p_gpio_register =
235 addr_gpio_register[GPIO_BLOCK(pin_id)];
236 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
237 enum gpio_error error = GPIO_OK;
238 u32 temp_reg;
239
240 temp_reg = readl(&p_gpio_register->gpio_afsa);
241 temp_reg &= ~mask;
242 writel(temp_reg, &p_gpio_register->gpio_afsa);
243 temp_reg = readl(&p_gpio_register->gpio_afsb);
244 temp_reg &= ~mask;
245 writel(temp_reg, &p_gpio_register->gpio_afsb);
246 writel(mask, &p_gpio_register->gpio_dirc);
247
248 return error;
249}
250
251struct gpio_config altfun_pinconfig;
252enum gpio_error gpio_altfunction(enum gpio_alt_function alt_func,
253 int which_altfunc, char *dev_name)
254{
255 int i, j, start, end;
256 enum gpio_error error = -1;
257
258 for (i = 0; i < ARRAY_SIZE(altfun_table); i++) {
259 if (altfun_table[i].altfun != alt_func)
260 continue;
261
262 start = altfun_table[i].start;
263 end = altfun_table[i].end;
264 for (j = start; j <= end; j++) {
265 if (which_altfunc == GPIO_ALTF_FIND)
266 altfun_pinconfig.mode = altfun_table[i].type;
267 else
268 altfun_pinconfig.mode = which_altfunc;
269 altfun_pinconfig.direction = GPIO_DIR_OUTPUT;
270 altfun_pinconfig.dev_name = dev_name;
271
272 if (which_altfunc != GPIO_ALTF_DISABLE)
273 error = gpio_setpinconfig(j, &altfun_pinconfig);
274 else
275 error = gpio_resetgpiopin(j, dev_name);
276 if (!error)
277 continue;
278 printf("GPIO %d configuration failure (nmdk_error:%d)",
279 j, error);
280 error = GPIO_INVALID_PARAMETER;
281 return error;
282 }
283
284 if (!altfun_table[i].cont)
285 break;
286 }
287 return error;
288}
289
290int gpio_writepin(int pin_id, enum gpio_data value, char *dev_name)
291{
292 struct gpio_register *p_gpio_register =
293 addr_gpio_register[GPIO_BLOCK(pin_id)];
294 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
295
296 switch (value) {
297 case GPIO_DATA_HIGH:
298 writel(mask, &p_gpio_register->gpio_dats);
299 break;
300 case GPIO_DATA_LOW:
301 writel(mask, &p_gpio_register->gpio_datc);
302 break;
303 default:
304 printf("Invalid value passed in %s", __FUNCTION__);
305 return GPIO_INVALID_PARAMETER;
306 }
307 return GPIO_OK;
308}
309
310int gpio_readpin(int pin_id, enum gpio_data *rv)
311{
312 struct gpio_register *p_gpio_register =
313 addr_gpio_register[GPIO_BLOCK(pin_id)];
314 u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
315
316 if ((readl(&p_gpio_register->gpio_dat) & mask) != 0)
317 *rv = GPIO_DATA_HIGH;
318 else
319 *rv = GPIO_DATA_LOW;
320 return GPIO_OK;
321}
322
323int gpio_altfuncenable(enum gpio_alt_function altfunc, char *dev_name)
324{
325 return (int)gpio_altfunction(altfunc, GPIO_ALTF_FIND, dev_name);
326}
327
328int gpio_altfuncdisable(enum gpio_alt_function altfunc, char *dev_name)
329{
330 return (int)gpio_altfunction(altfunc, GPIO_ALTF_DISABLE, dev_name);
331}