[PATCH 05/21] ARM: S5PC1XX: prepare common gpiolib code for S5PC110 sub-platform

Marek Szyprowski m.szyprowski at samsung.com
Thu Jan 14 06:29:23 EST 2010


S5PC100 GPIOlib support has been rewriten to make it possible to reuse
most of the common code in the upcoming S5PC110 sub-platform.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 arch/arm/mach-s5pc100/Makefile                    |    1 +
 arch/arm/mach-s5pc100/gpio-chips.c                |  106 ++++++
 arch/arm/mach-s5pc100/include/mach/gpio.h         |   46 +++
 arch/arm/mach-s5pc100/include/plat/irqs.h         |  198 +++++++++++
 arch/arm/mach-s5pc100/include/plat/regs-gpio.h    |   70 ++++
 arch/arm/plat-s5pc1xx/gpiolib.c                   |  374 ++-------------------
 arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h |   79 +++++
 arch/arm/plat-s5pc1xx/include/plat/irqs.h         |  198 -----------
 arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h    |   70 ----
 arch/arm/plat-s5pc1xx/irq-eint.c                  |   13 +-
 arch/arm/plat-s5pc1xx/irq-gpio.c                  |  105 +-----
 11 files changed, 558 insertions(+), 702 deletions(-)
 create mode 100644 arch/arm/mach-s5pc100/gpio-chips.c
 create mode 100644 arch/arm/mach-s5pc100/include/plat/irqs.h
 create mode 100644 arch/arm/mach-s5pc100/include/plat/regs-gpio.h
 create mode 100644 arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h
 delete mode 100644 arch/arm/plat-s5pc1xx/include/plat/irqs.h
 delete mode 100644 arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h

diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile
index dc6b0ff..8d29ea1 100644
--- a/arch/arm/mach-s5pc100/Makefile
+++ b/arch/arm/mach-s5pc100/Makefile
@@ -13,6 +13,7 @@ obj-				:=
 
 obj-$(CONFIG_CPU_S5PC100)	+= cpu.o
 obj-$(CONFIG_CPU_S5PC100)	+= clocks.o
+obj-$(CONFIG_CPU_S5PC100)	+= gpio-chips.o
 obj-$(CONFIG_CPU_S5PC100)	+= plls.o
 obj-$(CONFIG_CPU_S5PC100)	+= uarts.o
 
