1 /* linux/arch/arm/mach-s5p64x0/gpiolib.c
3 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
6 * S5P64X0 - GPIOlib support
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.
13 #include <linux/kernel.h>
14 #include <linux/irq.h>
16 #include <linux/gpio.h>
19 #include <mach/regs-gpio.h>
20 #include <mach/regs-clock.h>
22 #include <plat/gpio-core.h>
23 #include <plat/gpio-cfg.h>
24 #include <plat/gpio-cfg-helpers.h>
27 * S5P6440 GPIO bank summary:
29 * Bank GPIOs Style SlpCon ExtInt Group
38 * N 16 2Bit No IRQ_EINT
42 * S5P6450 GPIO bank summary:
44 * Bank GPIOs Style SlpCon ExtInt Group
55 * N 16 2Bit No IRQ_EINT
58 * R 15 4Bit[2] Yes None
61 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
62 * [2] BANK has two control registers, GPxCON0 and GPxCON1
65 static int s5p64x0_gpiolib_rbank_4bit2_input(struct gpio_chip
*chip
,
68 struct s3c_gpio_chip
*ourchip
= to_s3c_gpio(chip
);
69 void __iomem
*base
= ourchip
->base
;
70 void __iomem
*regcon
= base
;
90 s3c_gpio_lock(ourchip
, flags
);
92 con
= __raw_readl(regcon
);
93 con
&= ~(0xf << con_4bit_shift(offset
));
94 __raw_writel(con
, regcon
);
96 s3c_gpio_unlock(ourchip
, flags
);
101 static int s5p64x0_gpiolib_rbank_4bit2_output(struct gpio_chip
*chip
,
102 unsigned int offset
, int value
)
104 struct s3c_gpio_chip
*ourchip
= to_s3c_gpio(chip
);
105 void __iomem
*base
= ourchip
->base
;
106 void __iomem
*regcon
= base
;
110 unsigned con_offset
= offset
;
112 switch (con_offset
) {
128 s3c_gpio_lock(ourchip
, flags
);
130 con
= __raw_readl(regcon
);
131 con
&= ~(0xf << con_4bit_shift(con_offset
));
132 con
|= 0x1 << con_4bit_shift(con_offset
);
134 dat
= __raw_readl(base
+ GPIODAT_OFF
);
138 dat
&= ~(1 << offset
);
140 __raw_writel(con
, regcon
);
141 __raw_writel(dat
, base
+ GPIODAT_OFF
);
143 s3c_gpio_unlock(ourchip
, flags
);
148 int s5p64x0_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip
*chip
,
149 unsigned int off
, unsigned int cfg
)
151 void __iomem
*reg
= chip
->base
;
162 shift
= (off
& 7) * 4;
166 shift
= ((off
+ 1) & 7) * 4;
169 shift
= ((off
+ 1) & 7) * 4;
173 if (s3c_gpio_is_cfg_special(cfg
)) {
178 con
= __raw_readl(reg
);
179 con
&= ~(0xf << shift
);
181 __raw_writel(con
, reg
);
186 static struct s3c_gpio_cfg s5p64x0_gpio_cfgs
[] = {
193 .set_config
= s5p64x0_gpio_setcfg_4bit_rbank
,
196 .set_config
= s3c_gpio_setcfg_s3c24xx
,
197 .get_config
= s3c_gpio_getcfg_s3c24xx
,
200 .set_config
= s3c_gpio_setcfg_s3c24xx
,
201 .get_config
= s3c_gpio_getcfg_s3c24xx
,
204 .set_config
= s3c_gpio_setcfg_s3c24xx
,
205 .get_config
= s3c_gpio_getcfg_s3c24xx
,
209 static struct s3c_gpio_chip s5p6440_gpio_4bit
[] = {
211 .base
= S5P64X0_GPA_BASE
,
212 .config
= &s5p64x0_gpio_cfgs
[1],
214 .base
= S5P6440_GPA(0),
215 .ngpio
= S5P6440_GPIO_A_NR
,
219 .base
= S5P64X0_GPB_BASE
,
220 .config
= &s5p64x0_gpio_cfgs
[1],
222 .base
= S5P6440_GPB(0),
223 .ngpio
= S5P6440_GPIO_B_NR
,
227 .base
= S5P64X0_GPC_BASE
,
228 .config
= &s5p64x0_gpio_cfgs
[1],
230 .base
= S5P6440_GPC(0),
231 .ngpio
= S5P6440_GPIO_C_NR
,
235 .base
= S5P64X0_GPG_BASE
,
236 .config
= &s5p64x0_gpio_cfgs
[1],
238 .base
= S5P6440_GPG(0),
239 .ngpio
= S5P6440_GPIO_G_NR
,
245 static struct s3c_gpio_chip s5p6440_gpio_4bit2
[] = {
247 .base
= S5P64X0_GPH_BASE
+ 0x4,
248 .config
= &s5p64x0_gpio_cfgs
[1],
250 .base
= S5P6440_GPH(0),
251 .ngpio
= S5P6440_GPIO_H_NR
,
257 static struct s3c_gpio_chip s5p6440_gpio_rbank_4bit2
[] = {
259 .base
= S5P64X0_GPR_BASE
+ 0x4,
260 .config
= &s5p64x0_gpio_cfgs
[2],
262 .base
= S5P6440_GPR(0),
263 .ngpio
= S5P6440_GPIO_R_NR
,
269 static struct s3c_gpio_chip s5p6440_gpio_2bit
[] = {
271 .base
= S5P64X0_GPF_BASE
,
272 .config
= &s5p64x0_gpio_cfgs
[5],
274 .base
= S5P6440_GPF(0),
275 .ngpio
= S5P6440_GPIO_F_NR
,
279 .base
= S5P64X0_GPI_BASE
,
280 .config
= &s5p64x0_gpio_cfgs
[3],
282 .base
= S5P6440_GPI(0),
283 .ngpio
= S5P6440_GPIO_I_NR
,
287 .base
= S5P64X0_GPJ_BASE
,
288 .config
= &s5p64x0_gpio_cfgs
[3],
290 .base
= S5P6440_GPJ(0),
291 .ngpio
= S5P6440_GPIO_J_NR
,
295 .base
= S5P64X0_GPN_BASE
,
296 .config
= &s5p64x0_gpio_cfgs
[4],
298 .base
= S5P6440_GPN(0),
299 .ngpio
= S5P6440_GPIO_N_NR
,
303 .base
= S5P64X0_GPP_BASE
,
304 .config
= &s5p64x0_gpio_cfgs
[5],
306 .base
= S5P6440_GPP(0),
307 .ngpio
= S5P6440_GPIO_P_NR
,
313 static struct s3c_gpio_chip s5p6450_gpio_4bit
[] = {
315 .base
= S5P64X0_GPA_BASE
,
316 .config
= &s5p64x0_gpio_cfgs
[1],
318 .base
= S5P6450_GPA(0),
319 .ngpio
= S5P6450_GPIO_A_NR
,
323 .base
= S5P64X0_GPB_BASE
,
324 .config
= &s5p64x0_gpio_cfgs
[1],
326 .base
= S5P6450_GPB(0),
327 .ngpio
= S5P6450_GPIO_B_NR
,
331 .base
= S5P64X0_GPC_BASE
,
332 .config
= &s5p64x0_gpio_cfgs
[1],
334 .base
= S5P6450_GPC(0),
335 .ngpio
= S5P6450_GPIO_C_NR
,
339 .base
= S5P6450_GPD_BASE
,
340 .config
= &s5p64x0_gpio_cfgs
[1],
342 .base
= S5P6450_GPD(0),
343 .ngpio
= S5P6450_GPIO_D_NR
,
347 .base
= S5P6450_GPK_BASE
,
348 .config
= &s5p64x0_gpio_cfgs
[1],
350 .base
= S5P6450_GPK(0),
351 .ngpio
= S5P6450_GPIO_K_NR
,
357 static struct s3c_gpio_chip s5p6450_gpio_4bit2
[] = {
359 .base
= S5P64X0_GPG_BASE
+ 0x4,
360 .config
= &s5p64x0_gpio_cfgs
[1],
362 .base
= S5P6450_GPG(0),
363 .ngpio
= S5P6450_GPIO_G_NR
,
367 .base
= S5P64X0_GPH_BASE
+ 0x4,
368 .config
= &s5p64x0_gpio_cfgs
[1],
370 .base
= S5P6450_GPH(0),
371 .ngpio
= S5P6450_GPIO_H_NR
,
377 static struct s3c_gpio_chip s5p6450_gpio_rbank_4bit2
[] = {
379 .base
= S5P64X0_GPR_BASE
+ 0x4,
380 .config
= &s5p64x0_gpio_cfgs
[2],
382 .base
= S5P6450_GPR(0),
383 .ngpio
= S5P6450_GPIO_R_NR
,
389 static struct s3c_gpio_chip s5p6450_gpio_2bit
[] = {
391 .base
= S5P64X0_GPF_BASE
,
392 .config
= &s5p64x0_gpio_cfgs
[5],
394 .base
= S5P6450_GPF(0),
395 .ngpio
= S5P6450_GPIO_F_NR
,
399 .base
= S5P64X0_GPI_BASE
,
400 .config
= &s5p64x0_gpio_cfgs
[3],
402 .base
= S5P6450_GPI(0),
403 .ngpio
= S5P6450_GPIO_I_NR
,
407 .base
= S5P64X0_GPJ_BASE
,
408 .config
= &s5p64x0_gpio_cfgs
[3],
410 .base
= S5P6450_GPJ(0),
411 .ngpio
= S5P6450_GPIO_J_NR
,
415 .base
= S5P64X0_GPN_BASE
,
416 .config
= &s5p64x0_gpio_cfgs
[4],
418 .base
= S5P6450_GPN(0),
419 .ngpio
= S5P6450_GPIO_N_NR
,
423 .base
= S5P64X0_GPP_BASE
,
424 .config
= &s5p64x0_gpio_cfgs
[5],
426 .base
= S5P6450_GPP(0),
427 .ngpio
= S5P6450_GPIO_P_NR
,
431 .base
= S5P6450_GPQ_BASE
,
432 .config
= &s5p64x0_gpio_cfgs
[4],
434 .base
= S5P6450_GPQ(0),
435 .ngpio
= S5P6450_GPIO_Q_NR
,
439 .base
= S5P6450_GPS_BASE
,
440 .config
= &s5p64x0_gpio_cfgs
[5],
442 .base
= S5P6450_GPS(0),
443 .ngpio
= S5P6450_GPIO_S_NR
,
449 void __init
s5p64x0_gpiolib_set_cfg(struct s3c_gpio_cfg
*chipcfg
, int nr_chips
)
451 for (; nr_chips
> 0; nr_chips
--, chipcfg
++) {
452 if (!chipcfg
->set_config
)
453 chipcfg
->set_config
= s3c_gpio_setcfg_s3c64xx_4bit
;
454 if (!chipcfg
->get_config
)
455 chipcfg
->get_config
= s3c_gpio_getcfg_s3c64xx_4bit
;
456 if (!chipcfg
->set_pull
)
457 chipcfg
->set_pull
= s3c_gpio_setpull_updown
;
458 if (!chipcfg
->get_pull
)
459 chipcfg
->get_pull
= s3c_gpio_getpull_updown
;
463 static void __init
s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip
*chip
,
466 for (; nr_chips
> 0; nr_chips
--, chip
++) {
467 chip
->chip
.direction_input
= s5p64x0_gpiolib_rbank_4bit2_input
;
468 chip
->chip
.direction_output
=
469 s5p64x0_gpiolib_rbank_4bit2_output
;
470 s3c_gpiolib_add(chip
);
474 static int __init
s5p64x0_gpiolib_init(void)
478 chipid
= __raw_readl(S5P64X0_SYS_ID
);
480 s5p64x0_gpiolib_set_cfg(s5p64x0_gpio_cfgs
,
481 ARRAY_SIZE(s5p64x0_gpio_cfgs
));
483 if ((chipid
& 0xff000) == 0x50000) {
484 samsung_gpiolib_add_2bit_chips(s5p6450_gpio_2bit
,
485 ARRAY_SIZE(s5p6450_gpio_2bit
));
487 samsung_gpiolib_add_4bit_chips(s5p6450_gpio_4bit
,
488 ARRAY_SIZE(s5p6450_gpio_4bit
));
490 samsung_gpiolib_add_4bit2_chips(s5p6450_gpio_4bit2
,
491 ARRAY_SIZE(s5p6450_gpio_4bit2
));
493 s5p64x0_gpio_add_rbank_4bit2(s5p6450_gpio_rbank_4bit2
,
494 ARRAY_SIZE(s5p6450_gpio_rbank_4bit2
));
496 samsung_gpiolib_add_2bit_chips(s5p6440_gpio_2bit
,
497 ARRAY_SIZE(s5p6440_gpio_2bit
));
499 samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit
,
500 ARRAY_SIZE(s5p6440_gpio_4bit
));
502 samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2
,
503 ARRAY_SIZE(s5p6440_gpio_4bit2
));
505 s5p64x0_gpio_add_rbank_4bit2(s5p6440_gpio_rbank_4bit2
,
506 ARRAY_SIZE(s5p6440_gpio_rbank_4bit2
));
511 core_initcall(s5p64x0_gpiolib_init
);