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);