]>
Commit | Line | Data |
---|---|---|
afbf8899 JR |
1 | /* |
2 | * Copyright (C) ST-Ericsson SA 2009 | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
afbf8899 JR |
5 | */ |
6 | ||
7 | #include <common.h> | |
8 | #include <asm/arch/gpio.h> | |
9 | ||
10 | static 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 | ||
22 | struct 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 | */ | |
169 | enum 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 | ||
232 | enum 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 | ||
251 | struct gpio_config altfun_pinconfig; | |
252 | enum 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 | ||
290 | int 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 | ||
310 | int 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 | ||
323 | int gpio_altfuncenable(enum gpio_alt_function altfunc, char *dev_name) | |
324 | { | |
325 | return (int)gpio_altfunction(altfunc, GPIO_ALTF_FIND, dev_name); | |
326 | } | |
327 | ||
328 | int gpio_altfuncdisable(enum gpio_alt_function altfunc, char *dev_name) | |
329 | { | |
330 | return (int)gpio_altfunction(altfunc, GPIO_ALTF_DISABLE, dev_name); | |
331 | } |