Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   1/*
   2 * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
   3 *		http://www.samsung.com/
   4 *
   5 * Copyright 2008 Openmoko, Inc.
   6 * Copyright 2008 Simtec Electronics
   7 *      Ben Dooks <ben@simtec.co.uk>
   8 *      http://armlinux.simtec.co.uk/
   9 *
  10 * SAMSUNG - GPIOlib support
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/irq.h>
  19#include <linux/io.h>
  20#include <linux/gpio.h>
  21#include <linux/init.h>
  22#include <linux/spinlock.h>
  23#include <linux/module.h>
  24#include <linux/interrupt.h>
  25#include <linux/device.h>
  26#include <linux/ioport.h>
  27#include <linux/of.h>
  28#include <linux/slab.h>
  29#include <linux/of_address.h>
  30
  31#include <asm/irq.h>
  32
  33#include <mach/map.h>
  34#include <mach/regs-gpio.h>
  35
  36#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
  37#include <mach/gpio-samsung.h>
  38#endif
  39
  40#include <plat/cpu.h>
  41#include <plat/gpio-core.h>
  42#include <plat/gpio-cfg.h>
  43#include <plat/gpio-cfg-helpers.h>
  44#include <plat/pm.h>
  45
  46int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
  47				unsigned int off, samsung_gpio_pull_t pull)
  48{
  49	void __iomem *reg = chip->base + 0x08;
  50	int shift = off * 2;
  51	u32 pup;
  52
  53	pup = __raw_readl(reg);
  54	pup &= ~(3 << shift);
  55	pup |= pull << shift;
  56	__raw_writel(pup, reg);
  57
  58	return 0;
  59}
  60
  61samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
  62						unsigned int off)
  63{
  64	void __iomem *reg = chip->base + 0x08;
  65	int shift = off * 2;
  66	u32 pup = __raw_readl(reg);
  67
  68	pup >>= shift;
  69	pup &= 0x3;
  70
  71	return (__force samsung_gpio_pull_t)pup;
  72}
  73
  74int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
  75			 unsigned int off, samsung_gpio_pull_t pull)
  76{
  77	switch (pull) {
  78	case S3C_GPIO_PULL_NONE:
  79		pull = 0x01;
  80		break;
  81	case S3C_GPIO_PULL_UP:
  82		pull = 0x00;
  83		break;
  84	case S3C_GPIO_PULL_DOWN:
  85		pull = 0x02;
  86		break;
  87	}
  88	return samsung_gpio_setpull_updown(chip, off, pull);
  89}
  90
  91samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
  92					 unsigned int off)
  93{
  94	samsung_gpio_pull_t pull;
  95
  96	pull = samsung_gpio_getpull_updown(chip, off);
  97
  98	switch (pull) {
  99	case 0x00:
 100		pull = S3C_GPIO_PULL_UP;
 101		break;
 102	case 0x01:
 103	case 0x03:
 104		pull = S3C_GPIO_PULL_NONE;
 105		break;
 106	case 0x02:
 107		pull = S3C_GPIO_PULL_DOWN;
 108		break;
 109	}
 110
 111	return pull;
 112}
 113
 114static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
 115				  unsigned int off, samsung_gpio_pull_t pull,
 116				  samsung_gpio_pull_t updown)
 117{
 118	void __iomem *reg = chip->base + 0x08;
 119	u32 pup = __raw_readl(reg);
 120
 121	if (pull == updown)
 122		pup &= ~(1 << off);
 123	else if (pull == S3C_GPIO_PULL_NONE)
 124		pup |= (1 << off);
 125	else
 126		return -EINVAL;
 127
 128	__raw_writel(pup, reg);
 129	return 0;
 130}
 131
 132static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
 133						  unsigned int off,
 134						  samsung_gpio_pull_t updown)
 135{
 136	void __iomem *reg = chip->base + 0x08;
 137	u32 pup = __raw_readl(reg);
 138
 139	pup &= (1 << off);
 140	return pup ? S3C_GPIO_PULL_NONE : updown;
 141}
 142
 143samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
 144					     unsigned int off)
 145{
 146	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
 147}
 148
 149int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
 150			     unsigned int off, samsung_gpio_pull_t pull)
 151{
 152	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
 153}
 154
 155samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
 156					       unsigned int off)
 157{
 158	return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
 159}
 160
 161int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
 162			       unsigned int off, samsung_gpio_pull_t pull)
 163{
 164	return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
 165}
 166
 167/*
 168 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
 169 * @chip: The gpio chip that is being configured.
 170 * @off: The offset for the GPIO being configured.
 171 * @cfg: The configuration value to set.
 172 *
 173 * This helper deal with the GPIO cases where the control register
 174 * has two bits of configuration per gpio, which have the following
 175 * functions:
 176 *	00 = input
 177 *	01 = output
 178 *	1x = special function
 179 */
 180
 181static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
 182				    unsigned int off, unsigned int cfg)
 183{
 184	void __iomem *reg = chip->base;
 185	unsigned int shift = off * 2;
 186	u32 con;
 187
 188	if (samsung_gpio_is_cfg_special(cfg)) {
 189		cfg &= 0xf;
 190		if (cfg > 3)
 191			return -EINVAL;
 192
 193		cfg <<= shift;
 194	}
 195
 196	con = __raw_readl(reg);
 197	con &= ~(0x3 << shift);
 198	con |= cfg;
 199	__raw_writel(con, reg);
 200
 201	return 0;
 202}
 203
 204/*
 205 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
 206 * @chip: The gpio chip that is being configured.
 207 * @off: The offset for the GPIO being configured.
 208 *
 209 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
 210 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
 211 * S3C_GPIO_SPECIAL() macro.
 212 */
 213
 214static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
 215					     unsigned int off)
 216{
 217	u32 con;
 218
 219	con = __raw_readl(chip->base);
 220	con >>= off * 2;
 221	con &= 3;
 222
 223	/* this conversion works for IN and OUT as well as special mode */
 224	return S3C_GPIO_SPECIAL(con);
 225}
 226
 227/*
 228 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
 229 * @chip: The gpio chip that is being configured.
 230 * @off: The offset for the GPIO being configured.
 231 * @cfg: The configuration value to set.
 232 *
 233 * This helper deal with the GPIO cases where the control register has 4 bits
 234 * of control per GPIO, generally in the form of:
 235 *	0000 = Input
 236 *	0001 = Output
 237 *	others = Special functions (dependent on bank)
 238 *
 239 * Note, since the code to deal with the case where there are two control
 240 * registers instead of one, we do not have a separate set of functions for
 241 * each case.
 242 */
 243
 244static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
 245				    unsigned int off, unsigned int cfg)
 246{
 247	void __iomem *reg = chip->base;
 248	unsigned int shift = (off & 7) * 4;
 249	u32 con;
 250
 251	if (off < 8 && chip->chip.ngpio > 8)
 252		reg -= 4;
 253
 254	if (samsung_gpio_is_cfg_special(cfg)) {
 255		cfg &= 0xf;
 256		cfg <<= shift;
 257	}
 258
 259	con = __raw_readl(reg);
 260	con &= ~(0xf << shift);
 261	con |= cfg;
 262	__raw_writel(con, reg);
 263
 264	return 0;
 265}
 266
 267/*
 268 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
 269 * @chip: The gpio chip that is being configured.
 270 * @off: The offset for the GPIO being configured.
 271 *
 272 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
 273 * register setting into a value the software can use, such as could be passed
 274 * to samsung_gpio_setcfg_4bit().
 275 *
 276 * @sa samsung_gpio_getcfg_2bit
 277 */
 278
 279static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
 280					 unsigned int off)
 281{
 282	void __iomem *reg = chip->base;
 283	unsigned int shift = (off & 7) * 4;
 284	u32 con;
 285
 286	if (off < 8 && chip->chip.ngpio > 8)
 287		reg -= 4;
 288
 289	con = __raw_readl(reg);
 290	con >>= shift;
 291	con &= 0xf;
 292
 293	/* this conversion works for IN and OUT as well as special mode */
 294	return S3C_GPIO_SPECIAL(con);
 295}
 296
 297#ifdef CONFIG_PLAT_S3C24XX
 298/*
 299 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
 300 * @chip: The gpio chip that is being configured.
 301 * @off: The offset for the GPIO being configured.
 302 * @cfg: The configuration value to set.
 303 *
 304 * This helper deal with the GPIO cases where the control register
 305 * has one bit of configuration for the gpio, where setting the bit
 306 * means the pin is in special function mode and unset means output.
 307 */
 308
 309static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
 310				     unsigned int off, unsigned int cfg)
 311{
 312	void __iomem *reg = chip->base;
 313	unsigned int shift = off;
 314	u32 con;
 315
 316	if (samsung_gpio_is_cfg_special(cfg)) {
 317		cfg &= 0xf;
 318
 319		/* Map output to 0, and SFN2 to 1 */
 320		cfg -= 1;
 321		if (cfg > 1)
 322			return -EINVAL;
 323
 324		cfg <<= shift;
 325	}
 326
 327	con = __raw_readl(reg);
 328	con &= ~(0x1 << shift);
 329	con |= cfg;
 330	__raw_writel(con, reg);
 331
 332	return 0;
 333}
 334
 335/*
 336 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
 337 * @chip: The gpio chip that is being configured.
 338 * @off: The offset for the GPIO being configured.
 339 *
 340 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
 341 * GPIO configuration value.
 342 *
 343 * @sa samsung_gpio_getcfg_2bit
 344 * @sa samsung_gpio_getcfg_4bit
 345 */
 346
 347static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
 348					  unsigned int off)
 349{
 350	u32 con;
 351
 352	con = __raw_readl(chip->base);
 353	con >>= off;
 354	con &= 1;
 355	con++;
 356
 357	return S3C_GPIO_SFN(con);
 358}
 359#endif
 360
 361#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
 362static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
 363				     unsigned int off, unsigned int cfg)
 364{
 365	void __iomem *reg = chip->base;
 366	unsigned int shift;
 367	u32 con;
 368
 369	switch (off) {
 370	case 0:
 371	case 1:
 372	case 2:
 373	case 3:
 374	case 4:
 375	case 5:
 376		shift = (off & 7) * 4;
 377		reg -= 4;
 378		break;
 379	case 6:
 380		shift = ((off + 1) & 7) * 4;
 381		reg -= 4;
 382		break;
 383	default:
 384		shift = ((off + 1) & 7) * 4;
 385		break;
 386	}
 387
 388	if (samsung_gpio_is_cfg_special(cfg)) {
 389		cfg &= 0xf;
 390		cfg <<= shift;
 391	}
 392
 393	con = __raw_readl(reg);
 394	con &= ~(0xf << shift);
 395	con |= cfg;
 396	__raw_writel(con, reg);
 397
 398	return 0;
 399}
 400#endif
 401
 402static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
 403					   int nr_chips)
 404{
 405	for (; nr_chips > 0; nr_chips--, chipcfg++) {
 406		if (!chipcfg->set_config)
 407			chipcfg->set_config = samsung_gpio_setcfg_4bit;
 408		if (!chipcfg->get_config)
 409			chipcfg->get_config = samsung_gpio_getcfg_4bit;
 410		if (!chipcfg->set_pull)
 411			chipcfg->set_pull = samsung_gpio_setpull_updown;
 412		if (!chipcfg->get_pull)
 413			chipcfg->get_pull = samsung_gpio_getpull_updown;
 414	}
 415}
 416
 417struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
 418	.set_config	= samsung_gpio_setcfg_2bit,
 419	.get_config	= samsung_gpio_getcfg_2bit,
 420};
 421
 422#ifdef CONFIG_PLAT_S3C24XX
 423static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 424	.set_config	= s3c24xx_gpio_setcfg_abank,
 425	.get_config	= s3c24xx_gpio_getcfg_abank,
 426};
 427#endif
 428
 429#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
 430static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
 431	.cfg_eint	= 0x3,
 432	.set_config	= s5p64x0_gpio_setcfg_rbank,
 433	.get_config	= samsung_gpio_getcfg_4bit,
 434	.set_pull	= samsung_gpio_setpull_updown,
 435	.get_pull	= samsung_gpio_getpull_updown,
 436};
 437#endif
 438
 439static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
 440	[0] = {
 441		.cfg_eint	= 0x0,
 442	},
 443	[1] = {
 444		.cfg_eint	= 0x3,
 445	},
 446	[2] = {
 447		.cfg_eint	= 0x7,
 448	},
 449	[3] = {
 450		.cfg_eint	= 0xF,
 451	},
 452	[4] = {
 453		.cfg_eint	= 0x0,
 454		.set_config	= samsung_gpio_setcfg_2bit,
 455		.get_config	= samsung_gpio_getcfg_2bit,
 456	},
 457	[5] = {
 458		.cfg_eint	= 0x2,
 459		.set_config	= samsung_gpio_setcfg_2bit,
 460		.get_config	= samsung_gpio_getcfg_2bit,
 461	},
 462	[6] = {
 463		.cfg_eint	= 0x3,
 464		.set_config	= samsung_gpio_setcfg_2bit,
 465		.get_config	= samsung_gpio_getcfg_2bit,
 466	},
 467	[7] = {
 468		.set_config	= samsung_gpio_setcfg_2bit,
 469		.get_config	= samsung_gpio_getcfg_2bit,
 470	},
 471};
 472
 473/*
 474 * Default routines for controlling GPIO, based on the original S3C24XX
 475 * GPIO functions which deal with the case where each gpio bank of the
 476 * chip is as following:
 477 *
 478 * base + 0x00: Control register, 2 bits per gpio
 479 *	        gpio n: 2 bits starting at (2*n)
 480 *		00 = input, 01 = output, others mean special-function
 481 * base + 0x04: Data register, 1 bit per gpio
 482 *		bit n: data bit n
 483*/
 484
 485static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
 486{
 487	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 488	void __iomem *base = ourchip->base;
 489	unsigned long flags;
 490	unsigned long con;
 491
 492	samsung_gpio_lock(ourchip, flags);
 493
 494	con = __raw_readl(base + 0x00);
 495	con &= ~(3 << (offset * 2));
 496
 497	__raw_writel(con, base + 0x00);
 498
 499	samsung_gpio_unlock(ourchip, flags);
 500	return 0;
 501}
 502
 503static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
 504				       unsigned offset, int value)
 505{
 506	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 507	void __iomem *base = ourchip->base;
 508	unsigned long flags;
 509	unsigned long dat;
 510	unsigned long con;
 511
 512	samsung_gpio_lock(ourchip, flags);
 513
 514	dat = __raw_readl(base + 0x04);
 515	dat &= ~(1 << offset);
 516	if (value)
 517		dat |= 1 << offset;
 518	__raw_writel(dat, base + 0x04);
 519
 520	con = __raw_readl(base + 0x00);
 521	con &= ~(3 << (offset * 2));
 522	con |= 1 << (offset * 2);
 523
 524	__raw_writel(con, base + 0x00);
 525	__raw_writel(dat, base + 0x04);
 526
 527	samsung_gpio_unlock(ourchip, flags);
 528	return 0;
 529}
 530
 531/*
 532 * The samsung_gpiolib_4bit routines are to control the gpio banks where
 533 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
 534 * following example:
 535 *
 536 * base + 0x00: Control register, 4 bits per gpio
 537 *		gpio n: 4 bits starting at (4*n)
 538 *		0000 = input, 0001 = output, others mean special-function
 539 * base + 0x04: Data register, 1 bit per gpio
 540 *		bit n: data bit n
 541 *
 542 * Note, since the data register is one bit per gpio and is at base + 0x4
 543 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
 544 * state of the output.
 545 */
 546
 547static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
 548				      unsigned int offset)
 549{
 550	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 551	void __iomem *base = ourchip->base;
 552	unsigned long con;
 553
 554	con = __raw_readl(base + GPIOCON_OFF);
 555	if (ourchip->bitmap_gpio_int & BIT(offset))
 556		con |= 0xf << con_4bit_shift(offset);
 557	else
 558		con &= ~(0xf << con_4bit_shift(offset));
 559	__raw_writel(con, base + GPIOCON_OFF);
 560
 561	pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
 562
 563	return 0;
 564}
 565
 566static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
 567				       unsigned int offset, int value)
 568{
 569	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 570	void __iomem *base = ourchip->base;
 571	unsigned long con;
 572	unsigned long dat;
 573
 574	con = __raw_readl(base + GPIOCON_OFF);
 575	con &= ~(0xf << con_4bit_shift(offset));
 576	con |= 0x1 << con_4bit_shift(offset);
 577
 578	dat = __raw_readl(base + GPIODAT_OFF);
 579
 580	if (value)
 581		dat |= 1 << offset;
 582	else
 583		dat &= ~(1 << offset);
 584
 585	__raw_writel(dat, base + GPIODAT_OFF);
 586	__raw_writel(con, base + GPIOCON_OFF);
 587	__raw_writel(dat, base + GPIODAT_OFF);
 588
 589	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 590
 591	return 0;
 592}
 593
 594/*
 595 * The next set of routines are for the case where the GPIO configuration
 596 * registers are 4 bits per GPIO but there is more than one register (the
 597 * bank has more than 8 GPIOs.
 598 *
 599 * This case is the similar to the 4 bit case, but the registers are as
 600 * follows:
 601 *
 602 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
 603 *		gpio n: 4 bits starting at (4*n)
 604 *		0000 = input, 0001 = output, others mean special-function
 605 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
 606 *		gpio n: 4 bits starting at (4*n)
 607 *		0000 = input, 0001 = output, others mean special-function
 608 * base + 0x08: Data register, 1 bit per gpio
 609 *		bit n: data bit n
 610 *
 611 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
 612 * routines we store the 'base + 0x4' address so that these routines see
 613 * the data register at ourchip->base + 0x04.
 614 */
 615
 616static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
 617				       unsigned int offset)
 618{
 619	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 620	void __iomem *base = ourchip->base;
 621	void __iomem *regcon = base;
 622	unsigned long con;
 623
 624	if (offset > 7)
 625		offset -= 8;
 626	else
 627		regcon -= 4;
 628
 629	con = __raw_readl(regcon);
 630	con &= ~(0xf << con_4bit_shift(offset));
 631	__raw_writel(con, regcon);
 632
 633	pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
 634
 635	return 0;
 636}
 637
 638static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 639					unsigned int offset, int value)
 640{
 641	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 642	void __iomem *base = ourchip->base;
 643	void __iomem *regcon = base;
 644	unsigned long con;
 645	unsigned long dat;
 646	unsigned con_offset = offset;
 647
 648	if (con_offset > 7)
 649		con_offset -= 8;
 650	else
 651		regcon -= 4;
 652
 653	con = __raw_readl(regcon);
 654	con &= ~(0xf << con_4bit_shift(con_offset));
 655	con |= 0x1 << con_4bit_shift(con_offset);
 656
 657	dat = __raw_readl(base + GPIODAT_OFF);
 658
 659	if (value)
 660		dat |= 1 << offset;
 661	else
 662		dat &= ~(1 << offset);
 663
 664	__raw_writel(dat, base + GPIODAT_OFF);
 665	__raw_writel(con, regcon);
 666	__raw_writel(dat, base + GPIODAT_OFF);
 667
 668	pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 669
 670	return 0;
 671}
 672
 673#ifdef CONFIG_PLAT_S3C24XX
 674/* The next set of routines are for the case of s3c24xx bank a */
 675
 676static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
 677{
 678	return -EINVAL;
 679}
 680
 681static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
 682					unsigned offset, int value)
 683{
 684	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 685	void __iomem *base = ourchip->base;
 686	unsigned long flags;
 687	unsigned long dat;
 688	unsigned long con;
 689
 690	local_irq_save(flags);
 691
 692	con = __raw_readl(base + 0x00);
 693	dat = __raw_readl(base + 0x04);
 694
 695	dat &= ~(1 << offset);
 696	if (value)
 697		dat |= 1 << offset;
 698
 699	__raw_writel(dat, base + 0x04);
 700
 701	con &= ~(1 << offset);
 702
 703	__raw_writel(con, base + 0x00);
 704	__raw_writel(dat, base + 0x04);
 705
 706	local_irq_restore(flags);
 707	return 0;
 708}
 709#endif
 710
 711/* The next set of routines are for the case of s5p64x0 bank r */
 712
 713static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
 714				       unsigned int offset)
 715{
 716	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 717	void __iomem *base = ourchip->base;
 718	void __iomem *regcon = base;
 719	unsigned long con;
 720	unsigned long flags;
 721
 722	switch (offset) {
 723	case 6:
 724		offset += 1;
 725	case 0:
 726	case 1:
 727	case 2:
 728	case 3:
 729	case 4:
 730	case 5:
 731		regcon -= 4;
 732		break;
 733	default:
 734		offset -= 7;
 735		break;
 736	}
 737
 738	samsung_gpio_lock(ourchip, flags);
 739
 740	con = __raw_readl(regcon);
 741	con &= ~(0xf << con_4bit_shift(offset));
 742	__raw_writel(con, regcon);
 743
 744	samsung_gpio_unlock(ourchip, flags);
 745
 746	return 0;
 747}
 748
 749static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
 750					unsigned int offset, int value)
 751{
 752	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 753	void __iomem *base = ourchip->base;
 754	void __iomem *regcon = base;
 755	unsigned long con;
 756	unsigned long dat;
 757	unsigned long flags;
 758	unsigned con_offset  = offset;
 759
 760	switch (con_offset) {
 761	case 6:
 762		con_offset += 1;
 763	case 0:
 764	case 1:
 765	case 2:
 766	case 3:
 767	case 4:
 768	case 5:
 769		regcon -= 4;
 770		break;
 771	default:
 772		con_offset -= 7;
 773		break;
 774	}
 775
 776	samsung_gpio_lock(ourchip, flags);
 777
 778	con = __raw_readl(regcon);
 779	con &= ~(0xf << con_4bit_shift(con_offset));
 780	con |= 0x1 << con_4bit_shift(con_offset);
 781
 782	dat = __raw_readl(base + GPIODAT_OFF);
 783	if (value)
 784		dat |= 1 << offset;
 785	else
 786		dat &= ~(1 << offset);
 787
 788	__raw_writel(con, regcon);
 789	__raw_writel(dat, base + GPIODAT_OFF);
 790
 791	samsung_gpio_unlock(ourchip, flags);
 792
 793	return 0;
 794}
 795
 796static void samsung_gpiolib_set(struct gpio_chip *chip,
 797				unsigned offset, int value)
 798{
 799	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 800	void __iomem *base = ourchip->base;
 801	unsigned long flags;
 802	unsigned long dat;
 803
 804	samsung_gpio_lock(ourchip, flags);
 805
 806	dat = __raw_readl(base + 0x04);
 807	dat &= ~(1 << offset);
 808	if (value)
 809		dat |= 1 << offset;
 810	__raw_writel(dat, base + 0x04);
 811
 812	samsung_gpio_unlock(ourchip, flags);
 813}
 814
 815static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
 816{
 817	struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 818	unsigned long val;
 819
 820	val = __raw_readl(ourchip->base + 0x04);
 821	val >>= offset;
 822	val &= 1;
 823
 824	return val;
 825}
 826
 827/*
 828 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
 829 * for use with the configuration calls, and other parts of the s3c gpiolib
 830 * support code.
 831 *
 832 * Not all s3c support code will need this, as some configurations of cpu
 833 * may only support one or two different configuration options and have an
 834 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
 835 * the machine support file should provide its own samsung_gpiolib_getchip()
 836 * and any other necessary functions.
 837 */
 838
 839#ifdef CONFIG_S3C_GPIO_TRACK
 840struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 841
 842static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
 843{
 844	unsigned int gpn;
 845	int i;
 846
 847	gpn = chip->chip.base;
 848	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
 849		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
 850		s3c_gpios[gpn] = chip;
 851	}
 852}
 853#endif /* CONFIG_S3C_GPIO_TRACK */
 854
 855/*
 856 * samsung_gpiolib_add() - add the Samsung gpio_chip.
 857 * @chip: The chip to register
 858 *
 859 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
 860 * information and makes the necessary alterations for the platform and
 861 * notes the information for use with the configuration systems and any
 862 * other parts of the system.
 863 */
 864
 865static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 866{
 867	struct gpio_chip *gc = &chip->chip;
 868	int ret;
 869
 870	BUG_ON(!chip->base);
 871	BUG_ON(!gc->label);
 872	BUG_ON(!gc->ngpio);
 873
 874	spin_lock_init(&chip->lock);
 875
 876	if (!gc->direction_input)
 877		gc->direction_input = samsung_gpiolib_2bit_input;
 878	if (!gc->direction_output)
 879		gc->direction_output = samsung_gpiolib_2bit_output;
 880	if (!gc->set)
 881		gc->set = samsung_gpiolib_set;
 882	if (!gc->get)
 883		gc->get = samsung_gpiolib_get;
 884
 885#ifdef CONFIG_PM
 886	if (chip->pm != NULL) {
 887		if (!chip->pm->save || !chip->pm->resume)
 888			pr_err("gpio: %s has missing PM functions\n",
 889			       gc->label);
 890	} else
 891		pr_err("gpio: %s has no PM function\n", gc->label);
 892#endif
 893
 894	/* gpiochip_add() prints own failure message on error. */
 895	ret = gpiochip_add(gc);
 896	if (ret >= 0)
 897		s3c_gpiolib_track(chip);
 898}
 899
 900static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
 901					     int nr_chips, void __iomem *base)
 902{
 903	int i;
 904	struct gpio_chip *gc = &chip->chip;
 905
 906	for (i = 0 ; i < nr_chips; i++, chip++) {
 907		/* skip banks not present on SoC */
 908		if (chip->chip.base >= S3C_GPIO_END)
 909			continue;
 910
 911		if (!chip->config)
 912			chip->config = &s3c24xx_gpiocfg_default;
 913		if (!chip->pm)
 914			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
 915		if ((base != NULL) && (chip->base == NULL))
 916			chip->base = base + ((i) * 0x10);
 917
 918		if (!gc->direction_input)
 919			gc->direction_input = samsung_gpiolib_2bit_input;
 920		if (!gc->direction_output)
 921			gc->direction_output = samsung_gpiolib_2bit_output;
 922
 923		samsung_gpiolib_add(chip);
 924	}
 925}
 926
 927static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
 928						  int nr_chips, void __iomem *base,
 929						  unsigned int offset)
 930{
 931	int i;
 932
 933	for (i = 0 ; i < nr_chips; i++, chip++) {
 934		chip->chip.direction_input = samsung_gpiolib_2bit_input;
 935		chip->chip.direction_output = samsung_gpiolib_2bit_output;
 936
 937		if (!chip->config)
 938			chip->config = &samsung_gpio_cfgs[7];
 939		if (!chip->pm)
 940			chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
 941		if ((base != NULL) && (chip->base == NULL))
 942			chip->base = base + ((i) * offset);
 943
 944		samsung_gpiolib_add(chip);
 945	}
 946}
 947
 948/*
 949 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
 950 * @chip: The gpio chip that is being configured.
 951 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
 952 *
 953 * This helper deal with the GPIO cases where the control register has 4 bits
 954 * of control per GPIO, generally in the form of:
 955 * 0000 = Input
 956 * 0001 = Output
 957 * others = Special functions (dependent on bank)
 958 *
 959 * Note, since the code to deal with the case where there are two control
 960 * registers instead of one, we do not have a separate set of function
 961 * (samsung_gpiolib_add_4bit2_chips)for each case.
 962 */
 963
 964static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
 965						  int nr_chips, void __iomem *base)
 966{
 967	int i;
 968
 969	for (i = 0 ; i < nr_chips; i++, chip++) {
 970		chip->chip.direction_input = samsung_gpiolib_4bit_input;
 971		chip->chip.direction_output = samsung_gpiolib_4bit_output;
 972
 973		if (!chip->config)
 974			chip->config = &samsung_gpio_cfgs[2];
 975		if (!chip->pm)
 976			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
 977		if ((base != NULL) && (chip->base == NULL))
 978			chip->base = base + ((i) * 0x20);
 979
 980		chip->bitmap_gpio_int = 0;
 981
 982		samsung_gpiolib_add(chip);
 983	}
 984}
 985
 986static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
 987						   int nr_chips)
 988{
 989	for (; nr_chips > 0; nr_chips--, chip++) {
 990		chip->chip.direction_input = samsung_gpiolib_4bit2_input;
 991		chip->chip.direction_output = samsung_gpiolib_4bit2_output;
 992
 993		if (!chip->config)
 994			chip->config = &samsung_gpio_cfgs[2];
 995		if (!chip->pm)
 996			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
 997
 998		samsung_gpiolib_add(chip);
 999	}
1000}
1001
1002static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
1003					     int nr_chips)
1004{
1005	for (; nr_chips > 0; nr_chips--, chip++) {
1006		chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
1007		chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
1008
1009		if (!chip->pm)
1010			chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1011
1012		samsung_gpiolib_add(chip);
1013	}
1014}
1015
1016int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
1017{
1018	struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
1019
1020	return samsung_chip->irq_base + offset;
1021}
1022
1023#ifdef CONFIG_PLAT_S3C24XX
1024static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
1025{
1026	if (offset < 4) {
1027		if (soc_is_s3c2412())
1028			return IRQ_EINT0_2412 + offset;
1029		else
1030			return IRQ_EINT0 + offset;
1031	}
1032
1033	if (offset < 8)
1034		return IRQ_EINT4 + offset - 4;
1035
1036	return -EINVAL;
1037}
1038#endif
1039
1040#ifdef CONFIG_ARCH_S3C64XX
1041static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1042{
1043	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1044}
1045
1046static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1047{
1048	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1049}
1050#endif
1051
1052struct samsung_gpio_chip s3c24xx_gpios[] = {
1053#ifdef CONFIG_PLAT_S3C24XX
1054	{
1055		.config	= &s3c24xx_gpiocfg_banka,
1056		.chip	= {
1057			.base			= S3C2410_GPA(0),
1058			.owner			= THIS_MODULE,
1059			.label			= "GPIOA",
1060			.ngpio			= 27,
1061			.direction_input	= s3c24xx_gpiolib_banka_input,
1062			.direction_output	= s3c24xx_gpiolib_banka_output,
1063		},
1064	}, {
1065		.chip	= {
1066			.base	= S3C2410_GPB(0),
1067			.owner	= THIS_MODULE,
1068			.label	= "GPIOB",
1069			.ngpio	= 11,
1070		},
1071	}, {
1072		.chip	= {
1073			.base	= S3C2410_GPC(0),
1074			.owner	= THIS_MODULE,
1075			.label	= "GPIOC",
1076			.ngpio	= 16,
1077		},
1078	}, {
1079		.chip	= {
1080			.base	= S3C2410_GPD(0),
1081			.owner	= THIS_MODULE,
1082			.label	= "GPIOD",
1083			.ngpio	= 16,
1084		},
1085	}, {
1086		.chip	= {
1087			.base	= S3C2410_GPE(0),
1088			.label	= "GPIOE",
1089			.owner	= THIS_MODULE,
1090			.ngpio	= 16,
1091		},
1092	}, {
1093		.chip	= {
1094			.base	= S3C2410_GPF(0),
1095			.owner	= THIS_MODULE,
1096			.label	= "GPIOF",
1097			.ngpio	= 8,
1098			.to_irq	= s3c24xx_gpiolib_fbank_to_irq,
1099		},
1100	}, {
1101		.irq_base = IRQ_EINT8,
1102		.chip	= {
1103			.base	= S3C2410_GPG(0),
1104			.owner	= THIS_MODULE,
1105			.label	= "GPIOG",
1106			.ngpio	= 16,
1107			.to_irq	= samsung_gpiolib_to_irq,
1108		},
1109	}, {
1110		.chip	= {
1111			.base	= S3C2410_GPH(0),
1112			.owner	= THIS_MODULE,
1113			.label	= "GPIOH",
1114			.ngpio	= 15,
1115		},
1116	},
1117		/* GPIOS for the S3C2443 and later devices. */
1118	{
1119		.base	= S3C2440_GPJCON,
1120		.chip	= {
1121			.base	= S3C2410_GPJ(0),
1122			.owner	= THIS_MODULE,
1123			.label	= "GPIOJ",
1124			.ngpio	= 16,
1125		},
1126	}, {
1127		.base	= S3C2443_GPKCON,
1128		.chip	= {
1129			.base	= S3C2410_GPK(0),
1130			.owner	= THIS_MODULE,
1131			.label	= "GPIOK",
1132			.ngpio	= 16,
1133		},
1134	}, {
1135		.base	= S3C2443_GPLCON,
1136		.chip	= {
1137			.base	= S3C2410_GPL(0),
1138			.owner	= THIS_MODULE,
1139			.label	= "GPIOL",
1140			.ngpio	= 15,
1141		},
1142	}, {
1143		.base	= S3C2443_GPMCON,
1144		.chip	= {
1145			.base	= S3C2410_GPM(0),
1146			.owner	= THIS_MODULE,
1147			.label	= "GPIOM",
1148			.ngpio	= 2,
1149		},
1150	},
1151#endif
1152};
1153
1154/*
1155 * GPIO bank summary:
1156 *
1157 * Bank	GPIOs	Style	SlpCon	ExtInt Group
1158 * A	8	4Bit	Yes	1
1159 * B	7	4Bit	Yes	1
1160 * C	8	4Bit	Yes	2
1161 * D	5	4Bit	Yes	3
1162 * E	5	4Bit	Yes	None
1163 * F	16	2Bit	Yes	4 [1]
1164 * G	7	4Bit	Yes	5
1165 * H	10	4Bit[2]	Yes	6
1166 * I	16	2Bit	Yes	None
1167 * J	12	2Bit	Yes	None
1168 * K	16	4Bit[2]	No	None
1169 * L	15	4Bit[2] No	None
1170 * M	6	4Bit	No	IRQ_EINT
1171 * N	16	2Bit	No	IRQ_EINT
1172 * O	16	2Bit	Yes	7
1173 * P	15	2Bit	Yes	8
1174 * Q	9	2Bit	Yes	9
1175 *
1176 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1177 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1178 */
1179
1180static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1181#ifdef CONFIG_ARCH_S3C64XX
1182	{
1183		.chip	= {
1184			.base	= S3C64XX_GPA(0),
1185			.ngpio	= S3C64XX_GPIO_A_NR,
1186			.label	= "GPA",
1187		},
1188	}, {
1189		.chip	= {
1190			.base	= S3C64XX_GPB(0),
1191			.ngpio	= S3C64XX_GPIO_B_NR,
1192			.label	= "GPB",
1193		},
1194	}, {
1195		.chip	= {
1196			.base	= S3C64XX_GPC(0),
1197			.ngpio	= S3C64XX_GPIO_C_NR,
1198			.label	= "GPC",
1199		},
1200	}, {
1201		.chip	= {
1202			.base	= S3C64XX_GPD(0),
1203			.ngpio	= S3C64XX_GPIO_D_NR,
1204			.label	= "GPD",
1205		},
1206	}, {
1207		.config	= &samsung_gpio_cfgs[0],
1208		.chip	= {
1209			.base	= S3C64XX_GPE(0),
1210			.ngpio	= S3C64XX_GPIO_E_NR,
1211			.label	= "GPE",
1212		},
1213	}, {
1214		.base	= S3C64XX_GPG_BASE,
1215		.chip	= {
1216			.base	= S3C64XX_GPG(0),
1217			.ngpio	= S3C64XX_GPIO_G_NR,
1218			.label	= "GPG",
1219		},
1220	}, {
1221		.base	= S3C64XX_GPM_BASE,
1222		.config	= &samsung_gpio_cfgs[1],
1223		.chip	= {
1224			.base	= S3C64XX_GPM(0),
1225			.ngpio	= S3C64XX_GPIO_M_NR,
1226			.label	= "GPM",
1227			.to_irq = s3c64xx_gpiolib_mbank_to_irq,
1228		},
1229	},
1230#endif
1231};
1232
1233static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1234#ifdef CONFIG_ARCH_S3C64XX
1235	{
1236		.base	= S3C64XX_GPH_BASE + 0x4,
1237		.chip	= {
1238			.base	= S3C64XX_GPH(0),
1239			.ngpio	= S3C64XX_GPIO_H_NR,
1240			.label	= "GPH",
1241		},
1242	}, {
1243		.base	= S3C64XX_GPK_BASE + 0x4,
1244		.config	= &samsung_gpio_cfgs[0],
1245		.chip	= {
1246			.base	= S3C64XX_GPK(0),
1247			.ngpio	= S3C64XX_GPIO_K_NR,
1248			.label	= "GPK",
1249		},
1250	}, {
1251		.base	= S3C64XX_GPL_BASE + 0x4,
1252		.config	= &samsung_gpio_cfgs[1],
1253		.chip	= {
1254			.base	= S3C64XX_GPL(0),
1255			.ngpio	= S3C64XX_GPIO_L_NR,
1256			.label	= "GPL",
1257			.to_irq = s3c64xx_gpiolib_lbank_to_irq,
1258		},
1259	},
1260#endif
1261};
1262
1263static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1264#ifdef CONFIG_ARCH_S3C64XX
1265	{
1266		.base	= S3C64XX_GPF_BASE,
1267		.config	= &samsung_gpio_cfgs[6],
1268		.chip	= {
1269			.base	= S3C64XX_GPF(0),
1270			.ngpio	= S3C64XX_GPIO_F_NR,
1271			.label	= "GPF",
1272		},
1273	}, {
1274		.config	= &samsung_gpio_cfgs[7],
1275		.chip	= {
1276			.base	= S3C64XX_GPI(0),
1277			.ngpio	= S3C64XX_GPIO_I_NR,
1278			.label	= "GPI",
1279		},
1280	}, {
1281		.config	= &samsung_gpio_cfgs[7],
1282		.chip	= {
1283			.base	= S3C64XX_GPJ(0),
1284			.ngpio	= S3C64XX_GPIO_J_NR,
1285			.label	= "GPJ",
1286		},
1287	}, {
1288		.config	= &samsung_gpio_cfgs[6],
1289		.chip	= {
1290			.base	= S3C64XX_GPO(0),
1291			.ngpio	= S3C64XX_GPIO_O_NR,
1292			.label	= "GPO",
1293		},
1294	}, {
1295		.config	= &samsung_gpio_cfgs[6],
1296		.chip	= {
1297			.base	= S3C64XX_GPP(0),
1298			.ngpio	= S3C64XX_GPIO_P_NR,
1299			.label	= "GPP",
1300		},
1301	}, {
1302		.config	= &samsung_gpio_cfgs[6],
1303		.chip	= {
1304			.base	= S3C64XX_GPQ(0),
1305			.ngpio	= S3C64XX_GPIO_Q_NR,
1306			.label	= "GPQ",
1307		},
1308	}, {
1309		.base	= S3C64XX_GPN_BASE,
1310		.irq_base = IRQ_EINT(0),
1311		.config	= &samsung_gpio_cfgs[5],
1312		.chip	= {
1313			.base	= S3C64XX_GPN(0),
1314			.ngpio	= S3C64XX_GPIO_N_NR,
1315			.label	= "GPN",
1316			.to_irq = samsung_gpiolib_to_irq,
1317		},
1318	},
1319#endif
1320};
1321
1322/*
1323 * S5P6440 GPIO bank summary:
1324 *
1325 * Bank	GPIOs	Style	SlpCon	ExtInt Group
1326 * A	6	4Bit	Yes	1
1327 * B	7	4Bit	Yes	1
1328 * C	8	4Bit	Yes	2
1329 * F	2	2Bit	Yes	4 [1]
1330 * G	7	4Bit	Yes	5
1331 * H	10	4Bit[2]	Yes	6
1332 * I	16	2Bit	Yes	None
1333 * J	12	2Bit	Yes	None
1334 * N	16	2Bit	No	IRQ_EINT
1335 * P	8	2Bit	Yes	8
1336 * R	15	4Bit[2]	Yes	8
1337 */
1338
1339static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1340#ifdef CONFIG_CPU_S5P6440
1341	{
1342		.chip	= {
1343			.base	= S5P6440_GPA(0),
1344			.ngpio	= S5P6440_GPIO_A_NR,
1345			.label	= "GPA",
1346		},
1347	}, {
1348		.chip	= {
1349			.base	= S5P6440_GPB(0),
1350			.ngpio	= S5P6440_GPIO_B_NR,
1351			.label	= "GPB",
1352		},
1353	}, {
1354		.chip	= {
1355			.base	= S5P6440_GPC(0),
1356			.ngpio	= S5P6440_GPIO_C_NR,
1357			.label	= "GPC",
1358		},
1359	}, {
1360		.base	= S5P64X0_GPG_BASE,
1361		.chip	= {
1362			.base	= S5P6440_GPG(0),
1363			.ngpio	= S5P6440_GPIO_G_NR,
1364			.label	= "GPG",
1365		},
1366	},
1367#endif
1368};
1369
1370static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1371#ifdef CONFIG_CPU_S5P6440
1372	{
1373		.base	= S5P64X0_GPH_BASE + 0x4,
1374		.chip	= {
1375			.base	= S5P6440_GPH(0),
1376			.ngpio	= S5P6440_GPIO_H_NR,
1377			.label	= "GPH",
1378		},
1379	},
1380#endif
1381};
1382
1383static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1384#ifdef CONFIG_CPU_S5P6440
1385	{
1386		.base	= S5P64X0_GPR_BASE + 0x4,
1387		.config	= &s5p64x0_gpio_cfg_rbank,
1388		.chip	= {
1389			.base	= S5P6440_GPR(0),
1390			.ngpio	= S5P6440_GPIO_R_NR,
1391			.label	= "GPR",
1392		},
1393	},
1394#endif
1395};
1396
1397static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1398#ifdef CONFIG_CPU_S5P6440
1399	{
1400		.base	= S5P64X0_GPF_BASE,
1401		.config	= &samsung_gpio_cfgs[6],
1402		.chip	= {
1403			.base	= S5P6440_GPF(0),
1404			.ngpio	= S5P6440_GPIO_F_NR,
1405			.label	= "GPF",
1406		},
1407	}, {
1408		.base	= S5P64X0_GPI_BASE,
1409		.config	= &samsung_gpio_cfgs[4],
1410		.chip	= {
1411			.base	= S5P6440_GPI(0),
1412			.ngpio	= S5P6440_GPIO_I_NR,
1413			.label	= "GPI",
1414		},
1415	}, {
1416		.base	= S5P64X0_GPJ_BASE,
1417		.config	= &samsung_gpio_cfgs[4],
1418		.chip	= {
1419			.base	= S5P6440_GPJ(0),
1420			.ngpio	= S5P6440_GPIO_J_NR,
1421			.label	= "GPJ",
1422		},
1423	}, {
1424		.base	= S5P64X0_GPN_BASE,
1425		.config	= &samsung_gpio_cfgs[5],
1426		.chip	= {
1427			.base	= S5P6440_GPN(0),
1428			.ngpio	= S5P6440_GPIO_N_NR,
1429			.label	= "GPN",
1430		},
1431	}, {
1432		.base	= S5P64X0_GPP_BASE,
1433		.config	= &samsung_gpio_cfgs[6],
1434		.chip	= {
1435			.base	= S5P6440_GPP(0),
1436			.ngpio	= S5P6440_GPIO_P_NR,
1437			.label	= "GPP",
1438		},
1439	},
1440#endif
1441};
1442
1443/*
1444 * S5P6450 GPIO bank summary:
1445 *
1446 * Bank	GPIOs	Style	SlpCon	ExtInt Group
1447 * A	6	4Bit	Yes	1
1448 * B	7	4Bit	Yes	1
1449 * C	8	4Bit	Yes	2
1450 * D	8	4Bit	Yes	None
1451 * F	2	2Bit	Yes	None
1452 * G	14	4Bit[2]	Yes	5
1453 * H	10	4Bit[2]	Yes	6
1454 * I	16	2Bit	Yes	None
1455 * J	12	2Bit	Yes	None
1456 * K	5	4Bit	Yes	None
1457 * N	16	2Bit	No	IRQ_EINT
1458 * P	11	2Bit	Yes	8
1459 * Q	14	2Bit	Yes	None
1460 * R	15	4Bit[2]	Yes	None
1461 * S	8	2Bit	Yes	None
1462 *
1463 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1464 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1465 */
1466
1467static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1468#ifdef CONFIG_CPU_S5P6450
1469	{
1470		.chip	= {
1471			.base	= S5P6450_GPA(0),
1472			.ngpio	= S5P6450_GPIO_A_NR,
1473			.label	= "GPA",
1474		},
1475	}, {
1476		.chip	= {
1477			.base	= S5P6450_GPB(0),
1478			.ngpio	= S5P6450_GPIO_B_NR,
1479			.label	= "GPB",
1480		},
1481	}, {
1482		.chip	= {
1483			.base	= S5P6450_GPC(0),
1484			.ngpio	= S5P6450_GPIO_C_NR,
1485			.label	= "GPC",
1486		},
1487	}, {
1488		.chip	= {
1489			.base	= S5P6450_GPD(0),
1490			.ngpio	= S5P6450_GPIO_D_NR,
1491			.label	= "GPD",
1492		},
1493	}, {
1494		.base	= S5P6450_GPK_BASE,
1495		.chip	= {
1496			.base	= S5P6450_GPK(0),
1497			.ngpio	= S5P6450_GPIO_K_NR,
1498			.label	= "GPK",
1499		},
1500	},
1501#endif
1502};
1503
1504static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1505#ifdef CONFIG_CPU_S5P6450
1506	{
1507		.base	= S5P64X0_GPG_BASE + 0x4,
1508		.chip	= {
1509			.base	= S5P6450_GPG(0),
1510			.ngpio	= S5P6450_GPIO_G_NR,
1511			.label	= "GPG",
1512		},
1513	}, {
1514		.base	= S5P64X0_GPH_BASE + 0x4,
1515		.chip	= {
1516			.base	= S5P6450_GPH(0),
1517			.ngpio	= S5P6450_GPIO_H_NR,
1518			.label	= "GPH",
1519		},
1520	},
1521#endif
1522};
1523
1524static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1525#ifdef CONFIG_CPU_S5P6450
1526	{
1527		.base	= S5P64X0_GPR_BASE + 0x4,
1528		.config	= &s5p64x0_gpio_cfg_rbank,
1529		.chip	= {
1530			.base	= S5P6450_GPR(0),
1531			.ngpio	= S5P6450_GPIO_R_NR,
1532			.label	= "GPR",
1533		},
1534	},
1535#endif
1536};
1537
1538static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1539#ifdef CONFIG_CPU_S5P6450
1540	{
1541		.base	= S5P64X0_GPF_BASE,
1542		.config	= &samsung_gpio_cfgs[6],
1543		.chip	= {
1544			.base	= S5P6450_GPF(0),
1545			.ngpio	= S5P6450_GPIO_F_NR,
1546			.label	= "GPF",
1547		},
1548	}, {
1549		.base	= S5P64X0_GPI_BASE,
1550		.config	= &samsung_gpio_cfgs[4],
1551		.chip	= {
1552			.base	= S5P6450_GPI(0),
1553			.ngpio	= S5P6450_GPIO_I_NR,
1554			.label	= "GPI",
1555		},
1556	}, {
1557		.base	= S5P64X0_GPJ_BASE,
1558		.config	= &samsung_gpio_cfgs[4],
1559		.chip	= {
1560			.base	= S5P6450_GPJ(0),
1561			.ngpio	= S5P6450_GPIO_J_NR,
1562			.label	= "GPJ",
1563		},
1564	}, {
1565		.base	= S5P64X0_GPN_BASE,
1566		.config	= &samsung_gpio_cfgs[5],
1567		.chip	= {
1568			.base	= S5P6450_GPN(0),
1569			.ngpio	= S5P6450_GPIO_N_NR,
1570			.label	= "GPN",
1571		},
1572	}, {
1573		.base	= S5P64X0_GPP_BASE,
1574		.config	= &samsung_gpio_cfgs[6],
1575		.chip	= {
1576			.base	= S5P6450_GPP(0),
1577			.ngpio	= S5P6450_GPIO_P_NR,
1578			.label	= "GPP",
1579		},
1580	}, {
1581		.base	= S5P6450_GPQ_BASE,
1582		.config	= &samsung_gpio_cfgs[5],
1583		.chip	= {
1584			.base	= S5P6450_GPQ(0),
1585			.ngpio	= S5P6450_GPIO_Q_NR,
1586			.label	= "GPQ",
1587		},
1588	}, {
1589		.base	= S5P6450_GPS_BASE,
1590		.config	= &samsung_gpio_cfgs[6],
1591		.chip	= {
1592			.base	= S5P6450_GPS(0),
1593			.ngpio	= S5P6450_GPIO_S_NR,
1594			.label	= "GPS",
1595		},
1596	},
1597#endif
1598};
1599
1600/*
1601 * S5PC100 GPIO bank summary:
1602 *
1603 * Bank	GPIOs	Style	INT Type
1604 * A0	8	4Bit	GPIO_INT0
1605 * A1	5	4Bit	GPIO_INT1
1606 * B	8	4Bit	GPIO_INT2
1607 * C	5	4Bit	GPIO_INT3
1608 * D	7	4Bit	GPIO_INT4
1609 * E0	8	4Bit	GPIO_INT5
1610 * E1	6	4Bit	GPIO_INT6
1611 * F0	8	4Bit	GPIO_INT7
1612 * F1	8	4Bit	GPIO_INT8
1613 * F2	8	4Bit	GPIO_INT9
1614 * F3	4	4Bit	GPIO_INT10
1615 * G0	8	4Bit	GPIO_INT11
1616 * G1	3	4Bit	GPIO_INT12
1617 * G2	7	4Bit	GPIO_INT13
1618 * G3	7	4Bit	GPIO_INT14
1619 * H0	8	4Bit	WKUP_INT
1620 * H1	8	4Bit	WKUP_INT
1621 * H2	8	4Bit	WKUP_INT
1622 * H3	8	4Bit	WKUP_INT
1623 * I	8	4Bit	GPIO_INT15
1624 * J0	8	4Bit	GPIO_INT16
1625 * J1	5	4Bit	GPIO_INT17
1626 * J2	8	4Bit	GPIO_INT18
1627 * J3	8	4Bit	GPIO_INT19
1628 * J4	4	4Bit	GPIO_INT20
1629 * K0	8	4Bit	None
1630 * K1	6	4Bit	None
1631 * K2	8	4Bit	None
1632 * K3	8	4Bit	None
1633 * L0	8	4Bit	None
1634 * L1	8	4Bit	None
1635 * L2	8	4Bit	None
1636 * L3	8	4Bit	None
1637 */
1638
1639static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1640#ifdef CONFIG_CPU_S5PC100
1641	{
1642		.chip	= {
1643			.base	= S5PC100_GPA0(0),
1644			.ngpio	= S5PC100_GPIO_A0_NR,
1645			.label	= "GPA0",
1646		},
1647	}, {
1648		.chip	= {
1649			.base	= S5PC100_GPA1(0),
1650			.ngpio	= S5PC100_GPIO_A1_NR,
1651			.label	= "GPA1",
1652		},
1653	}, {
1654		.chip	= {
1655			.base	= S5PC100_GPB(0),
1656			.ngpio	= S5PC100_GPIO_B_NR,
1657			.label	= "GPB",
1658		},
1659	}, {
1660		.chip	= {
1661			.base	= S5PC100_GPC(0),
1662			.ngpio	= S5PC100_GPIO_C_NR,
1663			.label	= "GPC",
1664		},
1665	}, {
1666		.chip	= {
1667			.base	= S5PC100_GPD(0),
1668			.ngpio	= S5PC100_GPIO_D_NR,
1669			.label	= "GPD",
1670		},
1671	}, {
1672		.chip	= {
1673			.base	= S5PC100_GPE0(0),
1674			.ngpio	= S5PC100_GPIO_E0_NR,
1675			.label	= "GPE0",
1676		},
1677	}, {
1678		.chip	= {
1679			.base	= S5PC100_GPE1(0),
1680			.ngpio	= S5PC100_GPIO_E1_NR,
1681			.label	= "GPE1",
1682		},
1683	}, {
1684		.chip	= {
1685			.base	= S5PC100_GPF0(0),
1686			.ngpio	= S5PC100_GPIO_F0_NR,
1687			.label	= "GPF0",
1688		},
1689	}, {
1690		.chip	= {
1691			.base	= S5PC100_GPF1(0),
1692			.ngpio	= S5PC100_GPIO_F1_NR,
1693			.label	= "GPF1",
1694		},
1695	}, {
1696		.chip	= {
1697			.base	= S5PC100_GPF2(0),
1698			.ngpio	= S5PC100_GPIO_F2_NR,
1699			.label	= "GPF2",
1700		},
1701	}, {
1702		.chip	= {
1703			.base	= S5PC100_GPF3(0),
1704			.ngpio	= S5PC100_GPIO_F3_NR,
1705			.label	= "GPF3",
1706		},
1707	}, {
1708		.chip	= {
1709			.base	= S5PC100_GPG0(0),
1710			.ngpio	= S5PC100_GPIO_G0_NR,
1711			.label	= "GPG0",
1712		},
1713	}, {
1714		.chip	= {
1715			.base	= S5PC100_GPG1(0),
1716			.ngpio	= S5PC100_GPIO_G1_NR,
1717			.label	= "GPG1",
1718		},
1719	}, {
1720		.chip	= {
1721			.base	= S5PC100_GPG2(0),
1722			.ngpio	= S5PC100_GPIO_G2_NR,
1723			.label	= "GPG2",
1724		},
1725	}, {
1726		.chip	= {
1727			.base	= S5PC100_GPG3(0),
1728			.ngpio	= S5PC100_GPIO_G3_NR,
1729			.label	= "GPG3",
1730		},
1731	}, {
1732		.chip	= {
1733			.base	= S5PC100_GPI(0),
1734			.ngpio	= S5PC100_GPIO_I_NR,
1735			.label	= "GPI",
1736		},
1737	}, {
1738		.chip	= {
1739			.base	= S5PC100_GPJ0(0),
1740			.ngpio	= S5PC100_GPIO_J0_NR,
1741			.label	= "GPJ0",
1742		},
1743	}, {
1744		.chip	= {
1745			.base	= S5PC100_GPJ1(0),
1746			.ngpio	= S5PC100_GPIO_J1_NR,
1747			.label	= "GPJ1",
1748		},
1749	}, {
1750		.chip	= {
1751			.base	= S5PC100_GPJ2(0),
1752			.ngpio	= S5PC100_GPIO_J2_NR,
1753			.label	= "GPJ2",
1754		},
1755	}, {
1756		.chip	= {
1757			.base	= S5PC100_GPJ3(0),
1758			.ngpio	= S5PC100_GPIO_J3_NR,
1759			.label	= "GPJ3",
1760		},
1761	}, {
1762		.chip	= {
1763			.base	= S5PC100_GPJ4(0),
1764			.ngpio	= S5PC100_GPIO_J4_NR,
1765			.label	= "GPJ4",
1766		},
1767	}, {
1768		.chip	= {
1769			.base	= S5PC100_GPK0(0),
1770			.ngpio	= S5PC100_GPIO_K0_NR,
1771			.label	= "GPK0",
1772		},
1773	}, {
1774		.chip	= {
1775			.base	= S5PC100_GPK1(0),
1776			.ngpio	= S5PC100_GPIO_K1_NR,
1777			.label	= "GPK1",
1778		},
1779	}, {
1780		.chip	= {
1781			.base	= S5PC100_GPK2(0),
1782			.ngpio	= S5PC100_GPIO_K2_NR,
1783			.label	= "GPK2",
1784		},
1785	}, {
1786		.chip	= {
1787			.base	= S5PC100_GPK3(0),
1788			.ngpio	= S5PC100_GPIO_K3_NR,
1789			.label	= "GPK3",
1790		},
1791	}, {
1792		.chip	= {
1793			.base	= S5PC100_GPL0(0),
1794			.ngpio	= S5PC100_GPIO_L0_NR,
1795			.label	= "GPL0",
1796		},
1797	}, {
1798		.chip	= {
1799			.base	= S5PC100_GPL1(0),
1800			.ngpio	= S5PC100_GPIO_L1_NR,
1801			.label	= "GPL1",
1802		},
1803	}, {
1804		.chip	= {
1805			.base	= S5PC100_GPL2(0),
1806			.ngpio	= S5PC100_GPIO_L2_NR,
1807			.label	= "GPL2",
1808		},
1809	}, {
1810		.chip	= {
1811			.base	= S5PC100_GPL3(0),
1812			.ngpio	= S5PC100_GPIO_L3_NR,
1813			.label	= "GPL3",
1814		},
1815	}, {
1816		.chip	= {
1817			.base	= S5PC100_GPL4(0),
1818			.ngpio	= S5PC100_GPIO_L4_NR,
1819			.label	= "GPL4",
1820		},
1821	}, {
1822		.base	= (S5P_VA_GPIO + 0xC00),
1823		.irq_base = IRQ_EINT(0),
1824		.chip	= {
1825			.base	= S5PC100_GPH0(0),
1826			.ngpio	= S5PC100_GPIO_H0_NR,
1827			.label	= "GPH0",
1828			.to_irq = samsung_gpiolib_to_irq,
1829		},
1830	}, {
1831		.base	= (S5P_VA_GPIO + 0xC20),
1832		.irq_base = IRQ_EINT(8),
1833		.chip	= {
1834			.base	= S5PC100_GPH1(0),
1835			.ngpio	= S5PC100_GPIO_H1_NR,
1836			.label	= "GPH1",
1837			.to_irq = samsung_gpiolib_to_irq,
1838		},
1839	}, {
1840		.base	= (S5P_VA_GPIO + 0xC40),
1841		.irq_base = IRQ_EINT(16),
1842		.chip	= {
1843			.base	= S5PC100_GPH2(0),
1844			.ngpio	= S5PC100_GPIO_H2_NR,
1845			.label	= "GPH2",
1846			.to_irq = samsung_gpiolib_to_irq,
1847		},
1848	}, {
1849		.base	= (S5P_VA_GPIO + 0xC60),
1850		.irq_base = IRQ_EINT(24),
1851		.chip	= {
1852			.base	= S5PC100_GPH3(0),
1853			.ngpio	= S5PC100_GPIO_H3_NR,
1854			.label	= "GPH3",
1855			.to_irq = samsung_gpiolib_to_irq,
1856		},
1857	},
1858#endif
1859};
1860
1861/*
1862 * Followings are the gpio banks in S5PV210/S5PC110
1863 *
1864 * The 'config' member when left to NULL, is initialized to the default
1865 * structure samsung_gpio_cfgs[3] in the init function below.
1866 *
1867 * The 'base' member is also initialized in the init function below.
1868 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1869 * uses the above macro and depends on the banks being listed in order here.
1870 */
1871
1872static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1873#ifdef CONFIG_CPU_S5PV210
1874	{
1875		.chip	= {
1876			.base	= S5PV210_GPA0(0),
1877			.ngpio	= S5PV210_GPIO_A0_NR,
1878			.label	= "GPA0",
1879		},
1880	}, {
1881		.chip	= {
1882			.base	= S5PV210_GPA1(0),
1883			.ngpio	= S5PV210_GPIO_A1_NR,
1884			.label	= "GPA1",
1885		},
1886	}, {
1887		.chip	= {
1888			.base	= S5PV210_GPB(0),
1889			.ngpio	= S5PV210_GPIO_B_NR,
1890			.label	= "GPB",
1891		},
1892	}, {
1893		.chip	= {
1894			.base	= S5PV210_GPC0(0),
1895			.ngpio	= S5PV210_GPIO_C0_NR,
1896			.label	= "GPC0",
1897		},
1898	}, {
1899		.chip	= {
1900			.base	= S5PV210_GPC1(0),
1901			.ngpio	= S5PV210_GPIO_C1_NR,
1902			.label	= "GPC1",
1903		},
1904	}, {
1905		.chip	= {
1906			.base	= S5PV210_GPD0(0),
1907			.ngpio	= S5PV210_GPIO_D0_NR,
1908			.label	= "GPD0",
1909		},
1910	}, {
1911		.chip	= {
1912			.base	= S5PV210_GPD1(0),
1913			.ngpio	= S5PV210_GPIO_D1_NR,
1914			.label	= "GPD1",
1915		},
1916	}, {
1917		.chip	= {
1918			.base	= S5PV210_GPE0(0),
1919			.ngpio	= S5PV210_GPIO_E0_NR,
1920			.label	= "GPE0",
1921		},
1922	}, {
1923		.chip	= {
1924			.base	= S5PV210_GPE1(0),
1925			.ngpio	= S5PV210_GPIO_E1_NR,
1926			.label	= "GPE1",
1927		},
1928	}, {
1929		.chip	= {
1930			.base	= S5PV210_GPF0(0),
1931			.ngpio	= S5PV210_GPIO_F0_NR,
1932			.label	= "GPF0",
1933		},
1934	}, {
1935		.chip	= {
1936			.base	= S5PV210_GPF1(0),
1937			.ngpio	= S5PV210_GPIO_F1_NR,
1938			.label	= "GPF1",
1939		},
1940	}, {
1941		.chip	= {
1942			.base	= S5PV210_GPF2(0),
1943			.ngpio	= S5PV210_GPIO_F2_NR,
1944			.label	= "GPF2",
1945		},
1946	}, {
1947		.chip	= {
1948			.base	= S5PV210_GPF3(0),
1949			.ngpio	= S5PV210_GPIO_F3_NR,
1950			.label	= "GPF3",
1951		},
1952	}, {
1953		.chip	= {
1954			.base	= S5PV210_GPG0(0),
1955			.ngpio	= S5PV210_GPIO_G0_NR,
1956			.label	= "GPG0",
1957		},
1958	}, {
1959		.chip	= {
1960			.base	= S5PV210_GPG1(0),
1961			.ngpio	= S5PV210_GPIO_G1_NR,
1962			.label	= "GPG1",
1963		},
1964	}, {
1965		.chip	= {
1966			.base	= S5PV210_GPG2(0),
1967			.ngpio	= S5PV210_GPIO_G2_NR,
1968			.label	= "GPG2",
1969		},
1970	}, {
1971		.chip	= {
1972			.base	= S5PV210_GPG3(0),
1973			.ngpio	= S5PV210_GPIO_G3_NR,
1974			.label	= "GPG3",
1975		},
1976	}, {
1977		.chip	= {
1978			.base	= S5PV210_GPI(0),
1979			.ngpio	= S5PV210_GPIO_I_NR,
1980			.label	= "GPI",
1981		},
1982	}, {
1983		.chip	= {
1984			.base	= S5PV210_GPJ0(0),
1985			.ngpio	= S5PV210_GPIO_J0_NR,
1986			.label	= "GPJ0",
1987		},
1988	}, {
1989		.chip	= {
1990			.base	= S5PV210_GPJ1(0),
1991			.ngpio	= S5PV210_GPIO_J1_NR,
1992			.label	= "GPJ1",
1993		},
1994	}, {
1995		.chip	= {
1996			.base	= S5PV210_GPJ2(0),
1997			.ngpio	= S5PV210_GPIO_J2_NR,
1998			.label	= "GPJ2",
1999		},
2000	}, {
2001		.chip	= {
2002			.base	= S5PV210_GPJ3(0),
2003			.ngpio	= S5PV210_GPIO_J3_NR,
2004			.label	= "GPJ3",
2005		},
2006	}, {
2007		.chip	= {
2008			.base	= S5PV210_GPJ4(0),
2009			.ngpio	= S5PV210_GPIO_J4_NR,
2010			.label	= "GPJ4",
2011		},
2012	}, {
2013		.chip	= {
2014			.base	= S5PV210_MP01(0),
2015			.ngpio	= S5PV210_GPIO_MP01_NR,
2016			.label	= "MP01",
2017		},
2018	}, {
2019		.chip	= {
2020			.base	= S5PV210_MP02(0),
2021			.ngpio	= S5PV210_GPIO_MP02_NR,
2022			.label	= "MP02",
2023		},
2024	}, {
2025		.chip	= {
2026			.base	= S5PV210_MP03(0),
2027			.ngpio	= S5PV210_GPIO_MP03_NR,
2028			.label	= "MP03",
2029		},
2030	}, {
2031		.chip	= {
2032			.base	= S5PV210_MP04(0),
2033			.ngpio	= S5PV210_GPIO_MP04_NR,
2034			.label	= "MP04",
2035		},
2036	}, {
2037		.chip	= {
2038			.base	= S5PV210_MP05(0),
2039			.ngpio	= S5PV210_GPIO_MP05_NR,
2040			.label	= "MP05",
2041		},
2042	}, {
2043		.base	= (S5P_VA_GPIO + 0xC00),
2044		.irq_base = IRQ_EINT(0),
2045		.chip	= {
2046			.base	= S5PV210_GPH0(0),
2047			.ngpio	= S5PV210_GPIO_H0_NR,
2048			.label	= "GPH0",
2049			.to_irq = samsung_gpiolib_to_irq,
2050		},
2051	}, {
2052		.base	= (S5P_VA_GPIO + 0xC20),
2053		.irq_base = IRQ_EINT(8),
2054		.chip	= {
2055			.base	= S5PV210_GPH1(0),
2056			.ngpio	= S5PV210_GPIO_H1_NR,
2057			.label	= "GPH1",
2058			.to_irq = samsung_gpiolib_to_irq,
2059		},
2060	}, {
2061		.base	= (S5P_VA_GPIO + 0xC40),
2062		.irq_base = IRQ_EINT(16),
2063		.chip	= {
2064			.base	= S5PV210_GPH2(0),
2065			.ngpio	= S5PV210_GPIO_H2_NR,
2066			.label	= "GPH2",
2067			.to_irq = samsung_gpiolib_to_irq,
2068		},
2069	}, {
2070		.base	= (S5P_VA_GPIO + 0xC60),
2071		.irq_base = IRQ_EINT(24),
2072		.chip	= {
2073			.base	= S5PV210_GPH3(0),
2074			.ngpio	= S5PV210_GPIO_H3_NR,
2075			.label	= "GPH3",
2076			.to_irq = samsung_gpiolib_to_irq,
2077		},
2078	},
2079#endif
2080};
2081
2082/* TODO: cleanup soc_is_* */
2083static __init int samsung_gpiolib_init(void)
2084{
2085	struct samsung_gpio_chip *chip;
2086	int i, nr_chips;
2087	int group = 0;
2088
2089	/*
2090	 * Currently there are two drivers that can provide GPIO support for
2091	 * Samsung SoCs. For device tree enabled platforms, the new
2092	 * pinctrl-samsung driver is used, providing both GPIO and pin control
2093	 * interfaces. For legacy (non-DT) platforms this driver is used.
2094	 */
2095	if (of_have_populated_dt())
2096		return -ENODEV;
2097
2098	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2099
2100	if (soc_is_s3c24xx()) {
2101		s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2102				ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2103	} else if (soc_is_s3c64xx()) {
2104		samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2105				ARRAY_SIZE(s3c64xx_gpios_2bit),
2106				S3C64XX_VA_GPIO + 0xE0, 0x20);
2107		samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2108				ARRAY_SIZE(s3c64xx_gpios_4bit),
2109				S3C64XX_VA_GPIO);
2110		samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2111				ARRAY_SIZE(s3c64xx_gpios_4bit2));
2112	} else if (soc_is_s5p6440()) {
2113		samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2114				ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2115		samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2116				ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2117		samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2118				ARRAY_SIZE(s5p6440_gpios_4bit2));
2119		s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2120				ARRAY_SIZE(s5p6440_gpios_rbank));
2121	} else if (soc_is_s5p6450()) {
2122		samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2123				ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2124		samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2125				ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2126		samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2127				ARRAY_SIZE(s5p6450_gpios_4bit2));
2128		s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2129				ARRAY_SIZE(s5p6450_gpios_rbank));
2130	} else if (soc_is_s5pc100()) {
2131		group = 0;
2132		chip = s5pc100_gpios_4bit;
2133		nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2134
2135		for (i = 0; i < nr_chips; i++, chip++) {
2136			if (!chip->config) {
2137				chip->config = &samsung_gpio_cfgs[3];
2138				chip->group = group++;
2139			}
2140		}
2141		samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2142#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2143		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2144#endif
2145	} else if (soc_is_s5pv210()) {
2146		group = 0;
2147		chip = s5pv210_gpios_4bit;
2148		nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2149
2150		for (i = 0; i < nr_chips; i++, chip++) {
2151			if (!chip->config) {
2152				chip->config = &samsung_gpio_cfgs[3];
2153				chip->group = group++;
2154			}
2155		}
2156		samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2157#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2158		s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2159#endif
2160	} else {
2161		WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
2162		return -ENODEV;
2163	}
2164
2165	return 0;
2166}
2167core_initcall(samsung_gpiolib_init);
2168
2169int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2170{
2171	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2172	unsigned long flags;
2173	int offset;
2174	int ret;
2175
2176	if (!chip)
2177		return -EINVAL;
2178
2179	offset = pin - chip->chip.base;
2180
2181	samsung_gpio_lock(chip, flags);
2182	ret = samsung_gpio_do_setcfg(chip, offset, config);
2183	samsung_gpio_unlock(chip, flags);
2184
2185	return ret;
2186}
2187EXPORT_SYMBOL(s3c_gpio_cfgpin);
2188
2189int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2190			  unsigned int cfg)
2191{
2192	int ret;
2193
2194	for (; nr > 0; nr--, start++) {
2195		ret = s3c_gpio_cfgpin(start, cfg);
2196		if (ret != 0)
2197			return ret;
2198	}
2199
2200	return 0;
2201}
2202EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2203
2204int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2205			  unsigned int cfg, samsung_gpio_pull_t pull)
2206{
2207	int ret;
2208
2209	for (; nr > 0; nr--, start++) {
2210		s3c_gpio_setpull(start, pull);
2211		ret = s3c_gpio_cfgpin(start, cfg);
2212		if (ret != 0)
2213			return ret;
2214	}
2215
2216	return 0;
2217}
2218EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2219
2220unsigned s3c_gpio_getcfg(unsigned int pin)
2221{
2222	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2223	unsigned long flags;
2224	unsigned ret = 0;
2225	int offset;
2226
2227	if (chip) {
2228		offset = pin - chip->chip.base;
2229
2230		samsung_gpio_lock(chip, flags);
2231		ret = samsung_gpio_do_getcfg(chip, offset);
2232		samsung_gpio_unlock(chip, flags);
2233	}
2234
2235	return ret;
2236}
2237EXPORT_SYMBOL(s3c_gpio_getcfg);
2238
2239int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2240{
2241	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2242	unsigned long flags;
2243	int offset, ret;
2244
2245	if (!chip)
2246		return -EINVAL;
2247
2248	offset = pin - chip->chip.base;
2249
2250	samsung_gpio_lock(chip, flags);
2251	ret = samsung_gpio_do_setpull(chip, offset, pull);
2252	samsung_gpio_unlock(chip, flags);
2253
2254	return ret;
2255}
2256EXPORT_SYMBOL(s3c_gpio_setpull);
2257
2258samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2259{
2260	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2261	unsigned long flags;
2262	int offset;
2263	u32 pup = 0;
2264
2265	if (chip) {
2266		offset = pin - chip->chip.base;
2267
2268		samsung_gpio_lock(chip, flags);
2269		pup = samsung_gpio_do_getpull(chip, offset);
2270		samsung_gpio_unlock(chip, flags);
2271	}
2272
2273	return (__force samsung_gpio_pull_t)pup;
2274}
2275EXPORT_SYMBOL(s3c_gpio_getpull);
2276
2277#ifdef CONFIG_S5P_GPIO_DRVSTR
2278s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2279{
2280	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2281	unsigned int off;
2282	void __iomem *reg;
2283	int shift;
2284	u32 drvstr;
2285
2286	if (!chip)
2287		return -EINVAL;
2288
2289	off = pin - chip->chip.base;
2290	shift = off * 2;
2291	reg = chip->base + 0x0C;
2292
2293	drvstr = __raw_readl(reg);
2294	drvstr = drvstr >> shift;
2295	drvstr &= 0x3;
2296
2297	return (__force s5p_gpio_drvstr_t)drvstr;
2298}
2299EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2300
2301int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2302{
2303	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2304	unsigned int off;
2305	void __iomem *reg;
2306	int shift;
2307	u32 tmp;
2308
2309	if (!chip)
2310		return -EINVAL;
2311
2312	off = pin - chip->chip.base;
2313	shift = off * 2;
2314	reg = chip->base + 0x0C;
2315
2316	tmp = __raw_readl(reg);
2317	tmp &= ~(0x3 << shift);
2318	tmp |= drvstr << shift;
2319
2320	__raw_writel(tmp, reg);
2321
2322	return 0;
2323}
2324EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2325#endif	/* CONFIG_S5P_GPIO_DRVSTR */
2326
2327#ifdef CONFIG_PLAT_S3C24XX
2328unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2329{
2330	unsigned long flags;
2331	unsigned long misccr;
2332
2333	local_irq_save(flags);
2334	misccr = __raw_readl(S3C24XX_MISCCR);
2335	misccr &= ~clear;
2336	misccr ^= change;
2337	__raw_writel(misccr, S3C24XX_MISCCR);
2338	local_irq_restore(flags);
2339
2340	return misccr;
2341}
2342EXPORT_SYMBOL(s3c2410_modify_misccr);
2343#endif