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

Marek Szyprowski m.szyprowski at samsung.com
Fri Nov 20 08:42:36 EST 2009


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 +++
 .../include/plat/irqs.h                            |    2 +-
 .../include/plat/regs-gpio.h                       |    2 +-
 arch/arm/plat-s5pc1xx/gpiolib.c                    |  374 ++------------------
 arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.h  |   79 ++++
 arch/arm/plat-s5pc1xx/irq-eint.c                   |   13 +-
 arch/arm/plat-s5pc1xx/irq-gpio.c                   |  105 +-----
 9 files changed, 292 insertions(+), 436 deletions(-)
 create mode 100644 arch/arm/mach-s5pc100/gpio-chips.c
 rename arch/arm/{plat-s5pc1xx => mach-s5pc100}/include/plat/irqs.h (99%)
 rename arch/arm/{plat-s5pc1xx => mach-s5pc100}/include/plat/regs-gpio.h (98%)
 create mode 100644 arch/arm/plat-s5pc1xx/include/plat/gpio-s5pc1xx.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/plat-s5pc1xx/include/plat/irqs.h b/arch/arm/mach-s5pc100/include/plat/irqs.h
similarity index 99%
rename from arch/arm/plat-s5pc1xx/include/plat/irqs.h
rename to arch/arm/mach-s5pc100/include/plat/irqs.h
index ef87363..e34e2ef 100644
--- a/arch/arm/plat-s5pc1xx/include/plat/irqs.h
+++ b/arch/arm/mach-s5pc100/include/plat/irqs.h
@@ -3,7 +3,7 @@
  * Copyright 2009 Samsung Electronics Co.
  *      Byungho Min <bhmin at samsung.com>
  *
- * S5PC1XX - Common IRQ support
+ * S5PC100 - Common IRQ support
  *
  * Based on plat-s3c64xx/include/plat/irqs.h
  */
diff --git a/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h b/arch/arm/mach-s5pc100/include/plat/regs-gpio.h
similarity index 98%
rename from arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h
rename to arch/arm/mach-s5pc100/include/plat/regs-gpio.h
index 43c7bc8..87e1884 100644
--- a/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h
+++ b/arch/arm/mach-s5pc100/include/plat/regs-gpio.h
@@ -3,7 +3,7 @@
  * Copyright 2009 Samsung Electronics Co.
  *      Byungho Min <bhmin at samsung.com>
  *
- * S5PC1XX - GPIO register definitions
+ * S5PC100 - GPIO register definitions
  */
 
 #ifndef __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/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