diff --git a/arch/arm/mach-s5pc100/gpio-chips.c b/arch/arm/mach-s5pc100/gpio-chips.c
new file mode 100644
index 0000000..f8fa8d7
--- /dev/null
+++ b/arch/arm/mach-s5pc100/gpio-chips.c
@@ -0,0 +1,106 @@
+/*
+ * linux/arch/arm/mach-s5pc100/gpio-chips.c
+ *
+ *  Copyright 2009 Samsung Electronics Co
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *  Marek Szyprowski <m.szyprowski at samsung.com>
+ *
+ * S5PC100 - GPIOlib chip definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/map.h>
+#include <mach/gpio-core.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-s5pc1xx.h>
+#include <plat/regs-gpio.h>
+
+/* S5PC100 GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	INT Type
+ * A0	8	4Bit	GPIO_INT0
+ * A1	5	4Bit	GPIO_INT1
+ * B	8	4Bit	GPIO_INT2
+ * C	5	4Bit	GPIO_INT3
+ * D	7	4Bit	GPIO_INT4
+ * E0	8	4Bit	GPIO_INT5
+ * E1	6	4Bit	GPIO_INT6
+ * F0	8	4Bit	GPIO_INT7
+ * F1	8	4Bit	GPIO_INT8
+ * F2	8	4Bit	GPIO_INT9
+ * F3	4	4Bit	GPIO_INT10
+ * G0	8	4Bit	GPIO_INT11
+ * G1	3	4Bit	GPIO_INT12
+ * G2	7	4Bit	GPIO_INT13
+ * G3	7	4Bit	GPIO_INT14
+ * H0	8	4Bit	WKUP_INT
+ * H1	8	4Bit	WKUP_INT
+ * H2	8	4Bit	WKUP_INT
+ * H3	8	4Bit	WKUP_INT
+ * I	8	4Bit	GPIO_INT15
+ * J0	8	4Bit	GPIO_INT16
+ * J1	5	4Bit	GPIO_INT17
+ * J2	8	4Bit	GPIO_INT18
+ * J3	8	4Bit	GPIO_INT19
+ * J4	4	4Bit	GPIO_INT20
+ * K0	8	4Bit	None
+ * K1	6	4Bit	None
+ * K2	8	4Bit	None
+ * K3	8	4Bit	None
+ * L0	8	4Bit	None
+ * L1	8	4Bit	None
+ * L2	8	4Bit	None
+ * L3	8	4Bit	None
+ */
+
+static struct s5pc1xx_gpio_chip s5pc100_gpio_chips[] = {
+	S5PC1XX_INT_CHIP_DEF(S5PC100, A0),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, A1),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, B),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, C),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, D),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, E0),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, E1),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, F0),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, F1),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, F2),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, F3),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, G0),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, G1),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, G2),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, G3),
+	S5PC1XX_EINT_CHIP_DEF(S5PC100, H0),
+	S5PC1XX_EINT_CHIP_DEF(S5PC100, H1),
+	S5PC1XX_EINT_CHIP_DEF(S5PC100, H2),
+	S5PC1XX_EINT_CHIP_DEF(S5PC100, H3),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, I),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, J0),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, J1),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, J2),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, J3),
+	S5PC1XX_INT_CHIP_DEF(S5PC100, J4),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, K0),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, K1),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, K2),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, K3),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, L0),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, L1),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, L2),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, L3),
+	S5PC1XX_NOINT_CHIP_DEF(S5PC100, L4),
+};
+
+struct s5pc1xx_gpio s5pc1xx_gpio_chips = {
+	.chips = s5pc100_gpio_chips,
+	.count = ARRAY_SIZE(s5pc100_gpio_chips),
+};
diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h
index 2c4cbe8..3142c40 100644
--- a/arch/arm/mach-s5pc100/include/mach/gpio.h
+++ b/arch/arm/mach-s5pc100/include/mach/gpio.h
@@ -159,4 +159,50 @@ enum s3c_gpio_number {
 /* define the number of gpios we need to the one after the MP04() range */
 #define ARCH_NR_GPIOS		(S5PC100_GPIO_END + 1)
 
+/* Offset of the bank in the interrupt group registers */
+#define S5PC100_GPIO_A0_INT_GROUP	(0)
+#define S5PC100_GPIO_A1_INT_GROUP	(1)
+#define S5PC100_GPIO_B_INT_GROUP	(2)
+#define S5PC100_GPIO_C_INT_GROUP	(3)
+#define S5PC100_GPIO_D_INT_GROUP	(4)
+#define S5PC100_GPIO_E0_INT_GROUP	(5)
+#define S5PC100_GPIO_E1_INT_GROUP	(6)
+#define S5PC100_GPIO_F0_INT_GROUP	(7)
+#define S5PC100_GPIO_F1_INT_GROUP	(8)
+#define S5PC100_GPIO_F2_INT_GROUP	(9)
+#define S5PC100_GPIO_F3_INT_GROUP	(10)
+#define S5PC100_GPIO_G0_INT_GROUP	(11)
+#define S5PC100_GPIO_G1_INT_GROUP	(12)
+#define S5PC100_GPIO_G2_INT_GROUP	(13)
+#define S5PC100_GPIO_G3_INT_GROUP	(14)
+#define S5PC100_GPIO_I_INT_GROUP	(15)
+#define S5PC100_GPIO_J0_INT_GROUP	(16)
+#define S5PC100_GPIO_J1_INT_GROUP	(17)
+#define S5PC100_GPIO_J2_INT_GROUP	(18)
+#define S5PC100_GPIO_J3_INT_GROUP	(19)
+#define S5PC100_GPIO_J4_INT_GROUP	(20)
+#define S5PC100_GPIO_H0_INT_GROUP	(-1)
+#define S5PC100_GPIO_H1_INT_GROUP	(-1)
+#define S5PC100_GPIO_H2_INT_GROUP	(-1)
+#define S5PC100_GPIO_H3_INT_GROUP	(-1)
+#define S5PC100_GPIO_K0_INT_GROUP	(-1)
+#define S5PC100_GPIO_K1_INT_GROUP	(-1)
+#define S5PC100_GPIO_K2_INT_GROUP	(-1)
+#define S5PC100_GPIO_K3_INT_GROUP	(-1)
+#define S5PC100_GPIO_L0_INT_GROUP	(-1)
+#define S5PC100_GPIO_L1_INT_GROUP	(-1)
+#define S5PC100_GPIO_L2_INT_GROUP	(-1)
+#define S5PC100_GPIO_L3_INT_GROUP	(-1)
+#define S5PC100_GPIO_L4_INT_GROUP	(-1)
+
+#define S5PC100_GPIO_INT_GROUP_END	(S5PC100_GPIO_J4_INT_GROUP + 1)
+
+/* Common compatibility defines */
+#define S5PC1XX_GPIO_EINT_SFN	S3C_GPIO_SFN(0x2)
+#define S5PC1XX_GPH0(n)		S5PC100_GPH0(n)
+#define S5PC1XX_GPH1(n)		S5PC100_GPH1(n)
+#define S5PC1XX_GPH2(n)		S5PC100_GPH2(n)
+#define S5PC1XX_GPH3(n)		S5PC100_GPH3(n)
+#define S5PC1XX_GPIO_INT_GROUP_END	S5PC100_GPIO_INT_GROUP_END
+
 #include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-s5pc100/include/plat/irqs.h b/arch/arm/mach-s5pc100/include/plat/irqs.h
new file mode 100644
index 0000000..c06f4ff
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/plat/irqs.h
@@ -0,0 +1,198 @@
+/* linux/arch/arm/plat-s5pc1xx/include/plat/irqs.h
+ *
+ * Copyright 2009 Samsung Electronics Co.
+ *      Byungho Min <bhmin at samsung.com>
+ *
+ * S5PC100 - Common IRQ support
+ *
+ * Based on plat-s3c64xx/include/plat/irqs.h
+ */
+
+#ifndef __ASM_PLAT_S5PC1XX_IRQS_H
+#define __ASM_PLAT_S5PC1XX_IRQS_H __FILE__
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ *
+ * note, since we're using the VICs, our start must be a
+ * mulitple of 32 to allow the common code to work
+ */
+
+#define S3C_IRQ_OFFSET		(32)
+
+#define S3C_IRQ(x)		((x) + S3C_IRQ_OFFSET)
+
+#define S3C_VIC0_BASE		S3C_IRQ(0)
+#define S3C_VIC1_BASE		S3C_IRQ(32)
+#define S3C_VIC2_BASE		S3C_IRQ(64)
+
+/* UART interrupts, each UART has 4 intterupts per channel so
+ * use the space between the ISA and S3C main interrupts. Note, these
+ * are not in the same order as the S3C24XX series! */
+
+#define IRQ_S3CUART_BASE0	(16)
+#define IRQ_S3CUART_BASE1	(20)
+#define IRQ_S3CUART_BASE2	(24)
+#define IRQ_S3CUART_BASE3	(28)
+
+#define UART_IRQ_RXD		(0)
+#define UART_IRQ_ERR		(1)
+#define UART_IRQ_TXD		(2)
+#define UART_IRQ_MODEM		(3)
+
+#define IRQ_S3CUART_RX0		(IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX0		(IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR0	(IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
+
+#define IRQ_S3CUART_RX1		(IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX1		(IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR1	(IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
+
+#define IRQ_S3CUART_RX2		(IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX2		(IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR2	(IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
+
+#define IRQ_S3CUART_RX3		(IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX3		(IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR3	(IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
+
+/* VIC based IRQs */
+
+#define S5PC1XX_IRQ_VIC0(x)	(S3C_VIC0_BASE + (x))
+#define S5PC1XX_IRQ_VIC1(x)	(S3C_VIC1_BASE + (x))
+#define S5PC1XX_IRQ_VIC2(x)	(S3C_VIC2_BASE + (x))
+
+/*
+ * VIC0: system, DMA, timer
+ */
+#define IRQ_EINT0		S5PC1XX_IRQ_VIC0(0)
+#define IRQ_EINT1		S5PC1XX_IRQ_VIC0(1)
+#define IRQ_EINT2		S5PC1XX_IRQ_VIC0(2)
+#define IRQ_EINT3		S5PC1XX_IRQ_VIC0(3)
+#define IRQ_EINT4		S5PC1XX_IRQ_VIC0(4)
+#define IRQ_EINT5		S5PC1XX_IRQ_VIC0(5)
+#define IRQ_EINT6		S5PC1XX_IRQ_VIC0(6)
+#define IRQ_EINT7		S5PC1XX_IRQ_VIC0(7)
+#define IRQ_EINT8		S5PC1XX_IRQ_VIC0(8)
+#define IRQ_EINT9		S5PC1XX_IRQ_VIC0(9)
+#define IRQ_EINT10		S5PC1XX_IRQ_VIC0(10)
+#define IRQ_EINT11		S5PC1XX_IRQ_VIC0(11)
+#define IRQ_EINT12		S5PC1XX_IRQ_VIC0(12)
+#define IRQ_EINT13		S5PC1XX_IRQ_VIC0(13)
+#define IRQ_EINT14		S5PC1XX_IRQ_VIC0(14)
+#define IRQ_EINT15		S5PC1XX_IRQ_VIC0(15)
+#define IRQ_EINT16_31		S5PC1XX_IRQ_VIC0(16)
+#define IRQ_BATF		S5PC1XX_IRQ_VIC0(17)
+#define IRQ_MDMA		S5PC1XX_IRQ_VIC0(18)
+#define IRQ_PDMA0		S5PC1XX_IRQ_VIC0(19)
+#define IRQ_PDMA1		S5PC1XX_IRQ_VIC0(20)
+#define IRQ_TIMER0_VIC		S5PC1XX_IRQ_VIC0(21)
+#define IRQ_TIMER1_VIC		S5PC1XX_IRQ_VIC0(22)
+#define IRQ_TIMER2_VIC		S5PC1XX_IRQ_VIC0(23)
+#define IRQ_TIMER3_VIC		S5PC1XX_IRQ_VIC0(24)
+#define IRQ_TIMER4_VIC		S5PC1XX_IRQ_VIC0(25)
+#define IRQ_SYSTIMER		S5PC1XX_IRQ_VIC0(26)
+#define IRQ_WDT			S5PC1XX_IRQ_VIC0(27)
+#define IRQ_RTC_ALARM		S5PC1XX_IRQ_VIC0(28)
+#define IRQ_RTC_TIC		S5PC1XX_IRQ_VIC0(29)
+#define IRQ_GPIOINT		S5PC1XX_IRQ_VIC0(30)
+
+/*
+ * VIC1: ARM, power, memory, connectivity
+ */
+#define IRQ_CORTEX0		S5PC1XX_IRQ_VIC1(0)
+#define IRQ_CORTEX1		S5PC1XX_IRQ_VIC1(1)
+#define IRQ_CORTEX2		S5PC1XX_IRQ_VIC1(2)
+#define IRQ_CORTEX3		S5PC1XX_IRQ_VIC1(3)
+#define IRQ_CORTEX4		S5PC1XX_IRQ_VIC1(4)
+#define IRQ_IEMAPC		S5PC1XX_IRQ_VIC1(5)
+#define IRQ_IEMIEC		S5PC1XX_IRQ_VIC1(6)
+#define IRQ_ONENAND		S5PC1XX_IRQ_VIC1(7)
+#define IRQ_NFC			S5PC1XX_IRQ_VIC1(8)
+#define IRQ_CFC			S5PC1XX_IRQ_VIC1(9)
+#define IRQ_UART0		S5PC1XX_IRQ_VIC1(10)
+#define IRQ_UART1		S5PC1XX_IRQ_VIC1(11)
+#define IRQ_UART2		S5PC1XX_IRQ_VIC1(12)
+#define IRQ_UART3		S5PC1XX_IRQ_VIC1(13)
+#define IRQ_IIC			S5PC1XX_IRQ_VIC1(14)
+#define IRQ_SPI0		S5PC1XX_IRQ_VIC1(15)
+#define IRQ_SPI1		S5PC1XX_IRQ_VIC1(16)
+#define IRQ_SPI2		S5PC1XX_IRQ_VIC1(17)
+#define IRQ_IRDA		S5PC1XX_IRQ_VIC1(18)
+#define IRQ_CAN0		S5PC1XX_IRQ_VIC1(19)
+#define IRQ_CAN1		S5PC1XX_IRQ_VIC1(20)
+#define IRQ_HSIRX		S5PC1XX_IRQ_VIC1(21)
+#define IRQ_HSITX		S5PC1XX_IRQ_VIC1(22)
+#define IRQ_UHOST		S5PC1XX_IRQ_VIC1(23)
+#define IRQ_OTG			S5PC1XX_IRQ_VIC1(24)
+#define IRQ_MSM			S5PC1XX_IRQ_VIC1(25)
+#define IRQ_HSMMC0		S5PC1XX_IRQ_VIC1(26)
+#define IRQ_HSMMC1		S5PC1XX_IRQ_VIC1(27)
+#define IRQ_HSMMC2		S5PC1XX_IRQ_VIC1(28)
+#define IRQ_MIPICSI		S5PC1XX_IRQ_VIC1(29)
+#define IRQ_MIPIDSI		S5PC1XX_IRQ_VIC1(30)
+
+/*
+ * VIC2: multimedia, audio, security
+ */
+#define IRQ_LCD0		S5PC1XX_IRQ_VIC2(0)
+#define IRQ_LCD1		S5PC1XX_IRQ_VIC2(1)
+#define IRQ_LCD2		S5PC1XX_IRQ_VIC2(2)
+#define IRQ_LCD3		S5PC1XX_IRQ_VIC2(3)
+#define IRQ_ROTATOR		S5PC1XX_IRQ_VIC2(4)
+#define IRQ_FIMC0		S5PC1XX_IRQ_VIC2(5)
+#define IRQ_FIMC1		S5PC1XX_IRQ_VIC2(6)
+#define IRQ_FIMC2		S5PC1XX_IRQ_VIC2(7)
+#define IRQ_JPEG		S5PC1XX_IRQ_VIC2(8)
+#define IRQ_2D			S5PC1XX_IRQ_VIC2(9)
+#define IRQ_3D			S5PC1XX_IRQ_VIC2(10)
+#define IRQ_MIXER		S5PC1XX_IRQ_VIC2(11)
+#define IRQ_HDMI		S5PC1XX_IRQ_VIC2(12)
+#define IRQ_IIC1		S5PC1XX_IRQ_VIC2(13)
+#define IRQ_MFC			S5PC1XX_IRQ_VIC2(14)
+#define IRQ_TVENC		S5PC1XX_IRQ_VIC2(15)
+#define IRQ_I2S0		S5PC1XX_IRQ_VIC2(16)
+#define IRQ_I2S1		S5PC1XX_IRQ_VIC2(17)
+#define IRQ_I2S2		S5PC1XX_IRQ_VIC2(18)
+#define IRQ_AC97		S5PC1XX_IRQ_VIC2(19)
+#define IRQ_PCM0		S5PC1XX_IRQ_VIC2(20)
+#define IRQ_PCM1		S5PC1XX_IRQ_VIC2(21)
+#define IRQ_SPDIF		S5PC1XX_IRQ_VIC2(22)
+#define IRQ_ADC			S5PC1XX_IRQ_VIC2(23)
+#define IRQ_PENDN		S5PC1XX_IRQ_VIC2(24)
+#define IRQ_TC			IRQ_PENDN
+#define IRQ_KEYPAD		S5PC1XX_IRQ_VIC2(25)
+#define IRQ_CG			S5PC1XX_IRQ_VIC2(26)
+#define IRQ_SEC			S5PC1XX_IRQ_VIC2(27)
+#define IRQ_SECRX		S5PC1XX_IRQ_VIC2(28)
+#define IRQ_SECTX		S5PC1XX_IRQ_VIC2(29)
+#define IRQ_SDMIRQ		S5PC1XX_IRQ_VIC2(30)
+#define IRQ_SDMFIQ		S5PC1XX_IRQ_VIC2(31)
+
+#define IRQ_TIMER(x)		(IRQ_SDMFIQ + 1 + (x))
+#define IRQ_TIMER0		IRQ_TIMER(0)
+#define IRQ_TIMER1		IRQ_TIMER(1)
+#define IRQ_TIMER2		IRQ_TIMER(2)
+#define IRQ_TIMER3		IRQ_TIMER(3)
+#define IRQ_TIMER4		IRQ_TIMER(4)
+
+/* External interrupt */
+#define S3C_IRQ_EINT_BASE	(IRQ_SDMFIQ + 6)
+
+#define S3C_EINT(x)		(S3C_IRQ_EINT_BASE + (x - 16))
+#define IRQ_EINT(x)		(x < 16 ? IRQ_EINT0 + x : S3C_EINT(x))
+#define IRQ_EINT_BIT(x)		(x < IRQ_EINT16_31 ? x - IRQ_EINT0 : x - S3C_EINT(0))
+
+/* GPIO interrupt */
+#define S3C_IRQ_GPIO_BASE	(IRQ_EINT(31) + 1)
+#define S3C_IRQ_GPIO(x)		(S3C_IRQ_GPIO_BASE + (x))
+
+/*
+ * Until MP04 Groups -> 40 (exactly 39) Groups * 8 ~= 320 GPIOs
+ */
+#define NR_IRQS			(S3C_IRQ_GPIO(320) + 1)
+
+#endif /* __ASM_PLAT_S5PC1XX_IRQS_H */
+
diff --git a/arch/arm/mach-s5pc100/include/plat/regs-gpio.h b/arch/arm/mach-s5pc100/include/plat/regs-gpio.h
new file mode 100644
index 0000000..87e1884
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/plat/regs-gpio.h
@@ -0,0 +1,70 @@
+/* linux/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h
+ *
+ * Copyright 2009 Samsung Electronics Co.
+ *      Byungho Min <bhmin at samsung.com>
+ *
+ * S5PC100 - GPIO register definitions
+ */
+
+#ifndef __ASM_PLAT_S5PC1XX_REGS_GPIO_H
+#define __ASM_PLAT_S5PC1XX_REGS_GPIO_H __FILE__
+
+#include <mach/map.h>
+
+/* S5PC100 */
+#define S5PC100_GPIO_BASE	S5PC1XX_VA_GPIO
+#define S5PC100_GPA0_BASE	(S5PC100_GPIO_BASE + 0x0000)
+#define S5PC100_GPA1_BASE	(S5PC100_GPIO_BASE + 0x0020)
+#define S5PC100_GPB_BASE	(S5PC100_GPIO_BASE + 0x0040)
+#define S5PC100_GPC_BASE	(S5PC100_GPIO_BASE + 0x0060)
+#define S5PC100_GPD_BASE	(S5PC100_GPIO_BASE + 0x0080)
+#define S5PC100_GPE0_BASE	(S5PC100_GPIO_BASE + 0x00A0)
+#define S5PC100_GPE1_BASE	(S5PC100_GPIO_BASE + 0x00C0)
+#define S5PC100_GPF0_BASE	(S5PC100_GPIO_BASE + 0x00E0)
+#define S5PC100_GPF1_BASE	(S5PC100_GPIO_BASE + 0x0100)
+#define S5PC100_GPF2_BASE	(S5PC100_GPIO_BASE + 0x0120)
+#define S5PC100_GPF3_BASE	(S5PC100_GPIO_BASE + 0x0140)
+#define S5PC100_GPG0_BASE	(S5PC100_GPIO_BASE + 0x0160)
+#define S5PC100_GPG1_BASE	(S5PC100_GPIO_BASE + 0x0180)
+#define S5PC100_GPG2_BASE	(S5PC100_GPIO_BASE + 0x01A0)
+#define S5PC100_GPG3_BASE	(S5PC100_GPIO_BASE + 0x01C0)
+#define S5PC100_GPH0_BASE	(S5PC100_GPIO_BASE + 0x0C00)
+#define S5PC100_GPH1_BASE	(S5PC100_GPIO_BASE + 0x0C20)
+#define S5PC100_GPH2_BASE	(S5PC100_GPIO_BASE + 0x0C40)
+#define S5PC100_GPH3_BASE	(S5PC100_GPIO_BASE + 0x0C60)
+#define S5PC100_GPI_BASE	(S5PC100_GPIO_BASE + 0x01E0)
+#define S5PC100_GPJ0_BASE	(S5PC100_GPIO_BASE + 0x0200)
+#define S5PC100_GPJ1_BASE	(S5PC100_GPIO_BASE + 0x0220)
+#define S5PC100_GPJ2_BASE	(S5PC100_GPIO_BASE + 0x0240)
+#define S5PC100_GPJ3_BASE	(S5PC100_GPIO_BASE + 0x0260)
+#define S5PC100_GPJ4_BASE	(S5PC100_GPIO_BASE + 0x0280)
+#define S5PC100_GPK0_BASE	(S5PC100_GPIO_BASE + 0x02A0)
+#define S5PC100_GPK1_BASE	(S5PC100_GPIO_BASE + 0x02C0)
+#define S5PC100_GPK2_BASE	(S5PC100_GPIO_BASE + 0x02E0)
+#define S5PC100_GPK3_BASE	(S5PC100_GPIO_BASE + 0x0300)
+#define S5PC100_GPL0_BASE	(S5PC100_GPIO_BASE + 0x0320)
+#define S5PC100_GPL1_BASE	(S5PC100_GPIO_BASE + 0x0340)
+#define S5PC100_GPL2_BASE	(S5PC100_GPIO_BASE + 0x0360)
+#define S5PC100_GPL3_BASE	(S5PC100_GPIO_BASE + 0x0380)
+#define S5PC100_GPL4_BASE	(S5PC100_GPIO_BASE + 0x03A0)
+#define S5PC100_EINT_BASE	(S5PC100_GPIO_BASE + 0x0E00)
+
+#define S5PC100_UHOST		(S5PC100_GPIO_BASE + 0x0B68)
+#define S5PC100_PDNEN		(S5PC100_GPIO_BASE + 0x0F80)
+
+/* PDNEN */
+#define S5PC100_PDNEN_CFG_PDNEN	(1 << 1)
+#define S5PC100_PDNEN_CFG_AUTO	(0 << 1)
+#define S5PC100_PDNEN_POWERDOWN	(1 << 0)
+#define S5PC100_PDNEN_NORMAL	(0 << 0)
+
+/* Common part */
+/* External interrupt base is same at both s5pc100 and s5pc110 */
+#define S5PC1XX_EINT_BASE	(S5PC100_EINT_BASE)
+
+#define S5PC100_GPx_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S5PC100_GPx_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+#define S5PC100_GPx_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+
+#endif /* __ASM_PLAT_S5PC1XX_REGS_GPIO_H */
+
diff --git a/arch/arm/plat-s5pc1xx/gpiolib.c b/arch/arm/plat-s5pc1xx/gpiolib.c
index facb410..e0eb8e3 100644
--- a/arch/arm/plat-s5pc1xx/gpiolib.c
+++ b/arch/arm/plat-s5pc1xx/gpiolib.c
@@ -3,6 +3,7 @@
  *
  *  Copyright 2009 Samsung Electronics Co
  *  Kyungmin Park <kyungmin.park at samsung.com>
+ *  Marek Szyprowski <m.szyprowski at samsung.com>
  *
  * S5PC1XX - GPIOlib support
  *
@@ -21,46 +22,9 @@
 
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
+#include <plat/gpio-s5pc1xx.h>
 #include <plat/regs-gpio.h>
 
-/* S5PC100 GPIO bank summary:
- *
- * Bank	GPIOs	Style	INT Type
- * A0	8	4Bit	GPIO_INT0
- * A1	5	4Bit	GPIO_INT1
- * B	8	4Bit	GPIO_INT2
- * C	5	4Bit	GPIO_INT3
- * D	7	4Bit	GPIO_INT4
- * E0	8	4Bit	GPIO_INT5
- * E1	6	4Bit	GPIO_INT6
- * F0	8	4Bit	GPIO_INT7
- * F1	8	4Bit	GPIO_INT8
- * F2	8	4Bit	GPIO_INT9
- * F3	4	4Bit	GPIO_INT10
- * G0	8	4Bit	GPIO_INT11
- * G1	3	4Bit	GPIO_INT12
- * G2	7	4Bit	GPIO_INT13
- * G3	7	4Bit	GPIO_INT14
- * H0	8	4Bit	WKUP_INT
- * H1	8	4Bit	WKUP_INT
- * H2	8	4Bit	WKUP_INT
- * H3	8	4Bit	WKUP_INT
- * I	8	4Bit	GPIO_INT15
- * J0	8	4Bit	GPIO_INT16
- * J1	5	4Bit	GPIO_INT17
- * J2	8	4Bit	GPIO_INT18
- * J3	8	4Bit	GPIO_INT19
- * J4	4	4Bit	GPIO_INT20
- * K0	8	4Bit	None
- * K1	6	4Bit	None
- * K2	8	4Bit	None
- * K3	8	4Bit	None
- * L0	8	4Bit	None
- * L1	8	4Bit	None
- * L2	8	4Bit	None
- * L3	8	4Bit	None
- */
-
 #define OFF_GPCON	(0x00)
 #define OFF_GPDAT	(0x04)
 
@@ -138,328 +102,50 @@ static int s5pc1xx_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset)
 {
 	int base;
 
-	base = chip->base - S5PC100_GPH0(0);
+	base = chip->base - S5PC1XX_GPH0(0);
 	if (base == 0)
 		return IRQ_EINT(offset);
-	base = chip->base - S5PC100_GPH1(0);
+	base = chip->base - S5PC1XX_GPH1(0);
 	if (base == 0)
 		return IRQ_EINT(8 + offset);
-	base = chip->base - S5PC100_GPH2(0);
+	base = chip->base - S5PC1XX_GPH2(0);
 	if (base == 0)
 		return IRQ_EINT(16 + offset);
-	base = chip->base - S5PC100_GPH3(0);
+	base = chip->base - S5PC1XX_GPH3(0);
 	if (base == 0)
 		return IRQ_EINT(24 + offset);
+
 	return -EINVAL;
 }
 
