Commit | Line | Data |
---|---|---|
7d30e8b3 | 1 | /* linux/arch/arm/mach-exynos4/gpiolib.c |
d2e7eca3 | 2 | * |
7d30e8b3 | 3 | * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. |
d2e7eca3 JL |
4 | * http://www.samsung.com |
5 | * | |
7d30e8b3 | 6 | * EXYNOS4 - GPIOlib support |
d2e7eca3 JL |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
12 | ||
13 | #include <linux/kernel.h> | |
14 | #include <linux/irq.h> | |
15 | #include <linux/io.h> | |
16 | #include <linux/gpio.h> | |
17 | ||
18 | #include <mach/map.h> | |
19 | ||
20 | #include <plat/gpio-core.h> | |
21 | #include <plat/gpio-cfg.h> | |
22 | #include <plat/gpio-cfg-helpers.h> | |
23 | ||
0bf8fa04 TA |
24 | int s3c_gpio_setpull_exynos4(struct s3c_gpio_chip *chip, |
25 | unsigned int off, s3c_gpio_pull_t pull) | |
26 | { | |
27 | if (pull == S3C_GPIO_PULL_UP) | |
28 | pull = 3; | |
29 | ||
30 | return s3c_gpio_setpull_updown(chip, off, pull); | |
31 | } | |
32 | ||
33 | s3c_gpio_pull_t s3c_gpio_getpull_exynos4(struct s3c_gpio_chip *chip, | |
34 | unsigned int off) | |
35 | { | |
36 | s3c_gpio_pull_t pull; | |
37 | ||
38 | pull = s3c_gpio_getpull_updown(chip, off); | |
39 | if (pull == 3) | |
40 | pull = S3C_GPIO_PULL_UP; | |
41 | ||
42 | return pull; | |
43 | } | |
44 | ||
d2e7eca3 JL |
45 | static struct s3c_gpio_cfg gpio_cfg = { |
46 | .set_config = s3c_gpio_setcfg_s3c64xx_4bit, | |
0bf8fa04 TA |
47 | .set_pull = s3c_gpio_setpull_exynos4, |
48 | .get_pull = s3c_gpio_getpull_exynos4, | |
d2e7eca3 JL |
49 | }; |
50 | ||
51 | static struct s3c_gpio_cfg gpio_cfg_noint = { | |
52 | .set_config = s3c_gpio_setcfg_s3c64xx_4bit, | |
0bf8fa04 TA |
53 | .set_pull = s3c_gpio_setpull_exynos4, |
54 | .get_pull = s3c_gpio_getpull_exynos4, | |
d2e7eca3 JL |
55 | }; |
56 | ||
57 | /* | |
58 | * Following are the gpio banks in v310. | |
59 | * | |
60 | * The 'config' member when left to NULL, is initialized to the default | |
61 | * structure gpio_cfg in the init function below. | |
62 | * | |
63 | * The 'base' member is also initialized in the init function below. | |
64 | * Note: The initialization of 'base' member of s3c_gpio_chip structure | |
65 | * uses the above macro and depends on the banks being listed in order here. | |
66 | */ | |
7d30e8b3 | 67 | static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = { |
d2e7eca3 JL |
68 | { |
69 | .chip = { | |
7d30e8b3 KK |
70 | .base = EXYNOS4_GPA0(0), |
71 | .ngpio = EXYNOS4_GPIO_A0_NR, | |
d2e7eca3 JL |
72 | .label = "GPA0", |
73 | }, | |
74 | }, { | |
75 | .chip = { | |
7d30e8b3 KK |
76 | .base = EXYNOS4_GPA1(0), |
77 | .ngpio = EXYNOS4_GPIO_A1_NR, | |
d2e7eca3 JL |
78 | .label = "GPA1", |
79 | }, | |
80 | }, { | |
81 | .chip = { | |
7d30e8b3 KK |
82 | .base = EXYNOS4_GPB(0), |
83 | .ngpio = EXYNOS4_GPIO_B_NR, | |
d2e7eca3 JL |
84 | .label = "GPB", |
85 | }, | |
86 | }, { | |
87 | .chip = { | |
7d30e8b3 KK |
88 | .base = EXYNOS4_GPC0(0), |
89 | .ngpio = EXYNOS4_GPIO_C0_NR, | |
d2e7eca3 JL |
90 | .label = "GPC0", |
91 | }, | |
92 | }, { | |
93 | .chip = { | |
7d30e8b3 KK |
94 | .base = EXYNOS4_GPC1(0), |
95 | .ngpio = EXYNOS4_GPIO_C1_NR, | |
d2e7eca3 JL |
96 | .label = "GPC1", |
97 | }, | |
98 | }, { | |
99 | .chip = { | |
7d30e8b3 KK |
100 | .base = EXYNOS4_GPD0(0), |
101 | .ngpio = EXYNOS4_GPIO_D0_NR, | |
d2e7eca3 JL |
102 | .label = "GPD0", |
103 | }, | |
104 | }, { | |
105 | .chip = { | |
7d30e8b3 KK |
106 | .base = EXYNOS4_GPD1(0), |
107 | .ngpio = EXYNOS4_GPIO_D1_NR, | |
d2e7eca3 JL |
108 | .label = "GPD1", |
109 | }, | |
110 | }, { | |
111 | .chip = { | |
7d30e8b3 KK |
112 | .base = EXYNOS4_GPE0(0), |
113 | .ngpio = EXYNOS4_GPIO_E0_NR, | |
d2e7eca3 JL |
114 | .label = "GPE0", |
115 | }, | |
116 | }, { | |
117 | .chip = { | |
7d30e8b3 KK |
118 | .base = EXYNOS4_GPE1(0), |
119 | .ngpio = EXYNOS4_GPIO_E1_NR, | |
d2e7eca3 JL |
120 | .label = "GPE1", |
121 | }, | |
122 | }, { | |
123 | .chip = { | |
7d30e8b3 KK |
124 | .base = EXYNOS4_GPE2(0), |
125 | .ngpio = EXYNOS4_GPIO_E2_NR, | |
d2e7eca3 JL |
126 | .label = "GPE2", |
127 | }, | |
128 | }, { | |
129 | .chip = { | |
7d30e8b3 KK |
130 | .base = EXYNOS4_GPE3(0), |
131 | .ngpio = EXYNOS4_GPIO_E3_NR, | |
d2e7eca3 JL |
132 | .label = "GPE3", |
133 | }, | |
134 | }, { | |
135 | .chip = { | |
7d30e8b3 KK |
136 | .base = EXYNOS4_GPE4(0), |
137 | .ngpio = EXYNOS4_GPIO_E4_NR, | |
d2e7eca3 JL |
138 | .label = "GPE4", |
139 | }, | |
140 | }, { | |
141 | .chip = { | |
7d30e8b3 KK |
142 | .base = EXYNOS4_GPF0(0), |
143 | .ngpio = EXYNOS4_GPIO_F0_NR, | |
d2e7eca3 JL |
144 | .label = "GPF0", |
145 | }, | |
146 | }, { | |
147 | .chip = { | |
7d30e8b3 KK |
148 | .base = EXYNOS4_GPF1(0), |
149 | .ngpio = EXYNOS4_GPIO_F1_NR, | |
d2e7eca3 JL |
150 | .label = "GPF1", |
151 | }, | |
152 | }, { | |
153 | .chip = { | |
7d30e8b3 KK |
154 | .base = EXYNOS4_GPF2(0), |
155 | .ngpio = EXYNOS4_GPIO_F2_NR, | |
d2e7eca3 JL |
156 | .label = "GPF2", |
157 | }, | |
158 | }, { | |
159 | .chip = { | |
7d30e8b3 KK |
160 | .base = EXYNOS4_GPF3(0), |
161 | .ngpio = EXYNOS4_GPIO_F3_NR, | |
d2e7eca3 JL |
162 | .label = "GPF3", |
163 | }, | |
164 | }, | |
165 | }; | |
166 | ||
7d30e8b3 | 167 | static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = { |
d2e7eca3 JL |
168 | { |
169 | .chip = { | |
7d30e8b3 KK |
170 | .base = EXYNOS4_GPJ0(0), |
171 | .ngpio = EXYNOS4_GPIO_J0_NR, | |
d2e7eca3 JL |
172 | .label = "GPJ0", |
173 | }, | |
174 | }, { | |
175 | .chip = { | |
7d30e8b3 KK |
176 | .base = EXYNOS4_GPJ1(0), |
177 | .ngpio = EXYNOS4_GPIO_J1_NR, | |
d2e7eca3 JL |
178 | .label = "GPJ1", |
179 | }, | |
180 | }, { | |
181 | .chip = { | |
7d30e8b3 KK |
182 | .base = EXYNOS4_GPK0(0), |
183 | .ngpio = EXYNOS4_GPIO_K0_NR, | |
d2e7eca3 JL |
184 | .label = "GPK0", |
185 | }, | |
186 | }, { | |
187 | .chip = { | |
7d30e8b3 KK |
188 | .base = EXYNOS4_GPK1(0), |
189 | .ngpio = EXYNOS4_GPIO_K1_NR, | |
d2e7eca3 JL |
190 | .label = "GPK1", |
191 | }, | |
192 | }, { | |
193 | .chip = { | |
7d30e8b3 KK |
194 | .base = EXYNOS4_GPK2(0), |
195 | .ngpio = EXYNOS4_GPIO_K2_NR, | |
d2e7eca3 JL |
196 | .label = "GPK2", |
197 | }, | |
198 | }, { | |
199 | .chip = { | |
7d30e8b3 KK |
200 | .base = EXYNOS4_GPK3(0), |
201 | .ngpio = EXYNOS4_GPIO_K3_NR, | |
d2e7eca3 JL |
202 | .label = "GPK3", |
203 | }, | |
204 | }, { | |
205 | .chip = { | |
7d30e8b3 KK |
206 | .base = EXYNOS4_GPL0(0), |
207 | .ngpio = EXYNOS4_GPIO_L0_NR, | |
d2e7eca3 JL |
208 | .label = "GPL0", |
209 | }, | |
210 | }, { | |
211 | .chip = { | |
7d30e8b3 KK |
212 | .base = EXYNOS4_GPL1(0), |
213 | .ngpio = EXYNOS4_GPIO_L1_NR, | |
d2e7eca3 JL |
214 | .label = "GPL1", |
215 | }, | |
216 | }, { | |
217 | .chip = { | |
7d30e8b3 KK |
218 | .base = EXYNOS4_GPL2(0), |
219 | .ngpio = EXYNOS4_GPIO_L2_NR, | |
d2e7eca3 JL |
220 | .label = "GPL2", |
221 | }, | |
47a9c0ee MS |
222 | }, { |
223 | .config = &gpio_cfg_noint, | |
224 | .chip = { | |
225 | .base = EXYNOS4_GPY0(0), | |
226 | .ngpio = EXYNOS4_GPIO_Y0_NR, | |
227 | .label = "GPY0", | |
228 | }, | |
229 | }, { | |
230 | .config = &gpio_cfg_noint, | |
231 | .chip = { | |
232 | .base = EXYNOS4_GPY1(0), | |
233 | .ngpio = EXYNOS4_GPIO_Y1_NR, | |
234 | .label = "GPY1", | |
235 | }, | |
236 | }, { | |
237 | .config = &gpio_cfg_noint, | |
238 | .chip = { | |
239 | .base = EXYNOS4_GPY2(0), | |
240 | .ngpio = EXYNOS4_GPIO_Y2_NR, | |
241 | .label = "GPY2", | |
242 | }, | |
243 | }, { | |
244 | .config = &gpio_cfg_noint, | |
245 | .chip = { | |
246 | .base = EXYNOS4_GPY3(0), | |
247 | .ngpio = EXYNOS4_GPIO_Y3_NR, | |
248 | .label = "GPY3", | |
249 | }, | |
250 | }, { | |
251 | .config = &gpio_cfg_noint, | |
252 | .chip = { | |
253 | .base = EXYNOS4_GPY4(0), | |
254 | .ngpio = EXYNOS4_GPIO_Y4_NR, | |
255 | .label = "GPY4", | |
256 | }, | |
257 | }, { | |
258 | .config = &gpio_cfg_noint, | |
259 | .chip = { | |
260 | .base = EXYNOS4_GPY5(0), | |
261 | .ngpio = EXYNOS4_GPIO_Y5_NR, | |
262 | .label = "GPY5", | |
263 | }, | |
264 | }, { | |
265 | .config = &gpio_cfg_noint, | |
266 | .chip = { | |
267 | .base = EXYNOS4_GPY6(0), | |
268 | .ngpio = EXYNOS4_GPIO_Y6_NR, | |
269 | .label = "GPY6", | |
270 | }, | |
d2e7eca3 JL |
271 | }, { |
272 | .base = (S5P_VA_GPIO2 + 0xC00), | |
273 | .config = &gpio_cfg_noint, | |
274 | .irq_base = IRQ_EINT(0), | |
275 | .chip = { | |
7d30e8b3 KK |
276 | .base = EXYNOS4_GPX0(0), |
277 | .ngpio = EXYNOS4_GPIO_X0_NR, | |
d2e7eca3 JL |
278 | .label = "GPX0", |
279 | .to_irq = samsung_gpiolib_to_irq, | |
280 | }, | |
281 | }, { | |
282 | .base = (S5P_VA_GPIO2 + 0xC20), | |
283 | .config = &gpio_cfg_noint, | |
284 | .irq_base = IRQ_EINT(8), | |
285 | .chip = { | |
7d30e8b3 KK |
286 | .base = EXYNOS4_GPX1(0), |
287 | .ngpio = EXYNOS4_GPIO_X1_NR, | |
d2e7eca3 JL |
288 | .label = "GPX1", |
289 | .to_irq = samsung_gpiolib_to_irq, | |
290 | }, | |
291 | }, { | |
292 | .base = (S5P_VA_GPIO2 + 0xC40), | |
293 | .config = &gpio_cfg_noint, | |
294 | .irq_base = IRQ_EINT(16), | |
295 | .chip = { | |
7d30e8b3 KK |
296 | .base = EXYNOS4_GPX2(0), |
297 | .ngpio = EXYNOS4_GPIO_X2_NR, | |
d2e7eca3 JL |
298 | .label = "GPX2", |
299 | .to_irq = samsung_gpiolib_to_irq, | |
300 | }, | |
301 | }, { | |
302 | .base = (S5P_VA_GPIO2 + 0xC60), | |
303 | .config = &gpio_cfg_noint, | |
304 | .irq_base = IRQ_EINT(24), | |
305 | .chip = { | |
7d30e8b3 KK |
306 | .base = EXYNOS4_GPX3(0), |
307 | .ngpio = EXYNOS4_GPIO_X3_NR, | |
d2e7eca3 JL |
308 | .label = "GPX3", |
309 | .to_irq = samsung_gpiolib_to_irq, | |
310 | }, | |
311 | }, | |
312 | }; | |
313 | ||
7d30e8b3 | 314 | static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = { |
d2e7eca3 JL |
315 | { |
316 | .chip = { | |
7d30e8b3 KK |
317 | .base = EXYNOS4_GPZ(0), |
318 | .ngpio = EXYNOS4_GPIO_Z_NR, | |
d2e7eca3 JL |
319 | .label = "GPZ", |
320 | }, | |
321 | }, | |
322 | }; | |
323 | ||
7d30e8b3 | 324 | static __init int exynos4_gpiolib_init(void) |
d2e7eca3 JL |
325 | { |
326 | struct s3c_gpio_chip *chip; | |
327 | int i; | |
721bbd4a | 328 | int group = 0; |
d2e7eca3 JL |
329 | int nr_chips; |
330 | ||
331 | /* GPIO part 1 */ | |
332 | ||
7d30e8b3 KK |
333 | chip = exynos4_gpio_part1_4bit; |
334 | nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit); | |
d2e7eca3 JL |
335 | |
336 | for (i = 0; i < nr_chips; i++, chip++) { | |
721bbd4a | 337 | if (chip->config == NULL) { |
d2e7eca3 | 338 | chip->config = &gpio_cfg; |
721bbd4a MS |
339 | /* Assign the GPIO interrupt group */ |
340 | chip->group = group++; | |
341 | } | |
d2e7eca3 JL |
342 | if (chip->base == NULL) |
343 | chip->base = S5P_VA_GPIO1 + (i) * 0x20; | |
344 | } | |
345 | ||
7d30e8b3 | 346 | samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips); |
d2e7eca3 JL |
347 | |
348 | /* GPIO part 2 */ | |
349 | ||
7d30e8b3 KK |
350 | chip = exynos4_gpio_part2_4bit; |
351 | nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit); | |
d2e7eca3 JL |
352 | |
353 | for (i = 0; i < nr_chips; i++, chip++) { | |
721bbd4a | 354 | if (chip->config == NULL) { |
d2e7eca3 | 355 | chip->config = &gpio_cfg; |
721bbd4a MS |
356 | /* Assign the GPIO interrupt group */ |
357 | chip->group = group++; | |
358 | } | |
d2e7eca3 JL |
359 | if (chip->base == NULL) |
360 | chip->base = S5P_VA_GPIO2 + (i) * 0x20; | |
361 | } | |
362 | ||
7d30e8b3 | 363 | samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips); |
d2e7eca3 JL |
364 | |
365 | /* GPIO part 3 */ | |
366 | ||
7d30e8b3 KK |
367 | chip = exynos4_gpio_part3_4bit; |
368 | nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit); | |
d2e7eca3 JL |
369 | |
370 | for (i = 0; i < nr_chips; i++, chip++) { | |
721bbd4a | 371 | if (chip->config == NULL) { |
d2e7eca3 | 372 | chip->config = &gpio_cfg; |
721bbd4a MS |
373 | /* Assign the GPIO interrupt group */ |
374 | chip->group = group++; | |
375 | } | |
d2e7eca3 JL |
376 | if (chip->base == NULL) |
377 | chip->base = S5P_VA_GPIO3 + (i) * 0x20; | |
378 | } | |
379 | ||
7d30e8b3 | 380 | samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips); |
721bbd4a MS |
381 | s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS); |
382 | s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS); | |
d2e7eca3 JL |
383 | |
384 | return 0; | |
385 | } | |
7d30e8b3 | 386 | core_initcall(exynos4_gpiolib_init); |