]>
Commit | Line | Data |
---|---|---|
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 | ||
26 | static 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 | ||
38 | struct 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 | */ | |
185 | enum 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 | ||
248 | enum 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 | ||
267 | struct gpio_config altfun_pinconfig; | |
268 | enum 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 | ||
306 | int 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 | ||
326 | int 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 | ||
339 | int gpio_altfuncenable(enum gpio_alt_function altfunc, char *dev_name) | |
340 | { | |
341 | return (int)gpio_altfunction(altfunc, GPIO_ALTF_FIND, dev_name); | |
342 | } | |
343 | ||
344 | int gpio_altfuncdisable(enum gpio_alt_function altfunc, char *dev_name) | |
345 | { | |
346 | return (int)gpio_altfunction(altfunc, GPIO_ALTF_DISABLE, dev_name); | |
347 | } |