-static struct s3c_gpio_cfg gpio_cfg = {
+struct s3c_gpio_cfg s5pc1xx_gpio_cfg = {
 	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
 
-static struct s3c_gpio_cfg gpio_cfg_eint = {
+struct s3c_gpio_cfg s5pc1xx_gpio_cfg_eint = {
 	.cfg_eint	= 0xf,
 	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
 
-static struct s3c_gpio_cfg gpio_cfg_noint = {
+struct s3c_gpio_cfg s5pc1xx_gpio_cfg_noint = {
 	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
 
-static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
-	{
-		.base	= S5PC100_GPA0_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPA0(0),
-			.ngpio	= S5PC100_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.base	= S5PC100_GPA1_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPA1(0),
-			.ngpio	= S5PC100_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.base	= S5PC100_GPB_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPB(0),
-			.ngpio	= S5PC100_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.base	= S5PC100_GPC_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPC(0),
-			.ngpio	= S5PC100_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S5PC100_GPD_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPD(0),
-			.ngpio	= S5PC100_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.base	= S5PC100_GPE0_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPE0(0),
-			.ngpio	= S5PC100_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.base	= S5PC100_GPE1_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPE1(0),
-			.ngpio	= S5PC100_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.base	= S5PC100_GPF0_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPF0(0),
-			.ngpio	= S5PC100_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.base	= S5PC100_GPF1_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPF1(0),
-			.ngpio	= S5PC100_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.base	= S5PC100_GPF2_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPF2(0),
-			.ngpio	= S5PC100_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.base	= S5PC100_GPF3_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPF3(0),
-			.ngpio	= S5PC100_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	}, {
-		.base	= S5PC100_GPG0_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPG0(0),
-			.ngpio	= S5PC100_GPIO_G0_NR,
-			.label	= "GPG0",
-		},
-	}, {
-		.base	= S5PC100_GPG1_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPG1(0),
-			.ngpio	= S5PC100_GPIO_G1_NR,
-			.label	= "GPG1",
-		},
-	}, {
-		.base	= S5PC100_GPG2_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPG2(0),
-			.ngpio	= S5PC100_GPIO_G2_NR,
-			.label	= "GPG2",
-		},
-	}, {
-		.base	= S5PC100_GPG3_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPG3(0),
-			.ngpio	= S5PC100_GPIO_G3_NR,
-			.label	= "GPG3",
-		},
-	}, {
-		.base	= S5PC100_GPH0_BASE,
-		.config	= &gpio_cfg_eint,
-		.chip	= {
-			.base	= S5PC100_GPH0(0),
-			.ngpio	= S5PC100_GPIO_H0_NR,
-			.label	= "GPH0",
-		},
-	}, {
-		.base	= S5PC100_GPH1_BASE,
-		.config	= &gpio_cfg_eint,
-		.chip	= {
-			.base	= S5PC100_GPH1(0),
-			.ngpio	= S5PC100_GPIO_H1_NR,
-			.label	= "GPH1",
-		},
-	}, {
-		.base	= S5PC100_GPH2_BASE,
-		.config	= &gpio_cfg_eint,
-		.chip	= {
-			.base	= S5PC100_GPH2(0),
-			.ngpio	= S5PC100_GPIO_H2_NR,
-			.label	= "GPH2",
-		},
-	}, {
-		.base	= S5PC100_GPH3_BASE,
-		.config	= &gpio_cfg_eint,
-		.chip	= {
-			.base	= S5PC100_GPH3(0),
-			.ngpio	= S5PC100_GPIO_H3_NR,
-			.label	= "GPH3",
-		},
-	}, {
-		.base	= S5PC100_GPI_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPI(0),
-			.ngpio	= S5PC100_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S5PC100_GPJ0_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPJ0(0),
-			.ngpio	= S5PC100_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.base	= S5PC100_GPJ1_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPJ1(0),
-			.ngpio	= S5PC100_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.base	= S5PC100_GPJ2_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPJ2(0),
-			.ngpio	= S5PC100_GPIO_J2_NR,
-			.label	= "GPJ2",
-		},
-	}, {
-		.base	= S5PC100_GPJ3_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPJ3(0),
-			.ngpio	= S5PC100_GPIO_J3_NR,
-			.label	= "GPJ3",
-		},
-	}, {
-		.base	= S5PC100_GPJ4_BASE,
-		.config	= &gpio_cfg,
-		.chip	= {
-			.base	= S5PC100_GPJ4(0),
-			.ngpio	= S5PC100_GPIO_J4_NR,
-			.label	= "GPJ4",
-		},
-	}, {
-		.base	= S5PC100_GPK0_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK0(0),
-			.ngpio	= S5PC100_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.base	= S5PC100_GPK1_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK1(0),
-			.ngpio	= S5PC100_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.base	= S5PC100_GPK2_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK2(0),
-			.ngpio	= S5PC100_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.base	= S5PC100_GPK3_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPK3(0),
-			.ngpio	= S5PC100_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.base	= S5PC100_GPL0_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL0(0),
-			.ngpio	= S5PC100_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.base	= S5PC100_GPL1_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL1(0),
-			.ngpio	= S5PC100_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.base	= S5PC100_GPL2_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL2(0),
-			.ngpio	= S5PC100_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.base	= S5PC100_GPL3_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL3(0),
-			.ngpio	= S5PC100_GPIO_L3_NR,
-			.label	= "GPL3",
-		},
-	}, {
-		.base	= S5PC100_GPL4_BASE,
-		.config	= &gpio_cfg_noint,
-		.chip	= {
-			.base	= S5PC100_GPL4(0),
-			.ngpio	= S5PC100_GPIO_L4_NR,
-			.label	= "GPL4",
-		},
-	},
-};
-
-/* FIXME move from irq-gpio.c */
-extern struct irq_chip s5pc1xx_gpioint;
-extern void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc);
-
-static __init void s5pc1xx_gpiolib_link(struct s3c_gpio_chip *chip)
+static __init void s5pc1xx_gpiolib_link(struct s5pc1xx_gpio_chip *s5pc1xx_chip)
 {
+	struct s3c_gpio_chip *chip = &s5pc1xx_chip->chip;
 	chip->chip.direction_input = s5pc1xx_gpiolib_input;
 	chip->chip.direction_output = s5pc1xx_gpiolib_output;
 	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 
 	/* Interrupt */
-	if (chip->config == &gpio_cfg) {
+	if (chip->config == &s5pc1xx_gpio_cfg) {
 		int i, irq;
 
 		chip->chip.to_irq = s5pc1xx_gpiolib_to_irq;
@@ -471,31 +157,37 @@ static __init void s5pc1xx_gpiolib_link(struct s3c_gpio_chip *chip)
 			set_irq_handler(irq, handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID);
 		}
-	} else if (chip->config == &gpio_cfg_eint)
+
+		if (s5pc1xx_chip->gpio_group >= 0 &&
+		    s5pc1xx_chip->gpio_group < S5PC1XX_GPIO_INT_GROUP_END)
+			s5pc1xx_gpioint_group_map[s5pc1xx_chip->gpio_group] =
+				s5pc1xx_chip->gpio_start;
+
+	} else if (chip->config == &s5pc1xx_gpio_cfg_eint)
 		chip->chip.to_irq = s5pc1xx_gpiolib_to_eint;
 }
 
