]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - arch/arm/mach-s5p64x0/gpiolib.c
Merge branch 'depends/rmk/for-linus' into samsung/dt
[mirror_ubuntu-zesty-kernel.git] / arch / arm / mach-s5p64x0 / gpiolib.c
CommitLineData
5b1bab2e 1/* linux/arch/arm/mach-s5p64x0/gpiolib.c
42d828d4 2 *
5dd33d89
KK
3 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
42d828d4 5 *
5dd33d89 6 * S5P64X0 - GPIOlib support
42d828d4
KK
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.
5dd33d89 11*/
42d828d4
KK
12
13#include <linux/kernel.h>
14#include <linux/irq.h>
15#include <linux/io.h>
1c739c7f
KK
16#include <linux/gpio.h>
17
42d828d4 18#include <mach/map.h>
42d828d4 19#include <mach/regs-gpio.h>
f50266d3 20#include <mach/regs-clock.h>
1c739c7f 21
a3d93584 22#include <plat/cpu.h>
42d828d4
KK
23#include <plat/gpio-core.h>
24#include <plat/gpio-cfg.h>
25#include <plat/gpio-cfg-helpers.h>
26
5dd33d89
KK
27/*
28 * S5P6440 GPIO bank summary:
29 *
30 * Bank GPIOs Style SlpCon ExtInt Group
31 * A 6 4Bit Yes 1
32 * B 7 4Bit Yes 1
33 * C 8 4Bit Yes 2
34 * F 2 2Bit Yes 4 [1]
35 * G 7 4Bit Yes 5
36 * H 10 4Bit[2] Yes 6
37 * I 16 2Bit Yes None
38 * J 12 2Bit Yes None
39 * N 16 2Bit No IRQ_EINT
40 * P 8 2Bit Yes 8
41 * R 15 4Bit[2] Yes 8
42 *
f50266d3
KK
43 * S5P6450 GPIO bank summary:
44 *
45 * Bank GPIOs Style SlpCon ExtInt Group
46 * A 6 4Bit Yes 1
47 * B 7 4Bit Yes 1
48 * C 8 4Bit Yes 2
49 * D 8 4Bit Yes None
50 * F 2 2Bit Yes None
51 * G 14 4Bit[2] Yes 5
52 * H 10 4Bit[2] Yes 6
53 * I 16 2Bit Yes None
54 * J 12 2Bit Yes None
55 * K 5 4Bit Yes None
56 * N 16 2Bit No IRQ_EINT
57 * P 11 2Bit Yes 8
58 * Q 14 2Bit Yes None
59 * R 15 4Bit[2] Yes None
60 * S 8 2Bit Yes None
61 *
5dd33d89
KK
62 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
63 * [2] BANK has two control registers, GPxCON0 and GPxCON1
64 */
42d828d4 65
5dd33d89 66static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
42d828d4
KK
67 unsigned int offset)
68{
69 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
70 void __iomem *base = ourchip->base;
71 void __iomem *regcon = base;
72 unsigned long con;
6a399547 73 unsigned long flags;
42d828d4
KK
74
75 switch (offset) {
76 case 6:
77 offset += 1;
78 case 0:
79 case 1:
80 case 2:
81 case 3:
82 case 4:
83 case 5:
84 regcon -= 4;
85 break;
86 default:
87 offset -= 7;
88 break;
89 }
90
6a399547
BD
91 s3c_gpio_lock(ourchip, flags);
92
42d828d4
KK
93 con = __raw_readl(regcon);
94 con &= ~(0xf << con_4bit_shift(offset));
95 __raw_writel(con, regcon);
96
6a399547
BD
97 s3c_gpio_unlock(ourchip, flags);
98
42d828d4
KK
99 return 0;
100}
101
5dd33d89 102static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
42d828d4
KK
103 unsigned int offset, int value)
104{
105 struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
106 void __iomem *base = ourchip->base;
107 void __iomem *regcon = base;
108 unsigned long con;
109 unsigned long dat;
6a399547 110 unsigned long flags;
42d828d4
KK
111 unsigned con_offset = offset;
112
113 switch (con_offset) {
114 case 6:
115 con_offset += 1;
116 case 0:
117 case 1:
118 case 2:
119 case 3:
120 case 4:
121 case 5:
122 regcon -= 4;
123 break;
124 default:
125 con_offset -= 7;
126 break;
127 }
128
6a399547
BD
129 s3c_gpio_lock(ourchip, flags);
130
42d828d4
KK
131 con = __raw_readl(regcon);
132 con &= ~(0xf << con_4bit_shift(con_offset));
133 con |= 0x1 << con_4bit_shift(con_offset);
134
135 dat = __raw_readl(base + GPIODAT_OFF);
136 if (value)
137 dat |= 1 << offset;
138 else
139 dat &= ~(1 << offset);
140
141 __raw_writel(con, regcon);
142 __raw_writel(dat, base + GPIODAT_OFF);
143
6a399547
BD
144 s3c_gpio_unlock(ourchip, flags);
145
42d828d4
KK
146 return 0;
147}
148
5dd33d89 149int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
42d828d4
KK
150 unsigned int off, unsigned int cfg)
151{
152 void __iomem *reg = chip->base;
153 unsigned int shift;
154 u32 con;
155
156 switch (off) {
157 case 0:
158 case 1:
159 case 2:
160 case 3:
161 case 4:
162 case 5:
163 shift = (off & 7) * 4;
164 reg -= 4;
165 break;
166 case 6:
167 shift = ((off + 1) & 7) * 4;
168 reg -= 4;
169 default:
170 shift = ((off + 1) & 7) * 4;
171 break;
172 }
173
174 if (s3c_gpio_is_cfg_special(cfg)) {
175 cfg &= 0xf;
176 cfg <<= shift;
177 }
178
179 con = __raw_readl(reg);
180 con &= ~(0xf << shift);
181 con |= cfg;
182 __raw_writel(con, reg);
183
184 return 0;
185}
186
5dd33d89 187static struct s3c_gpio_cfg s5p64x0_gpio_cfgs[] = {
42d828d4
KK
188 {
189 .cfg_eint = 0,
190 }, {
191 .cfg_eint = 7,
192 }, {
193 .cfg_eint = 3,
5dd33d89 194 .set_config = s5p64x0_gpio_setcfg_4bit_rbank,
42d828d4
KK
195 }, {
196 .cfg_eint = 0,
197 .set_config = s3c_gpio_setcfg_s3c24xx,
97a33999 198 .get_config = s3c_gpio_getcfg_s3c24xx,
42d828d4
KK
199 }, {
200 .cfg_eint = 2,
201 .set_config = s3c_gpio_setcfg_s3c24xx,
97a33999 202 .get_config = s3c_gpio_getcfg_s3c24xx,
42d828d4
KK
203 }, {
204 .cfg_eint = 3,
205 .set_config = s3c_gpio_setcfg_s3c24xx,
97a33999 206 .get_config = s3c_gpio_getcfg_s3c24xx,
42d828d4
KK
207 },
208};
209
210static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
211 {
f50266d3 212 .base = S5P64X0_GPA_BASE,
5dd33d89 213 .config = &s5p64x0_gpio_cfgs[1],
42d828d4
KK
214 .chip = {
215 .base = S5P6440_GPA(0),
216 .ngpio = S5P6440_GPIO_A_NR,
217 .label = "GPA",
218 },
219 }, {
f50266d3 220 .base = S5P64X0_GPB_BASE,
5dd33d89 221 .config = &s5p64x0_gpio_cfgs[1],
42d828d4
KK
222 .chip = {
223 .base = S5P6440_GPB(0),
224 .ngpio = S5P6440_GPIO_B_NR,
225 .label = "GPB",
226 },
227 }, {
f50266d3 228 .base = S5P64X0_GPC_BASE,
5dd33d89 229 .config = &s5p64x0_gpio_cfgs[1],
42d828d4
KK
230 .chip = {
231 .base = S5P6440_GPC(0),
232 .ngpio = S5P6440_GPIO_C_NR,
233 .label = "GPC",
234 },
235 }, {
f50266d3 236 .base = S5P64X0_GPG_BASE,
5dd33d89 237 .config = &s5p64x0_gpio_cfgs[1],
42d828d4
KK
238 .chip = {
239 .base = S5P6440_GPG(0),
240 .ngpio = S5P6440_GPIO_G_NR,
241 .label = "GPG",
242 },
243 },
244};
245
246static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
247 {
f50266d3 248 .base = S5P64X0_GPH_BASE + 0x4,
5dd33d89 249 .config = &s5p64x0_gpio_cfgs[1],
42d828d4
KK
250 .chip = {
251 .base = S5P6440_GPH(0),
252 .ngpio = S5P6440_GPIO_H_NR,
253 .label = "GPH",
254 },
255 },
256};
257
5dd33d89 258static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2[] = {
42d828d4 259 {
f50266d3 260 .base = S5P64X0_GPR_BASE + 0x4,
5dd33d89 261 .config = &s5p64x0_gpio_cfgs[2],
42d828d4
KK
262 .chip = {
263 .base = S5P6440_GPR(0),
264 .ngpio = S5P6440_GPIO_R_NR,
265 .label = "GPR",
266 },
267 },
268};
269
270static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
271 {
f50266d3 272 .base = S5P64X0_GPF_BASE,
5dd33d89 273 .config = &s5p64x0_gpio_cfgs[5],
42d828d4
KK
274 .chip = {
275 .base = S5P6440_GPF(0),
276 .ngpio = S5P6440_GPIO_F_NR,
277 .label = "GPF",
278 },
279 }, {
f50266d3 280 .base = S5P64X0_GPI_BASE,
5dd33d89 281 .config = &s5p64x0_gpio_cfgs[3],
42d828d4
KK
282 .chip = {
283 .base = S5P6440_GPI(0),
284 .ngpio = S5P6440_GPIO_I_NR,
285 .label = "GPI",
286 },
287 }, {
f50266d3 288 .base = S5P64X0_GPJ_BASE,
5dd33d89 289 .config = &s5p64x0_gpio_cfgs[3],
42d828d4
KK
290 .chip = {
291 .base = S5P6440_GPJ(0),
292 .ngpio = S5P6440_GPIO_J_NR,
293 .label = "GPJ",
294 },
295 }, {
f50266d3 296 .base = S5P64X0_GPN_BASE,
5dd33d89 297 .config = &s5p64x0_gpio_cfgs[4],
42d828d4
KK
298 .chip = {
299 .base = S5P6440_GPN(0),
300 .ngpio = S5P6440_GPIO_N_NR,
301 .label = "GPN",
302 },
303 }, {
f50266d3 304 .base = S5P64X0_GPP_BASE,
5dd33d89 305 .config = &s5p64x0_gpio_cfgs[5],
42d828d4
KK
306 .chip = {
307 .base = S5P6440_GPP(0),
308 .ngpio = S5P6440_GPIO_P_NR,
309 .label = "GPP",
310 },
311 },
312};
313
f50266d3
KK
314static struct s3c_gpio_chip s5p6450_gpio_4bit[] = {
315 {
316 .base = S5P64X0_GPA_BASE,
317 .config = &s5p64x0_gpio_cfgs[1],
318 .chip = {
319 .base = S5P6450_GPA(0),
320 .ngpio = S5P6450_GPIO_A_NR,
321 .label = "GPA",
322 },
323 }, {
324 .base = S5P64X0_GPB_BASE,
325 .config = &s5p64x0_gpio_cfgs[1],
326 .chip = {
327 .base = S5P6450_GPB(0),
328 .ngpio = S5P6450_GPIO_B_NR,
329 .label = "GPB",
330 },
331 }, {
332 .base = S5P64X0_GPC_BASE,
333 .config = &s5p64x0_gpio_cfgs[1],
334 .chip = {
335 .base = S5P6450_GPC(0),
336 .ngpio = S5P6450_GPIO_C_NR,
337 .label = "GPC",
338 },
339 }, {
340 .base = S5P6450_GPD_BASE,
341 .config = &s5p64x0_gpio_cfgs[1],
342 .chip = {
343 .base = S5P6450_GPD(0),
344 .ngpio = S5P6450_GPIO_D_NR,
345 .label = "GPD",
346 },
347 }, {
348 .base = S5P6450_GPK_BASE,
349 .config = &s5p64x0_gpio_cfgs[1],
350 .chip = {
351 .base = S5P6450_GPK(0),
352 .ngpio = S5P6450_GPIO_K_NR,
353 .label = "GPK",
354 },
355 },
356};
357
358static struct s3c_gpio_chip s5p6450_gpio_4bit2[] = {
359 {
360 .base = S5P64X0_GPG_BASE + 0x4,
361 .config = &s5p64x0_gpio_cfgs[1],
362 .chip = {
363 .base = S5P6450_GPG(0),
364 .ngpio = S5P6450_GPIO_G_NR,
365 .label = "GPG",
366 },
367 }, {
368 .base = S5P64X0_GPH_BASE + 0x4,
369 .config = &s5p64x0_gpio_cfgs[1],
370 .chip = {
371 .base = S5P6450_GPH(0),
372 .ngpio = S5P6450_GPIO_H_NR,
373 .label = "GPH",
374 },
375 },
376};
377
378static struct s3c_gpio_chip s5p6450_gpio_rbank_4bit2[] = {
379 {
380 .base = S5P64X0_GPR_BASE + 0x4,
381 .config = &s5p64x0_gpio_cfgs[2],
382 .chip = {
383 .base = S5P6450_GPR(0),
384 .ngpio = S5P6450_GPIO_R_NR,
385 .label = "GPR",
386 },
387 },
388};
389
390static struct s3c_gpio_chip s5p6450_gpio_2bit[] = {
391 {
392 .base = S5P64X0_GPF_BASE,
393 .config = &s5p64x0_gpio_cfgs[5],
394 .chip = {
395 .base = S5P6450_GPF(0),
396 .ngpio = S5P6450_GPIO_F_NR,
397 .label = "GPF",
398 },
399 }, {
400 .base = S5P64X0_GPI_BASE,
401 .config = &s5p64x0_gpio_cfgs[3],
402 .chip = {
403 .base = S5P6450_GPI(0),
404 .ngpio = S5P6450_GPIO_I_NR,
405 .label = "GPI",
406 },
407 }, {
408 .base = S5P64X0_GPJ_BASE,
409 .config = &s5p64x0_gpio_cfgs[3],
410 .chip = {
411 .base = S5P6450_GPJ(0),
412 .ngpio = S5P6450_GPIO_J_NR,
413 .label = "GPJ",
414 },
415 }, {
416 .base = S5P64X0_GPN_BASE,
417 .config = &s5p64x0_gpio_cfgs[4],
418 .chip = {
419 .base = S5P6450_GPN(0),
420 .ngpio = S5P6450_GPIO_N_NR,
421 .label = "GPN",
422 },
423 }, {
424 .base = S5P64X0_GPP_BASE,
425 .config = &s5p64x0_gpio_cfgs[5],
426 .chip = {
427 .base = S5P6450_GPP(0),
428 .ngpio = S5P6450_GPIO_P_NR,
429 .label = "GPP",
430 },
431 }, {
432 .base = S5P6450_GPQ_BASE,
433 .config = &s5p64x0_gpio_cfgs[4],
434 .chip = {
435 .base = S5P6450_GPQ(0),
436 .ngpio = S5P6450_GPIO_Q_NR,
437 .label = "GPQ",
438 },
439 }, {
440 .base = S5P6450_GPS_BASE,
441 .config = &s5p64x0_gpio_cfgs[5],
442 .chip = {
443 .base = S5P6450_GPS(0),
444 .ngpio = S5P6450_GPIO_S_NR,
445 .label = "GPS",
446 },
447 },
448};
449
5dd33d89 450void __init s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
42d828d4
KK
451{
452 for (; nr_chips > 0; nr_chips--, chipcfg++) {
453 if (!chipcfg->set_config)
454 chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit;
97a33999
BD
455 if (!chipcfg->get_config)
456 chipcfg->get_config = s3c_gpio_getcfg_s3c64xx_4bit;
42d828d4
KK
457 if (!chipcfg->set_pull)
458 chipcfg->set_pull = s3c_gpio_setpull_updown;
459 if (!chipcfg->get_pull)
460 chipcfg->get_pull = s3c_gpio_getpull_updown;
461 }
462}
463
5dd33d89 464static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
42d828d4
KK
465 int nr_chips)
466{
467 for (; nr_chips > 0; nr_chips--, chip++) {
5dd33d89 468 chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
42d828d4 469 chip->chip.direction_output =
5dd33d89 470 s5p64x0_gpiolib_rbank_4bit2_output;
42d828d4
KK
471 s3c_gpiolib_add(chip);
472 }
473}
474
f50266d3 475static int __init s5p64x0_gpiolib_init(void)
42d828d4 476{
5dd33d89
KK
477 s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs,
478 ARRAY_SIZE(s5p64x0_gpio_cfgs));
f50266d3 479
a3d93584 480 if (soc_is_s5p6450()) {
bb1d7002
KK
481 samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit,
482 ARRAY_SIZE(s5p6450_gpio_2bit));
42d828d4 483
f50266d3
KK
484 samsung_gpiolib_add_4bit_chips(s5p6450_gpio_4bit,
485 ARRAY_SIZE(s5p6450_gpio_4bit));
42d828d4 486
f50266d3
KK
487 samsung_gpiolib_add_4bit2_chips(s5p6450_gpio_4bit2,
488 ARRAY_SIZE(s5p6450_gpio_4bit2));
42d828d4 489
f50266d3
KK
490 s5p64x0_gpio_add_rbank_4bit2(s5p6450_gpio_rbank_4bit2,
491 ARRAY_SIZE(s5p6450_gpio_rbank_4bit2));
492 } else {
bb1d7002
KK
493 samsung_gpiolib_add_2bit_chips(s5p6440_gpio_2bit,
494 ARRAY_SIZE(s5p6440_gpio_2bit));
42d828d4 495
f50266d3
KK
496 samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
497 ARRAY_SIZE(s5p6440_gpio_4bit));
498
499 samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
500 ARRAY_SIZE(s5p6440_gpio_4bit2));
501
502 s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2,
503 ARRAY_SIZE(s5p6440_gpio_rbank_4bit2));
504 }
42d828d4
KK
505
506 return 0;
507}
f85cbea9 508core_initcall(s5p64x0_gpiolib_init);