-static __init void s5pc1xx_gpiolib_add(struct s3c_gpio_chip *chips,
-				       int nr_chips,
-				       void (*fn)(struct s3c_gpio_chip *))
+static __init void s5pc1xx_gpiolib_add(struct s5pc1xx_gpio *chips)
 {
-	for (; nr_chips > 0; nr_chips--, chips++) {
-		if (fn)
-			(fn)(chips);
-		s3c_gpiolib_add(chips);
+	struct s5pc1xx_gpio_chip *chip;
+	int i;
+
+	for (chip = chips->chips; i < chips->count; i++, chip++) {
+		s5pc1xx_gpiolib_link(chip);
+		s3c_gpiolib_add(&chip->chip);
 	}
 }
 
 static __init int s5pc1xx_gpiolib_init(void)
 {
-	struct s3c_gpio_chip *chips;
-	int nr_chips;
+	int i;
 
-		chips = s5pc100_gpio_chips;
-		nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
+	for (i = 0; i < S5PC1XX_GPIO_INT_GROUP_END; i++)
+		s5pc1xx_gpioint_group_map[i] = -1;
 
-	s5pc1xx_gpiolib_add(chips, nr_chips, s5pc1xx_gpiolib_link);
-	/* Interrupt */
+	s5pc1xx_gpiolib_add(&s5pc1xx_gpio_chips);
+
+	/* register gpio interrupt handler */
 	set_irq_chained_handler(IRQ_GPIOINT, s5pc1xx_irq_gpioint_handler);
 
 	return 0;
diff --git a/arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h b/arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h
new file mode 100644
index 0000000..ad7c174
--- /dev/null
+++ b/arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h
@@ -0,0 +1,79 @@
+/* linux/arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h
+ *
+ *  Copyright 2009 Samsung Electronics Co
+ *  Kyungmin Park <kyungmin.park at samsung.com>
+ *  Marek Szyprowski <m.szyprowski at samsung.com>
+ *
+ * GPIOlib support for S5PC1XX
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __GPIO_S5PC1XX_H
+#define __GPIO_S5PC1XX_H __FILE__
+
+struct s5pc1xx_gpio_chip {
+       struct s3c_gpio_chip chip;
+       unsigned int gpio_group;
+       unsigned int gpio_start;
+};
+
+extern struct irq_chip s5pc1xx_gpioint;
+extern int s5pc1xx_gpioint_group_map[S5PC1XX_GPIO_INT_GROUP_END];
+extern void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc);
+
+#define S5PC1XX_CHIP_DEF(plat, bank, cfg) \
+	{ \
+		.base	= plat ## _GP ## bank ## _BASE, \
+		.config	= &cfg, \
+		.chip	= { \
+			.base	= plat ## _GP ## bank(0), \
+			.ngpio	= plat ## _GPIO_ ## bank ## _NR, \
+			.label	= "GP" # bank, \
+		}, \
+	}
+
+#define S5PC1XX_INT_CHIP_DEF(plat, bank) \
+	{ \
+		.chip = S5PC1XX_CHIP_DEF(plat, bank, s5pc1xx_gpio_cfg), \
+		.gpio_start = plat ## _GPIO_## bank ## _START, \
+		.gpio_group = plat ## _GPIO_## bank ## _INT_GROUP, \
+	}
+
+#define S5PC1XX_EINT_CHIP_DEF(plat, bank) \
+	{ \
+		.chip = S5PC1XX_CHIP_DEF(plat, bank, s5pc1xx_gpio_cfg_eint), \
+	}
+
+#define S5PC1XX_NOINT_CHIP_DEF(plat, bank) \
+	{ \
+		.chip = S5PC1XX_CHIP_DEF(plat, bank, s5pc1xx_gpio_cfg_noint), \
+	}
+
+#define S5PC1XX_MP_CHIP_DEF(plat, bank) \
+	{ \
+		.chip = { \
+			.base	= plat ## _ ## bank ## _BASE, \
+			.config	= &s5pc1xx_gpio_cfg_noint, \
+			.chip	= { \
+				.base	= plat ## _ ## bank(0), \
+				.ngpio	= plat ## _GPIO_ ## bank ## _NR, \
+				.label	= "" # bank, \
+			}, \
+		}, \
+	}
+
+extern struct s3c_gpio_cfg s5pc1xx_gpio_cfg;
+extern struct s3c_gpio_cfg s5pc1xx_gpio_cfg_eint;
+extern struct s3c_gpio_cfg s5pc1xx_gpio_cfg_noint;
+
+struct s5pc1xx_gpio {
+	struct s5pc1xx_gpio_chip *chips;
+	int count;
+};
+
+extern struct s5pc1xx_gpio s5pc1xx_gpio_chips;
+
+#endif /* __GPIO_S5PC1XX_H */
diff --git a/arch/arm/plat-s5pc1xx/include/plat/irqs.h b/arch/arm/plat-s5pc1xx/include/plat/irqs.h
deleted file mode 100644
index 409c804..0000000
--- a/arch/arm/plat-s5pc1xx/include/plat/irqs.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/* linux/arch/arm/plat-s5pc1xx/include/plat/irqs.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin at samsung.com>
- *
- * S5PC1XX - Common IRQ support
- *
- * Based on plat-s3c64xx/include/plat/irqs.h
- */
-
-#ifndef __ASM_PLAT_S5PC1XX_IRQS_H
-#define __ASM_PLAT_S5PC1XX_IRQS_H __FILE__
-
-/* we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- * note, since we're using the VICs, our start must be a
- * mulitple of 32 to allow the common code to work
- */
-
-#define S3C_IRQ_OFFSET		(32)
-
-#define S3C_IRQ(x)		((x) + S3C_IRQ_OFFSET)
-
-#define S3C_VIC0_BASE		S3C_IRQ(0)
-#define S3C_VIC1_BASE		S3C_IRQ(32)
-#define S3C_VIC2_BASE		S3C_IRQ(64)
-
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S3CUART_BASE0	(16)
-#define IRQ_S3CUART_BASE1	(20)
-#define IRQ_S3CUART_BASE2	(24)
-#define IRQ_S3CUART_BASE3	(28)
-
-#define UART_IRQ_RXD		(0)
-#define UART_IRQ_ERR		(1)
-#define UART_IRQ_TXD		(2)
-#define UART_IRQ_MODEM		(3)
-
-#define IRQ_S3CUART_RX0		(IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX0		(IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR0	(IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX1		(IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX1		(IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR1	(IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX2		(IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX2		(IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR2	(IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX3		(IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX3		(IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR3	(IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
-
-/* VIC based IRQs */
-
-#define S5PC1XX_IRQ_VIC0(x)	(S3C_VIC0_BASE + (x))
-#define S5PC1XX_IRQ_VIC1(x)	(S3C_VIC1_BASE + (x))
-#define S5PC1XX_IRQ_VIC2(x)	(S3C_VIC2_BASE + (x))
-
-/*
- * VIC0: system, DMA, timer
- */
-#define IRQ_EINT0		S5PC1XX_IRQ_VIC0(0)
-#define IRQ_EINT1		S5PC1XX_IRQ_VIC0(1)
-#define IRQ_EINT2		S5PC1XX_IRQ_VIC0(2)
-#define IRQ_EINT3		S5PC1XX_IRQ_VIC0(3)
-#define IRQ_EINT4		S5PC1XX_IRQ_VIC0(4)
-#define IRQ_EINT5		S5PC1XX_IRQ_VIC0(5)
-#define IRQ_EINT6		S5PC1XX_IRQ_VIC0(6)
-#define IRQ_EINT7		S5PC1XX_IRQ_VIC0(7)
-#define IRQ_EINT8		S5PC1XX_IRQ_VIC0(8)
-#define IRQ_EINT9		S5PC1XX_IRQ_VIC0(9)
-#define IRQ_EINT10		S5PC1XX_IRQ_VIC0(10)
-#define IRQ_EINT11		S5PC1XX_IRQ_VIC0(11)
-#define IRQ_EINT12		S5PC1XX_IRQ_VIC0(12)
-#define IRQ_EINT13		S5PC1XX_IRQ_VIC0(13)
-#define IRQ_EINT14		S5PC1XX_IRQ_VIC0(14)
-#define IRQ_EINT15		S5PC1XX_IRQ_VIC0(15)
-#define IRQ_EINT16_31		S5PC1XX_IRQ_VIC0(16)
-#define IRQ_BATF		S5PC1XX_IRQ_VIC0(17)
-#define IRQ_MDMA		S5PC1XX_IRQ_VIC0(18)
-#define IRQ_PDMA0		S5PC1XX_IRQ_VIC0(19)
-#define IRQ_PDMA1		S5PC1XX_IRQ_VIC0(20)
-#define IRQ_TIMER0_VIC		S5PC1XX_IRQ_VIC0(21)
-#define IRQ_TIMER1_VIC		S5PC1XX_IRQ_VIC0(22)
-#define IRQ_TIMER2_VIC		S5PC1XX_IRQ_VIC0(23)
-#define IRQ_TIMER3_VIC		S5PC1XX_IRQ_VIC0(24)
-#define IRQ_TIMER4_VIC		S5PC1XX_IRQ_VIC0(25)
-#define IRQ_SYSTIMER		S5PC1XX_IRQ_VIC0(26)
-#define IRQ_WDT			S5PC1XX_IRQ_VIC0(27)
-#define IRQ_RTC_ALARM		S5PC1XX_IRQ_VIC0(28)
-#define IRQ_RTC_TIC		S5PC1XX_IRQ_VIC0(29)
-#define IRQ_GPIOINT		S5PC1XX_IRQ_VIC0(30)
-
-/*
- * VIC1: ARM, power, memory, connectivity
- */
-#define IRQ_CORTEX0		S5PC1XX_IRQ_VIC1(0)
-#define IRQ_CORTEX1		S5PC1XX_IRQ_VIC1(1)
-#define IRQ_CORTEX2		S5PC1XX_IRQ_VIC1(2)
-#define IRQ_CORTEX3		S5PC1XX_IRQ_VIC1(3)
-#define IRQ_CORTEX4		S5PC1XX_IRQ_VIC1(4)
-#define IRQ_IEMAPC		S5PC1XX_IRQ_VIC1(5)
-#define IRQ_IEMIEC		S5PC1XX_IRQ_VIC1(6)
-#define IRQ_ONENAND		S5PC1XX_IRQ_VIC1(7)
-#define IRQ_NFC			S5PC1XX_IRQ_VIC1(8)
-#define IRQ_CFC			S5PC1XX_IRQ_VIC1(9)
-#define IRQ_UART0		S5PC1XX_IRQ_VIC1(10)
-#define IRQ_UART1		S5PC1XX_IRQ_VIC1(11)
-#define IRQ_UART2		S5PC1XX_IRQ_VIC1(12)
-#define IRQ_UART3		S5PC1XX_IRQ_VIC1(13)
-#define IRQ_IIC			S5PC1XX_IRQ_VIC1(14)
-#define IRQ_SPI0		S5PC1XX_IRQ_VIC1(15)
-#define IRQ_SPI1		S5PC1XX_IRQ_VIC1(16)
-#define IRQ_SPI2		S5PC1XX_IRQ_VIC1(17)
-#define IRQ_IRDA		S5PC1XX_IRQ_VIC1(18)
-#define IRQ_CAN0		S5PC1XX_IRQ_VIC1(19)
-#define IRQ_CAN1		S5PC1XX_IRQ_VIC1(20)
-#define IRQ_HSIRX		S5PC1XX_IRQ_VIC1(21)
-#define IRQ_HSITX		S5PC1XX_IRQ_VIC1(22)
-#define IRQ_UHOST		S5PC1XX_IRQ_VIC1(23)
-#define IRQ_OTG			S5PC1XX_IRQ_VIC1(24)
-#define IRQ_MSM			S5PC1XX_IRQ_VIC1(25)
-#define IRQ_HSMMC0		S5PC1XX_IRQ_VIC1(26)
-#define IRQ_HSMMC1		S5PC1XX_IRQ_VIC1(27)
-#define IRQ_HSMMC2		S5PC1XX_IRQ_VIC1(28)
-#define IRQ_MIPICSI		S5PC1XX_IRQ_VIC1(29)
-#define IRQ_MIPIDSI		S5PC1XX_IRQ_VIC1(30)
-
-/*
- * VIC2: multimedia, audio, security
- */
-#define IRQ_LCD0		S5PC1XX_IRQ_VIC2(0)
-#define IRQ_LCD1		S5PC1XX_IRQ_VIC2(1)
-#define IRQ_LCD2		S5PC1XX_IRQ_VIC2(2)
-#define IRQ_LCD3		S5PC1XX_IRQ_VIC2(3)
-#define IRQ_ROTATOR		S5PC1XX_IRQ_VIC2(4)
-#define IRQ_FIMC0		S5PC1XX_IRQ_VIC2(5)
-#define IRQ_FIMC1		S5PC1XX_IRQ_VIC2(6)
-#define IRQ_FIMC2		S5PC1XX_IRQ_VIC2(7)
-#define IRQ_JPEG		S5PC1XX_IRQ_VIC2(8)
-#define IRQ_2D			S5PC1XX_IRQ_VIC2(9)
-#define IRQ_3D			S5PC1XX_IRQ_VIC2(10)
-#define IRQ_MIXER		S5PC1XX_IRQ_VIC2(11)
-#define IRQ_HDMI		S5PC1XX_IRQ_VIC2(12)
-#define IRQ_IIC1		S5PC1XX_IRQ_VIC2(13)
-#define IRQ_MFC			S5PC1XX_IRQ_VIC2(14)
-#define IRQ_TVENC		S5PC1XX_IRQ_VIC2(15)
-#define IRQ_I2S0		S5PC1XX_IRQ_VIC2(16)
-#define IRQ_I2S1		S5PC1XX_IRQ_VIC2(17)
-#define IRQ_I2S2		S5PC1XX_IRQ_VIC2(18)
-#define IRQ_AC97		S5PC1XX_IRQ_VIC2(19)
-#define IRQ_PCM0		S5PC1XX_IRQ_VIC2(20)
-#define IRQ_PCM1		S5PC1XX_IRQ_VIC2(21)
-#define IRQ_SPDIF		S5PC1XX_IRQ_VIC2(22)
-#define IRQ_ADC			S5PC1XX_IRQ_VIC2(23)
-#define IRQ_PENDN		S5PC1XX_IRQ_VIC2(24)
-#define IRQ_TC			IRQ_PENDN
-#define IRQ_KEYPAD		S5PC1XX_IRQ_VIC2(25)
-#define IRQ_CG			S5PC1XX_IRQ_VIC2(26)
-#define IRQ_SEC			S5PC1XX_IRQ_VIC2(27)
-#define IRQ_SECRX		S5PC1XX_IRQ_VIC2(28)
-#define IRQ_SECTX		S5PC1XX_IRQ_VIC2(29)
-#define IRQ_SDMIRQ		S5PC1XX_IRQ_VIC2(30)
-#define IRQ_SDMFIQ		S5PC1XX_IRQ_VIC2(31)
-
-#define IRQ_TIMER(x)		(IRQ_SDMFIQ + 1 + (x))
-#define IRQ_TIMER0		IRQ_TIMER(0)
-#define IRQ_TIMER1		IRQ_TIMER(1)
-#define IRQ_TIMER2		IRQ_TIMER(2)
-#define IRQ_TIMER3		IRQ_TIMER(3)
-#define IRQ_TIMER4		IRQ_TIMER(4)
-
-/* External interrupt */
-#define S3C_IRQ_EINT_BASE	(IRQ_SDMFIQ + 6)
-
-#define S3C_EINT(x)		(S3C_IRQ_EINT_BASE + (x - 16))
-#define IRQ_EINT(x)		(x < 16 ? IRQ_EINT0 + x : S3C_EINT(x))
-#define IRQ_EINT_BIT(x)		(x < IRQ_EINT16_31 ? x - IRQ_EINT0 : x - S3C_EINT(0))
-
-/* GPIO interrupt */
-#define S3C_IRQ_GPIO_BASE	(IRQ_EINT(31) + 1)
-#define S3C_IRQ_GPIO(x)		(S3C_IRQ_GPIO_BASE + (x))
-
-/*
- * Until MP04 Groups -> 40 (exactly 39) Groups * 8 ~= 320 GPIOs
- */
-#define NR_IRQS			(S3C_IRQ_GPIO(320) + 1)
-
-#endif /* __ASM_PLAT_S5PC1XX_IRQS_H */
-
diff --git a/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h b/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h
deleted file mode 100644
index 43c7bc8..0000000
--- a/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin at samsung.com>
- *
- * S5PC1XX - GPIO register definitions
- */
-
-#ifndef __ASM_PLAT_S5PC1XX_REGS_GPIO_H
-#define __ASM_PLAT_S5PC1XX_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-
-/* S5PC100 */
-#define S5PC100_GPIO_BASE	S5PC1XX_VA_GPIO
-#define S5PC100_GPA0_BASE	(S5PC100_GPIO_BASE + 0x0000)
-#define S5PC100_GPA1_BASE	(S5PC100_GPIO_BASE + 0x0020)
-#define S5PC100_GPB_BASE	(S5PC100_GPIO_BASE + 0x0040)
-#define S5PC100_GPC_BASE	(S5PC100_GPIO_BASE + 0x0060)
-#define S5PC100_GPD_BASE	(S5PC100_GPIO_BASE + 0x0080)
-#define S5PC100_GPE0_BASE	(S5PC100_GPIO_BASE + 0x00A0)
-#define S5PC100_GPE1_BASE	(S5PC100_GPIO_BASE + 0x00C0)
-#define S5PC100_GPF0_BASE	(S5PC100_GPIO_BASE + 0x00E0)
-#define S5PC100_GPF1_BASE	(S5PC100_GPIO_BASE + 0x0100)
-#define S5PC100_GPF2_BASE	(S5PC100_GPIO_BASE + 0x0120)
-#define S5PC100_GPF3_BASE	(S5PC100_GPIO_BASE + 0x0140)
-#define S5PC100_GPG0_BASE	(S5PC100_GPIO_BASE + 0x0160)
-#define S5PC100_GPG1_BASE	(S5PC100_GPIO_BASE + 0x0180)
-#define S5PC100_GPG2_BASE	(S5PC100_GPIO_BASE + 0x01A0)
-#define S5PC100_GPG3_BASE	(S5PC100_GPIO_BASE + 0x01C0)
-#define S5PC100_GPH0_BASE	(S5PC100_GPIO_BASE + 0x0C00)
-#define S5PC100_GPH1_BASE	(S5PC100_GPIO_BASE + 0x0C20)
-#define S5PC100_GPH2_BASE	(S5PC100_GPIO_BASE + 0x0C40)
-#define S5PC100_GPH3_BASE	(S5PC100_GPIO_BASE + 0x0C60)
-#define S5PC100_GPI_BASE	(S5PC100_GPIO_BASE + 0x01E0)
-#define S5PC100_GPJ0_BASE	(S5PC100_GPIO_BASE + 0x0200)
-#define S5PC100_GPJ1_BASE	(S5PC100_GPIO_BASE + 0x0220)
-#define S5PC100_GPJ2_BASE	(S5PC100_GPIO_BASE + 0x0240)
-#define S5PC100_GPJ3_BASE	(S5PC100_GPIO_BASE + 0x0260)
-#define S5PC100_GPJ4_BASE	(S5PC100_GPIO_BASE + 0x0280)
-#define S5PC100_GPK0_BASE	(S5PC100_GPIO_BASE + 0x02A0)
-#define S5PC100_GPK1_BASE	(S5PC100_GPIO_BASE + 0x02C0)
-#define S5PC100_GPK2_BASE	(S5PC100_GPIO_BASE + 0x02E0)
-#define S5PC100_GPK3_BASE	(S5PC100_GPIO_BASE + 0x0300)
-#define S5PC100_GPL0_BASE	(S5PC100_GPIO_BASE + 0x0320)
-#define S5PC100_GPL1_BASE	(S5PC100_GPIO_BASE + 0x0340)
-#define S5PC100_GPL2_BASE	(S5PC100_GPIO_BASE + 0x0360)
-#define S5PC100_GPL3_BASE	(S5PC100_GPIO_BASE + 0x0380)
-#define S5PC100_GPL4_BASE	(S5PC100_GPIO_BASE + 0x03A0)
-#define S5PC100_EINT_BASE	(S5PC100_GPIO_BASE + 0x0E00)
-
-#define S5PC100_UHOST		(S5PC100_GPIO_BASE + 0x0B68)
-#define S5PC100_PDNEN		(S5PC100_GPIO_BASE + 0x0F80)
-
-/* PDNEN */
-#define S5PC100_PDNEN_CFG_PDNEN	(1 << 1)
-#define S5PC100_PDNEN_CFG_AUTO	(0 << 1)
-#define S5PC100_PDNEN_POWERDOWN	(1 << 0)
-#define S5PC100_PDNEN_NORMAL	(0 << 0)
-
-/* Common part */
-/* External interrupt base is same at both s5pc100 and s5pc110 */
-#define S5PC1XX_EINT_BASE	(S5PC100_EINT_BASE)
-
-#define S5PC100_GPx_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S5PC100_GPx_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-#define S5PC100_GPx_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-
-#endif /* __ASM_PLAT_S5PC1XX_REGS_GPIO_H */
-
diff --git a/arch/arm/plat-s5pc1xx/irq-eint.c b/arch/arm/plat-s5pc1xx/irq-eint.c
index 373122f..9e8bc12 100644
--- a/arch/arm/plat-s5pc1xx/irq-eint.c
+++ b/arch/arm/plat-s5pc1xx/irq-eint.c
@@ -105,7 +105,7 @@ static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
 {
 	u32 bank = s3c_get_bank(irq);
 	int real = s3c_get_eint(irq);
-	int gpio, shift, sfn;
+	int gpio, shift;
 	u32 ctrl, con = 0;
 
 	switch (type) {
@@ -148,23 +148,22 @@ static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
 
 	switch (real) {
 	case 0 ... 7:
-			gpio = S5PC100_GPH0(gpio);
+		gpio = S5PC1XX_GPH0(gpio);
 		break;
 	case 8 ... 15:
-			gpio = S5PC100_GPH1(gpio);
+		gpio = S5PC1XX_GPH1(gpio);
 		break;
 	case 16 ... 23:
-			gpio = S5PC100_GPH2(gpio);
+		gpio = S5PC1XX_GPH2(gpio);
 		break;
 	case 24 ... 31:
-			gpio = S5PC100_GPH3(gpio);
+		gpio = S5PC1XX_GPH3(gpio);
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	sfn = S3C_GPIO_SFN(0x2);
-	s3c_gpio_cfgpin(gpio, sfn);
+	s3c_gpio_cfgpin(gpio, S5PC1XX_GPIO_EINT_SFN);
 
 	return 0;
 }
diff --git a/arch/arm/plat-s5pc1xx/irq-gpio.c b/arch/arm/plat-s5pc1xx/irq-gpio.c
index fecca7a..117cb8d 100644
--- a/arch/arm/plat-s5pc1xx/irq-gpio.c
+++ b/arch/arm/plat-s5pc1xx/irq-gpio.c
@@ -17,7 +17,9 @@
 #include <linux/gpio.h>
 
 #include <mach/map.h>
+#include <mach/gpio-core.h>
 #include <plat/gpio-cfg.h>
+#include <plat/gpio-s5pc1xx.h>
 
 #define S5PC1XX_GPIOREG(x)		(S5PC1XX_VA_GPIO + (x))
 
@@ -49,88 +51,19 @@ static int group_to_pend_offset(int group)
 	return group << 2;
 }
 
-static int s5pc1xx_get_start(unsigned int group)
-{
-	switch (group) {
-	case 0: return S5PC100_GPIO_A0_START;
-	case 1: return S5PC100_GPIO_A1_START;
-	case 2: return S5PC100_GPIO_B_START;
-	case 3: return S5PC100_GPIO_C_START;
-	case 4: return S5PC100_GPIO_D_START;
-	case 5: return S5PC100_GPIO_E0_START;
-	case 6: return S5PC100_GPIO_E1_START;
-	case 7: return S5PC100_GPIO_F0_START;
-	case 8: return S5PC100_GPIO_F1_START;
-	case 9: return S5PC100_GPIO_F2_START;
-	case 10: return S5PC100_GPIO_F3_START;
-	case 11: return S5PC100_GPIO_G0_START;
-	case 12: return S5PC100_GPIO_G1_START;
-	case 13: return S5PC100_GPIO_G2_START;
-	case 14: return S5PC100_GPIO_G3_START;
-	case 15: return S5PC100_GPIO_I_START;
-	case 16: return S5PC100_GPIO_J0_START;
-	case 17: return S5PC100_GPIO_J1_START;
-	case 18: return S5PC100_GPIO_J2_START;
-	case 19: return S5PC100_GPIO_J3_START;
-	case 20: return S5PC100_GPIO_J4_START;
-	default:
-		BUG();
-	}
-
-	return -EINVAL;
-}
-
 static int s5pc1xx_get_group(unsigned int irq)
 {
-	irq -= S3C_IRQ_GPIO(0);
-
-	switch (irq) {
-	case S5PC100_GPIO_A0_START ... S5PC100_GPIO_A1_START - 1:
-		return 0;
-	case S5PC100_GPIO_A1_START ... S5PC100_GPIO_B_START - 1:
-		return 1;
-	case S5PC100_GPIO_B_START ... S5PC100_GPIO_C_START - 1:
-		return 2;
-	case S5PC100_GPIO_C_START ... S5PC100_GPIO_D_START - 1:
-		return 3;
-	case S5PC100_GPIO_D_START ... S5PC100_GPIO_E0_START - 1:
-		return 4;
-	case S5PC100_GPIO_E0_START ... S5PC100_GPIO_E1_START - 1:
-		return 5;
-	case S5PC100_GPIO_E1_START ... S5PC100_GPIO_F0_START - 1:
-		return 6;
-	case S5PC100_GPIO_F0_START ... S5PC100_GPIO_F1_START - 1:
-		return 7;
-	case S5PC100_GPIO_F1_START ... S5PC100_GPIO_F2_START - 1:
-		return 8;
-	case S5PC100_GPIO_F2_START ... S5PC100_GPIO_F3_START - 1:
-		return 9;
-	case S5PC100_GPIO_F3_START ... S5PC100_GPIO_G0_START - 1:
-		return 10;
-	case S5PC100_GPIO_G0_START ... S5PC100_GPIO_G1_START - 1:
-		return 11;
-	case S5PC100_GPIO_G1_START ... S5PC100_GPIO_G2_START - 1:
-		return 12;
-	case S5PC100_GPIO_G2_START ... S5PC100_GPIO_G3_START - 1:
-		return 13;
-	case S5PC100_GPIO_G3_START ... S5PC100_GPIO_H0_START - 1:
-		return 14;
-	case S5PC100_GPIO_I_START ... S5PC100_GPIO_J0_START - 1:
-		return 15;
-	case S5PC100_GPIO_J0_START ... S5PC100_GPIO_J1_START - 1:
-		return 16;
-	case S5PC100_GPIO_J1_START ... S5PC100_GPIO_J2_START - 1:
-		return 17;
-	case S5PC100_GPIO_J2_START ... S5PC100_GPIO_J3_START - 1:
-		return 18;
-	case S5PC100_GPIO_J3_START ... S5PC100_GPIO_J4_START - 1:
-		return 19;
-	case S5PC100_GPIO_J4_START ... S5PC100_GPIO_K0_START - 1:
-		return 20;
-	default:
-		BUG();
-	}
-
+	struct gpio_chip *chip = get_irq_data(irq);
+	struct s3c_gpio_chip *s3c_chip = container_of(chip,
+					 struct s3c_gpio_chip, chip);
+	struct s5pc1xx_gpio_chip *s5pc1xx_chip = container_of(s3c_chip,
+						 struct s5pc1xx_gpio_chip,
+						 chip);
+
+	if (s5pc1xx_chip->gpio_group >= 0 &&
+	    s5pc1xx_chip->gpio_group < S5PC1XX_GPIO_INT_GROUP_END)
+		return s5pc1xx_chip->gpio_group;
+	BUG();
 	return -EINVAL;
 }
 
@@ -220,7 +153,6 @@ static int s5pc1xx_gpioint_set_type(unsigned int irq, unsigned int type)
 		BUG();
 	}
 
-
 	value = __raw_readl(S5PC1XX_GPIOREG(CON_OFFSET) + con_offset);
 	value &= ~(0xf << (offset * 0x4));
 	value |= (type << (offset * 0x4));
@@ -238,15 +170,15 @@ struct irq_chip s5pc1xx_gpioint = {
 	.set_type	= s5pc1xx_gpioint_set_type,
 };
 
+int s5pc1xx_gpioint_group_map[S5PC1XX_GPIO_INT_GROUP_END];
+
 void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 {
 	int group, offset, pend_offset, mask_offset;
-	int real_irq, group_end;
+	int real_irq;
 	unsigned int pend, mask;
 
-	group_end = 21;
-
-	for (group = 0; group < group_end; group++) {
+	for (group = 0; group < S5PC1XX_GPIO_INT_GROUP_END; group++) {
 		pend_offset = group_to_pend_offset(group);
 		pend = __raw_readl(S5PC1XX_GPIOREG(PEND_OFFSET) + pend_offset);
 		if (!pend)
@@ -258,7 +190,8 @@ void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 
 		for (offset = 0; offset < 8; offset++) {
 			if (pend & (1 << offset)) {
-				real_irq = s5pc1xx_get_start(group) + offset;
+				real_irq = s5pc1xx_gpioint_group_map[group] +
+					   offset;
 				generic_handle_irq(S3C_IRQ_GPIO(real_irq));
 			}
 		}
-- 
1.6.4




More information about the linux-arm-kernel mailing list