linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update
@ 2011-02-17  7:25 Marek Szyprowski
  2011-02-17  7:25 ` [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks Marek Szyprowski
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-17  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

This patch series perform an update on interrupts support for
S5PC210/S5PV310/EXYNOS4 platform. Two optional features have been added.
The first one is GPIO interrupts handler, a second is support for board
specific interrupts. The patches have been prepared to maximise the code
reuse, so common code for gpio interrupts for s5pc100, s5pc110 & s5pc210
have been prepared.

The patches have been prepared against
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
for-next branch (commit 857ddb87db).

Patches that make use of these 2 optional features for universal c210
board will follow soon.

Best regards
--
Marek Szyprowski
Samsung Poland R&D Center



Patch summary:

Marek Szyprowski (5):
  ARM: S5PV310: Add missing GPYx banks.
  ARM: Samsung: cleanup S5P gpio interrupt code
  ARM: Samsung: add function to register gpio interrupt bank data
  ARM: S5PC210: add support for gpio interrupts
  ARM: S5PC210: add a placeholder for board specific interrupts

 arch/arm/mach-s5pc100/gpiolib.c               |    1 +
 arch/arm/mach-s5pv210/gpiolib.c               |    1 +
 arch/arm/mach-s5pv310/gpiolib.c               |   67 ++++++++++-
 arch/arm/mach-s5pv310/include/mach/gpio.h     |   23 ++++-
 arch/arm/mach-s5pv310/include/mach/irqs.h     |   16 ++-
 arch/arm/plat-s5p/irq-gpioint.c               |  169 +++++++++++++++----------
 arch/arm/plat-samsung/include/plat/gpio-cfg.h |   16 +++
 7 files changed, 220 insertions(+), 73 deletions(-)

-- 
1.7.1.569.g6f426

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks.
  2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
@ 2011-02-17  7:25 ` Marek Szyprowski
  2011-02-23  6:57   ` Kukjin Kim
  2011-02-17  7:25 ` [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code Marek Szyprowski
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-17  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds missing GPYx gpio banks on Samsung S5PC210 platform.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv310/gpiolib.c           |   49 +++++++++++++++++++++++++++++
 arch/arm/mach-s5pv310/include/mach/gpio.h |   23 +++++++++++++-
 2 files changed, 71 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-s5pv310/gpiolib.c
index 55217b8..f417ecd 100644
--- a/arch/arm/mach-s5pv310/gpiolib.c
+++ b/arch/arm/mach-s5pv310/gpiolib.c
@@ -199,6 +199,55 @@ static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[] = {
 			.label	= "GPL2",
 		},
 	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY0(0),
+			.ngpio	= S5PV310_GPIO_Y0_NR,
+			.label	= "GPY0",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY1(0),
+			.ngpio	= S5PV310_GPIO_Y1_NR,
+			.label	= "GPY1",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY2(0),
+			.ngpio	= S5PV310_GPIO_Y2_NR,
+			.label	= "GPY2",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY3(0),
+			.ngpio	= S5PV310_GPIO_Y3_NR,
+			.label	= "GPY3",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY4(0),
+			.ngpio	= S5PV310_GPIO_Y4_NR,
+			.label	= "GPY4",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY5(0),
+			.ngpio	= S5PV310_GPIO_Y5_NR,
+			.label	= "GPY5",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV310_GPY6(0),
+			.ngpio	= S5PV310_GPIO_Y6_NR,
+			.label	= "GPY6",
+		},
+	}, {
 		.base	= (S5P_VA_GPIO2 + 0xC00),
 		.config	= &gpio_cfg_noint,
 		.irq_base = IRQ_EINT(0),
diff --git a/arch/arm/mach-s5pv310/include/mach/gpio.h b/arch/arm/mach-s5pv310/include/mach/gpio.h
index 20cb80c..4b44463 100644
--- a/arch/arm/mach-s5pv310/include/mach/gpio.h
+++ b/arch/arm/mach-s5pv310/include/mach/gpio.h
@@ -50,6 +50,13 @@
 #define S5PV310_GPIO_X1_NR	(8)
 #define S5PV310_GPIO_X2_NR	(8)
 #define S5PV310_GPIO_X3_NR	(8)
+#define S5PV310_GPIO_Y0_NR	(6)
+#define S5PV310_GPIO_Y1_NR	(4)
+#define S5PV310_GPIO_Y2_NR	(6)
+#define S5PV310_GPIO_Y3_NR	(8)
+#define S5PV310_GPIO_Y4_NR	(8)
+#define S5PV310_GPIO_Y5_NR	(8)
+#define S5PV310_GPIO_Y6_NR	(8)
 #define S5PV310_GPIO_Z_NR	(7)
 
 /* GPIO bank numbers */
@@ -87,7 +94,14 @@ enum s5p_gpio_number {
 	S5PV310_GPIO_X1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
 	S5PV310_GPIO_X2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
 	S5PV310_GPIO_X3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
-	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
+	S5PV310_GPIO_Y0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
+	S5PV310_GPIO_Y1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y0),
+	S5PV310_GPIO_Y2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y1),
+	S5PV310_GPIO_Y3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y2),
+	S5PV310_GPIO_Y4_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y3),
+	S5PV310_GPIO_Y5_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y4),
+	S5PV310_GPIO_Y6_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y5),
+	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y6),
 };
 
 /* S5PV310 GPIO number definitions */
@@ -120,6 +134,13 @@ enum s5p_gpio_number {
 #define S5PV310_GPX1(_nr)	(S5PV310_GPIO_X1_START + (_nr))
 #define S5PV310_GPX2(_nr)	(S5PV310_GPIO_X2_START + (_nr))
 #define S5PV310_GPX3(_nr)	(S5PV310_GPIO_X3_START + (_nr))
+#define S5PV310_GPY0(_nr)	(S5PV310_GPIO_Y0_START + (_nr))
+#define S5PV310_GPY1(_nr)	(S5PV310_GPIO_Y1_START + (_nr))
+#define S5PV310_GPY2(_nr)	(S5PV310_GPIO_Y2_START + (_nr))
+#define S5PV310_GPY3(_nr)	(S5PV310_GPIO_Y3_START + (_nr))
+#define S5PV310_GPY4(_nr)	(S5PV310_GPIO_Y4_START + (_nr))
+#define S5PV310_GPY5(_nr)	(S5PV310_GPIO_Y5_START + (_nr))
+#define S5PV310_GPY6(_nr)	(S5PV310_GPIO_Y6_START + (_nr))
 #define S5PV310_GPZ(_nr)	(S5PV310_GPIO_Z_START + (_nr))
 
 /* the end of the S5PV310 specific gpios */
-- 
1.7.1.569.g6f426

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code
  2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
  2011-02-17  7:25 ` [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks Marek Szyprowski
@ 2011-02-17  7:25 ` Marek Szyprowski
  2011-02-23 10:15   ` Kukjin Kim
  2011-02-17  7:25 ` [PATCH 3/5] ARM: Samsung: add function to register gpio interrupt bank data Marek Szyprowski
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-17  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

This patch performs a global cleanup in s5p gpio interrupt support code.
The code is prepared for upcoming support for gpio interrupts on S5PC210
platform, which has 2 gpio banks (regions) instead of one (like on
S5PC110 and S5PC100).

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/plat-s5p/irq-gpioint.c |  106 +++++++++++++++++----------------------
 1 files changed, 46 insertions(+), 60 deletions(-)

diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index 3b6bf89..af10328 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -22,77 +22,64 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 
-#define S5P_GPIOREG(x)			(S5P_VA_GPIO + (x))
+#define GPIO_BASE(chip)		(((unsigned long)(chip)->base) & ~(SZ_4K - 1))
 
-#define GPIOINT_CON_OFFSET		0x700
-#define GPIOINT_MASK_OFFSET		0x900
-#define GPIOINT_PEND_OFFSET		0xA00
+#define CON_OFFSET		0x700
+#define MASK_OFFSET		0x900
+#define PEND_OFFSET		0xA00
+#define REG_OFFSET(x)		((x) << 2)
 
 static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
 
-static int s5p_gpioint_get_group(struct irq_data *data)
-{
-	struct gpio_chip *chip = irq_data_get_irq_data(data);
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-	int group;
-
-	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++)
-		if (s3c_chip == irq_chips[group])
-			break;
-
-	return group;
-}
-
 static int s5p_gpioint_get_offset(struct irq_data *data)
 {
-	struct gpio_chip *chip = irq_data_get_irq_data(data);
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-
-	return data->irq - s3c_chip->irq_base;
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+	return data->irq - chip->irq_base;
 }
 
 static void s5p_gpioint_ack(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, pend_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	pend_offset = group << 2;
+	pend_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
-	value |= 1 << offset;
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
+	value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
+	value |= BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
 }
 
 static void s5p_gpioint_mask(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	mask_offset = group << 2;
+	mask_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
-	value |= 1 << offset;
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
+	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
+	value |= BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 }
 
 static void s5p_gpioint_unmask(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	mask_offset = group << 2;
+	mask_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
-	value &= ~(1 << offset);
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
+	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
+	value &= ~BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 }
 
 static void s5p_gpioint_mask_ack(struct irq_data *data)
@@ -103,12 +90,13 @@ static void s5p_gpioint_mask_ack(struct irq_data *data)
 
 static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, con_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	con_offset = group << 2;
+	con_offset = REG_OFFSET(group);
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -132,15 +120,15 @@ static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 		return -EINVAL;
 	}
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
+	value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset);
 	value &= ~(0x7 << (offset * 0x4));
 	value |= (type << (offset * 0x4));
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
+	__raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);
 
 	return 0;
 }
 
-struct irq_chip s5p_gpioint = {
+static struct irq_chip s5p_gpioint = {
 	.name		= "s5p_gpioint",
 	.irq_ack	= s5p_gpioint_ack,
 	.irq_mask	= s5p_gpioint_mask,
@@ -151,30 +139,28 @@ struct irq_chip s5p_gpioint = {
 
 static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 {
-	int group, offset, pend_offset, mask_offset;
-	int real_irq;
+	int group, pend_offset, mask_offset;
 	unsigned int pend, mask;
 
 	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
-		pend_offset = group << 2;
-		pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) +
-				pend_offset);
+		struct s3c_gpio_chip *chip = irq_chips[group];
+		if (!chip)
+			continue;
+
+		pend_offset = REG_OFFSET(group);
+		pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
 		if (!pend)
 			continue;
 
-		mask_offset = group << 2;
-		mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) +
-				mask_offset);
+		mask_offset = REG_OFFSET(group);
+		mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 		pend &= ~mask;
 
-		for (offset = 0; offset < 8; offset++) {
-			if (pend & (1 << offset)) {
-				struct s3c_gpio_chip *chip = irq_chips[group];
-				if (chip) {
-					real_irq = chip->irq_base + offset;
-					generic_handle_irq(real_irq);
-				}
-			}
+		while (pend) {
+			int offset = fls(pend) - 1;
+			int real_irq = chip->irq_base + offset;
+			generic_handle_irq(real_irq);
+			pend &= ~BIT(offset);
 		}
 	}
 }
@@ -202,7 +188,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
 	for (i = 0; i < chip->chip.ngpio; i++) {
 		irq = chip->irq_base + i;
 		set_irq_chip(irq, &s5p_gpioint);
-		set_irq_data(irq, &chip->chip);
+		set_irq_data(irq, chip);
 		set_irq_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
-- 
1.7.1.569.g6f426

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/5] ARM: Samsung: add function to register gpio interrupt bank data
  2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
  2011-02-17  7:25 ` [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks Marek Szyprowski
  2011-02-17  7:25 ` [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code Marek Szyprowski
@ 2011-02-17  7:25 ` Marek Szyprowski
  2011-02-17  7:25 ` [PATCH 4/5] ARM: S5PC210: add support for gpio interrupts Marek Szyprowski
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-17  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

This patch removes all global data from common s5p gpio interrupt
handler code. This enables to reuse this code on S5PC210 platform.
Instead of global data (IRQ_GPIOINT interrupt number,
S5P_GPIOINT_GROUP_MAXNR groups count), a s5p_register_gpioint_bank()
function is introduced. It is aimed to be called from gpiolib init.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pc100/gpiolib.c               |    1 +
 arch/arm/mach-s5pv210/gpiolib.c               |    1 +
 arch/arm/plat-s5p/irq-gpioint.c               |   69 +++++++++++++++++++++----
 arch/arm/plat-samsung/include/plat/gpio-cfg.h |   16 ++++++
 4 files changed, 77 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c
index 20856eb..2842394 100644
--- a/arch/arm/mach-s5pc100/gpiolib.c
+++ b/arch/arm/mach-s5pc100/gpiolib.c
@@ -348,6 +348,7 @@ static __init int s5pc100_gpiolib_init(void)
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 
 	return 0;
 }
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c
index ab673ef..1ba20a7 100644
--- a/arch/arm/mach-s5pv210/gpiolib.c
+++ b/arch/arm/mach-s5pv210/gpiolib.c
@@ -281,6 +281,7 @@ static __init int s5pv210_gpiolib_init(void)
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 
 	return 0;
 }
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index af10328..70329e6 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/slab.h>
 
 #include <mach/map.h>
 #include <plat/gpio-core.h>
@@ -29,7 +30,17 @@
 #define PEND_OFFSET		0xA00
 #define REG_OFFSET(x)		((x) << 2)
 
-static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
+struct s5p_gpioint_bank
+{
+	struct list_head	list;
+	int			start;
+	int			nr_groups;
+	int			irq;
+	struct s3c_gpio_chip	**chips;
+	void			(*handler)(unsigned int, struct irq_desc *);
+};
+
+LIST_HEAD(banks);
 
 static int s5p_gpioint_get_offset(struct irq_data *data)
 {
@@ -139,11 +150,12 @@ static struct irq_chip s5p_gpioint = {
 
 static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 {
+	struct s5p_gpioint_bank *bank = get_irq_data(irq);
 	int group, pend_offset, mask_offset;
 	unsigned int pend, mask;
 
-	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
-		struct s3c_gpio_chip *chip = irq_chips[group];
+	for (group = 0; group < bank->nr_groups; group++) {
+		struct s3c_gpio_chip *chip = bank->chips[group];
 		if (!chip)
 			continue;
 
@@ -168,23 +180,44 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
 {
 	static int used_gpioint_groups = 0;
-	static bool handler_registered = 0;
 	int irq, group = chip->group;
 	int i;
+	struct s5p_gpioint_bank *bank = NULL;
 
 	if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
 		return -ENOMEM;
 
+	list_for_each_entry(bank, &banks, list) {
+		if (group >= bank->start &&
+		    group < bank->start + bank->nr_groups)
+			break;
+	}
+	if (!bank)
+		return -EINVAL;
+
+	if (!bank->handler) {
+		bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+				      bank->nr_groups, GFP_KERNEL);
+		if (!bank->chips)
+			return -ENOMEM;
+
+		set_irq_chained_handler(bank->irq, s5p_gpioint_handler);
+		set_irq_data(bank->irq, bank);
+		bank->handler = s5p_gpioint_handler;
+		printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
+		       bank->irq);
+	}
+
+	/*
+	 * chained GPIO irq has been sucessfully registered, allocate new gpio
+	 * int group and assign irq nubmers
+	 */
+
 	chip->irq_base = S5P_GPIOINT_BASE +
 			 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
 	used_gpioint_groups++;
 
-	if (!handler_registered) {
-		set_irq_chained_handler(IRQ_GPIOINT, s5p_gpioint_handler);
-		handler_registered = 1;
-	}
-
-	irq_chips[group] = chip;
+	bank->chips[group - bank->start] = chip;
 	for (i = 0; i < chip->chip.ngpio; i++) {
 		irq = chip->irq_base + i;
 		set_irq_chip(irq, &s5p_gpioint);
@@ -221,3 +254,19 @@ int __init s5p_register_gpio_interrupt(int pin)
 	}
 	return ret;
 }
+
+int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
+{
+	struct s5p_gpioint_bank *bank;
+
+	bank = kzalloc(sizeof(*bank), GFP_KERNEL);
+	if (!bank)
+		return -ENOMEM;
+
+	bank->start = start;
+	bank->nr_groups = nr_groups;
+	bank->irq = chain_irq;
+
+	list_add_tail(&bank->list, &banks);
+	return 0;
+}
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index e4b5cf1..5e04fa6 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -225,4 +225,20 @@ extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
  */
 extern int s5p_register_gpio_interrupt(int pin);
 
+/** s5p_register_gpioint_bank() - add gpio bank for further gpio interrupt
+ * registration (see s5p_register_gpio_interrupt function)
+ * @chain_irq: chained irq number for the gpio int handler for this bank
+ * @start: start gpio group number of this bank
+ * @nr_groups: number of gpio groups handled by this bank
+ *
+ * This functions registers initial information about gpio banks that
+ * can be later used by the s5p_register_gpio_interrupt() function to
+ * enable support for gpio interrupt for particular gpio group.
+ */
+#ifdef CONFIG_S5P_GPIO_INT
+extern int s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups);
+#else
+#define s5p_register_gpioint_bank(chain_irq, start, nr_groups) do { } while (0)
+#endif
+
 #endif /* __PLAT_GPIO_CFG_H */
-- 
1.7.1.569.g6f426

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/5] ARM: S5PC210: add support for gpio interrupts
  2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
                   ` (2 preceding siblings ...)
  2011-02-17  7:25 ` [PATCH 3/5] ARM: Samsung: add function to register gpio interrupt bank data Marek Szyprowski
@ 2011-02-17  7:25 ` Marek Szyprowski
  2011-02-17  7:25 ` [PATCH 5/5] ARM: S5PC210: add a placeholder for board specific interrupts Marek Szyprowski
  2011-03-12  3:23 ` [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Kukjin Kim
  5 siblings, 0 replies; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-17  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for gpio interrupts on Samsung S5PC210 platform.
Common s5p-gpioint.c code is used for handling gpio interrupts. Each gpio
line that needs gpio interrupt support must be later registered with
s5p_register_gpio_interrupt() function.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv310/gpiolib.c           |   18 +++++++++++++++---
 arch/arm/mach-s5pv310/include/mach/irqs.h |   12 ++++++++++--
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-s5pv310/gpiolib.c
index f417ecd..288f672 100644
--- a/arch/arm/mach-s5pv310/gpiolib.c
+++ b/arch/arm/mach-s5pv310/gpiolib.c
@@ -304,6 +304,7 @@ static __init int s5pv310_gpiolib_init(void)
 {
 	struct s3c_gpio_chip *chip;
 	int i;
+	int group = 0;
 	int nr_chips;
 
 	/* GPIO part 1 */
@@ -312,8 +313,11 @@ static __init int s5pv310_gpiolib_init(void)
 	nr_chips = ARRAY_SIZE(s5pv310_gpio_part1_4bit);
 
 	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
+		if (chip->config == NULL) {
 			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
 		if (chip->base == NULL)
 			chip->base = S5P_VA_GPIO1 + (i) * 0x20;
 	}
@@ -326,8 +330,11 @@ static __init int s5pv310_gpiolib_init(void)
 	nr_chips = ARRAY_SIZE(s5pv310_gpio_part2_4bit);
 
 	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
+		if (chip->config == NULL) {
 			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
 		if (chip->base == NULL)
 			chip->base = S5P_VA_GPIO2 + (i) * 0x20;
 	}
@@ -340,13 +347,18 @@ static __init int s5pv310_gpiolib_init(void)
 	nr_chips = ARRAY_SIZE(s5pv310_gpio_part3_4bit);
 
 	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
+		if (chip->config == NULL) {
 			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
 		if (chip->base == NULL)
 			chip->base = S5P_VA_GPIO3 + (i) * 0x20;
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part3_4bit, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+	s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
 
 	return 0;
 }
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 536b0b5..64dbe15 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -85,6 +85,9 @@
 #define IRQ_RTC_ALARM		COMBINER_IRQ(23, 0)
 #define IRQ_RTC_TIC		COMBINER_IRQ(23, 1)
 
+#define IRQ_GPIO_XB		COMBINER_IRQ(24, 0)
+#define IRQ_GPIO_XA		COMBINER_IRQ(24, 1)
+
 #define IRQ_UART0		COMBINER_IRQ(26, 0)
 #define IRQ_UART1		COMBINER_IRQ(26, 1)
 #define IRQ_UART2		COMBINER_IRQ(26, 2)
@@ -139,8 +142,13 @@
 #define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
 #define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
 
-/* Set the default NR_IRQS */
+/* optional GPIO interrupts */
+#define S5P_GPIOINT_BASE	(S5P_IRQ_EINT_BASE + 32)
+#define IRQ_GPIO1_NR_GROUPS	16
+#define IRQ_GPIO2_NR_GROUPS	9
+#define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
 
-#define NR_IRQS			(S5P_IRQ_EINT_BASE + 32)
+/* Set the default NR_IRQS */
+#define NR_IRQS			(IRQ_GPIO_END)
 
 #endif /* __ASM_ARCH_IRQS_H */
-- 
1.7.1.569.g6f426

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/5] ARM: S5PC210: add a placeholder for board specific interrupts
  2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
                   ` (3 preceding siblings ...)
  2011-02-17  7:25 ` [PATCH 4/5] ARM: S5PC210: add support for gpio interrupts Marek Szyprowski
@ 2011-02-17  7:25 ` Marek Szyprowski
  2011-03-12  3:23 ` [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Kukjin Kim
  5 siblings, 0 replies; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-17  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds a placeholder for board specific interrupts on S5PC210
platform.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv310/include/mach/irqs.h |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 64dbe15..a28de22 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -148,7 +148,11 @@
 #define IRQ_GPIO2_NR_GROUPS	9
 #define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
 
+/* optional board specific irqs */
+#define IRQ_BOARD_START		IRQ_GPIO_END
+#define IRQ_NR_BOARD		16
+
 /* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_GPIO_END)
+#define NR_IRQS			(IRQ_GPIO_END + IRQ_NR_BOARD)
 
 #endif /* __ASM_ARCH_IRQS_H */
-- 
1.7.1.569.g6f426

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks.
  2011-02-17  7:25 ` [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks Marek Szyprowski
@ 2011-02-23  6:57   ` Kukjin Kim
  0 siblings, 0 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-02-23  6:57 UTC (permalink / raw)
  To: linux-arm-kernel

Marek Szyrowski wrote:
> 
> This patch adds missing GPYx gpio banks on Samsung S5PC210 platform.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  arch/arm/mach-s5pv310/gpiolib.c           |   49
> +++++++++++++++++++++++++++++
>  arch/arm/mach-s5pv310/include/mach/gpio.h |   23 +++++++++++++-
>  2 files changed, 71 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-
> s5pv310/gpiolib.c
> index 55217b8..f417ecd 100644
> --- a/arch/arm/mach-s5pv310/gpiolib.c
> +++ b/arch/arm/mach-s5pv310/gpiolib.c
> @@ -199,6 +199,55 @@ static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[]
=
> {
>  			.label	= "GPL2",
>  		},
>  	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY0(0),
> +			.ngpio	= S5PV310_GPIO_Y0_NR,
> +			.label	= "GPY0",
> +		},
> +	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY1(0),
> +			.ngpio	= S5PV310_GPIO_Y1_NR,
> +			.label	= "GPY1",
> +		},
> +	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY2(0),
> +			.ngpio	= S5PV310_GPIO_Y2_NR,
> +			.label	= "GPY2",
> +		},
> +	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY3(0),
> +			.ngpio	= S5PV310_GPIO_Y3_NR,
> +			.label	= "GPY3",
> +		},
> +	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY4(0),
> +			.ngpio	= S5PV310_GPIO_Y4_NR,
> +			.label	= "GPY4",
> +		},
> +	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY5(0),
> +			.ngpio	= S5PV310_GPIO_Y5_NR,
> +			.label	= "GPY5",
> +		},
> +	}, {
> +		.config	= &gpio_cfg_noint,
> +		.chip	= {
> +			.base	= S5PV310_GPY6(0),
> +			.ngpio	= S5PV310_GPIO_Y6_NR,
> +			.label	= "GPY6",
> +		},
> +	}, {
>  		.base	= (S5P_VA_GPIO2 + 0xC00),
>  		.config	= &gpio_cfg_noint,
>  		.irq_base = IRQ_EINT(0),
> diff --git a/arch/arm/mach-s5pv310/include/mach/gpio.h b/arch/arm/mach-
> s5pv310/include/mach/gpio.h
> index 20cb80c..4b44463 100644
> --- a/arch/arm/mach-s5pv310/include/mach/gpio.h
> +++ b/arch/arm/mach-s5pv310/include/mach/gpio.h
> @@ -50,6 +50,13 @@
>  #define S5PV310_GPIO_X1_NR	(8)
>  #define S5PV310_GPIO_X2_NR	(8)
>  #define S5PV310_GPIO_X3_NR	(8)
> +#define S5PV310_GPIO_Y0_NR	(6)
> +#define S5PV310_GPIO_Y1_NR	(4)
> +#define S5PV310_GPIO_Y2_NR	(6)
> +#define S5PV310_GPIO_Y3_NR	(8)
> +#define S5PV310_GPIO_Y4_NR	(8)
> +#define S5PV310_GPIO_Y5_NR	(8)
> +#define S5PV310_GPIO_Y6_NR	(8)
>  #define S5PV310_GPIO_Z_NR	(7)
> 
>  /* GPIO bank numbers */
> @@ -87,7 +94,14 @@ enum s5p_gpio_number {
>  	S5PV310_GPIO_X1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
>  	S5PV310_GPIO_X2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
>  	S5PV310_GPIO_X3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
> -	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
> +	S5PV310_GPIO_Y0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
> +	S5PV310_GPIO_Y1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y0),
> +	S5PV310_GPIO_Y2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y1),
> +	S5PV310_GPIO_Y3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y2),
> +	S5PV310_GPIO_Y4_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y3),
> +	S5PV310_GPIO_Y5_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y4),
> +	S5PV310_GPIO_Y6_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y5),
> +	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_Y6),
>  };
> 
>  /* S5PV310 GPIO number definitions */
> @@ -120,6 +134,13 @@ enum s5p_gpio_number {
>  #define S5PV310_GPX1(_nr)	(S5PV310_GPIO_X1_START + (_nr))
>  #define S5PV310_GPX2(_nr)	(S5PV310_GPIO_X2_START + (_nr))
>  #define S5PV310_GPX3(_nr)	(S5PV310_GPIO_X3_START + (_nr))
> +#define S5PV310_GPY0(_nr)	(S5PV310_GPIO_Y0_START + (_nr))
> +#define S5PV310_GPY1(_nr)	(S5PV310_GPIO_Y1_START + (_nr))
> +#define S5PV310_GPY2(_nr)	(S5PV310_GPIO_Y2_START + (_nr))
> +#define S5PV310_GPY3(_nr)	(S5PV310_GPIO_Y3_START + (_nr))
> +#define S5PV310_GPY4(_nr)	(S5PV310_GPIO_Y4_START + (_nr))
> +#define S5PV310_GPY5(_nr)	(S5PV310_GPIO_Y5_START + (_nr))
> +#define S5PV310_GPY6(_nr)	(S5PV310_GPIO_Y6_START + (_nr))
>  #define S5PV310_GPZ(_nr)	(S5PV310_GPIO_Z_START + (_nr))
> 
>  /* the end of the S5PV310 specific gpios */
> --

Ok...but as you know, need to re-work based on latest.
Could you re-submit this based on my for-next which includes Exynos4?

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code
  2011-02-17  7:25 ` [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code Marek Szyprowski
@ 2011-02-23 10:15   ` Kukjin Kim
  2011-02-25  9:00     ` Marek Szyprowski
  0 siblings, 1 reply; 10+ messages in thread
From: Kukjin Kim @ 2011-02-23 10:15 UTC (permalink / raw)
  To: linux-arm-kernel

Marek Szyprowski wrote:
> 
> This patch performs a global cleanup in s5p gpio interrupt support code.
> The code is prepared for upcoming support for gpio interrupts on S5PC210
> platform, which has 2 gpio banks (regions) instead of one (like on
> S5PC110 and S5PC100).
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  arch/arm/plat-s5p/irq-gpioint.c |  106
+++++++++++++++++--------------------
> --
>  1 files changed, 46 insertions(+), 60 deletions(-)
> 
> diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-
> gpioint.c
> index 3b6bf89..af10328 100644
> --- a/arch/arm/plat-s5p/irq-gpioint.c
> +++ b/arch/arm/plat-s5p/irq-gpioint.c
> @@ -22,77 +22,64 @@
>  #include <plat/gpio-core.h>
>  #include <plat/gpio-cfg.h>
> 
> -#define S5P_GPIOREG(x)			(S5P_VA_GPIO + (x))
> +#define GPIO_BASE(chip)		(((unsigned long)(chip)->base) &
> ~(SZ_4K - 1))
> 

Need SZ_4K here instead of 0xFFFFF000?

> -#define GPIOINT_CON_OFFSET		0x700
> -#define GPIOINT_MASK_OFFSET		0x900
> -#define GPIOINT_PEND_OFFSET		0xA00
> +#define CON_OFFSET		0x700
> +#define MASK_OFFSET		0x900
> +#define PEND_OFFSET		0xA00

I don't know why need to change above definitions...

> +#define REG_OFFSET(x)		((x) << 2)
> 
Actually, this is used instead of "group << 2" in this file.
So how about "GPIOINT_REG_OFFSET(x)" like others?

>  static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
> 
> -static int s5p_gpioint_get_group(struct irq_data *data)
> -{
> -	struct gpio_chip *chip = irq_data_get_irq_data(data);
> -	struct s3c_gpio_chip *s3c_chip = container_of(chip,
> -			struct s3c_gpio_chip, chip);
> -	int group;
> -
> -	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++)
> -		if (s3c_chip == irq_chips[group])
> -			break;
> -
> -	return group;
> -}
> -
>  static int s5p_gpioint_get_offset(struct irq_data *data)
>  {
> -	struct gpio_chip *chip = irq_data_get_irq_data(data);
> -	struct s3c_gpio_chip *s3c_chip = container_of(chip,
> -			struct s3c_gpio_chip, chip);
> -
> -	return data->irq - s3c_chip->irq_base;
> +	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
> +	return data->irq - chip->irq_base;
>  }
> 
>  static void s5p_gpioint_ack(struct irq_data *data)
>  {
> +	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
>  	int group, offset, pend_offset;
>  	unsigned int value;
> 
> -	group = s5p_gpioint_get_group(data);
> +	group = chip->group;
>  	offset = s5p_gpioint_get_offset(data);
> -	pend_offset = group << 2;
> +	pend_offset = REG_OFFSET(group);
> 
> -	value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
> -	value |= 1 << offset;
> -	__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
> +	value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
> +	value |= BIT(offset);

No need inclusion <linux/bitops.h>?

> +	__raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
>  }
> 
>  static void s5p_gpioint_mask(struct irq_data *data)
>  {
> +	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
>  	int group, offset, mask_offset;
>  	unsigned int value;
> 
> -	group = s5p_gpioint_get_group(data);
> +	group = chip->group;
>  	offset = s5p_gpioint_get_offset(data);
> -	mask_offset = group << 2;
> +	mask_offset = REG_OFFSET(group);
> 
> -	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
> -	value |= 1 << offset;
> -	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
> +	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
> +	value |= BIT(offset);
> +	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
>  }
> 
>  static void s5p_gpioint_unmask(struct irq_data *data)
>  {
> +	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
>  	int group, offset, mask_offset;
>  	unsigned int value;
> 
> -	group = s5p_gpioint_get_group(data);
> +	group = chip->group;
>  	offset = s5p_gpioint_get_offset(data);
> -	mask_offset = group << 2;
> +	mask_offset = REG_OFFSET(group);
> 
> -	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
> -	value &= ~(1 << offset);
> -	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
> +	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
> +	value &= ~BIT(offset);
> +	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
>  }
> 
>  static void s5p_gpioint_mask_ack(struct irq_data *data)
> @@ -103,12 +90,13 @@ static void s5p_gpioint_mask_ack(struct irq_data
*data)
> 
>  static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
>  {
> +	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
>  	int group, offset, con_offset;
>  	unsigned int value;
> 
> -	group = s5p_gpioint_get_group(data);
> +	group = chip->group;
>  	offset = s5p_gpioint_get_offset(data);
> -	con_offset = group << 2;
> +	con_offset = REG_OFFSET(group);
> 
>  	switch (type) {
>  	case IRQ_TYPE_EDGE_RISING:
> @@ -132,15 +120,15 @@ static int s5p_gpioint_set_type(struct irq_data
*data,
> unsigned int type)
>  		return -EINVAL;
>  	}
> 
> -	value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
> +	value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset);
>  	value &= ~(0x7 << (offset * 0x4));
>  	value |= (type << (offset * 0x4));
> -	__raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
> +	__raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);
> 
>  	return 0;
>  }
> 
> -struct irq_chip s5p_gpioint = {
> +static struct irq_chip s5p_gpioint = {
>  	.name		= "s5p_gpioint",
>  	.irq_ack	= s5p_gpioint_ack,
>  	.irq_mask	= s5p_gpioint_mask,
> @@ -151,30 +139,28 @@ struct irq_chip s5p_gpioint = {
> 
>  static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
>  {
> -	int group, offset, pend_offset, mask_offset;
> -	int real_irq;
> +	int group, pend_offset, mask_offset;
>  	unsigned int pend, mask;
> 
>  	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
> -		pend_offset = group << 2;
> -		pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) +
> -				pend_offset);
> +		struct s3c_gpio_chip *chip = irq_chips[group];
> +		if (!chip)
> +			continue;
> +
> +		pend_offset = REG_OFFSET(group);
> +		pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET +
> pend_offset);
>  		if (!pend)
>  			continue;
> 
> -		mask_offset = group << 2;
> -		mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) +
> -				mask_offset);
> +		mask_offset = REG_OFFSET(group);
> +		mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET +
> mask_offset);
>  		pend &= ~mask;
> 
> -		for (offset = 0; offset < 8; offset++) {
> -			if (pend & (1 << offset)) {
> -				struct s3c_gpio_chip *chip =
irq_chips[group];
> -				if (chip) {
> -					real_irq = chip->irq_base + offset;
> -					generic_handle_irq(real_irq);
> -				}
> -			}
> +		while (pend) {
> +			int offset = fls(pend) - 1;

__ffs?

And hmm...do we really need while loop here?

> +			int real_irq = chip->irq_base + offset;
> +			generic_handle_irq(real_irq);
> +			pend &= ~BIT(offset);
>  		}
>  	}
>  }
> @@ -202,7 +188,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip
> *chip)
>  	for (i = 0; i < chip->chip.ngpio; i++) {
>  		irq = chip->irq_base + i;
>  		set_irq_chip(irq, &s5p_gpioint);
> -		set_irq_data(irq, &chip->chip);
> +		set_irq_data(irq, chip);

?

>  		set_irq_handler(irq, handle_level_irq);
>  		set_irq_flags(irq, IRQF_VALID);
>  	}
> --


Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code
  2011-02-23 10:15   ` Kukjin Kim
@ 2011-02-25  9:00     ` Marek Szyprowski
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Szyprowski @ 2011-02-25  9:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Wednesday, February 23, 2011 11:15 AM Kukjin Kim wrote:

> Marek Szyprowski wrote:
> >
> > This patch performs a global cleanup in s5p gpio interrupt support code.
> > The code is prepared for upcoming support for gpio interrupts on S5PC210
> > platform, which has 2 gpio banks (regions) instead of one (like on
> > S5PC110 and S5PC100).
> >
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> >  arch/arm/plat-s5p/irq-gpioint.c |  106
> +++++++++++++++++--------------------
> > --
> >  1 files changed, 46 insertions(+), 60 deletions(-)
> >
> > diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-
> > gpioint.c
> > index 3b6bf89..af10328 100644
> > --- a/arch/arm/plat-s5p/irq-gpioint.c
> > +++ b/arch/arm/plat-s5p/irq-gpioint.c
> > @@ -22,77 +22,64 @@
> >  #include <plat/gpio-core.h>
> >  #include <plat/gpio-cfg.h>
> >
> > -#define S5P_GPIOREG(x)			(S5P_VA_GPIO + (x))
> > +#define GPIO_BASE(chip)		(((unsigned long)(chip)->base) &
> > ~(SZ_4K - 1))
> >
> 
> Need SZ_4K here instead of 0xFFFFF000?

No problem, I can change it to 0xFFFFF000

> 
> > -#define GPIOINT_CON_OFFSET		0x700
> > -#define GPIOINT_MASK_OFFSET		0x900
> > -#define GPIOINT_PEND_OFFSET		0xA00
> > +#define CON_OFFSET		0x700
> > +#define MASK_OFFSET		0x900
> > +#define PEND_OFFSET		0xA00
> 
> I don't know why need to change above definitions...

I've shortened them to make the code the uses them to fit 80 characters
per line... They are just a local defines that imho don't need to be
prefixed with GPIOINT_

> > +#define REG_OFFSET(x)		((x) << 2)
> >
> Actually, this is used instead of "group << 2" in this file.
> So how about "GPIOINT_REG_OFFSET(x)" like others?

Ok.

> >  static void s5p_gpioint_ack(struct irq_data *data)
> >  {
> > +	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
> >  	int group, offset, pend_offset;
> >  	unsigned int value;
> >
> > -	group = s5p_gpioint_get_group(data);
> > +	group = chip->group;
> >  	offset = s5p_gpioint_get_offset(data);
> > -	pend_offset = group << 2;
> > +	pend_offset = REG_OFFSET(group);
> >
> > -	value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
> > -	value |= 1 << offset;
> > -	__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
> > +	value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
> > +	value |= BIT(offset);
> 
> No need inclusion <linux/bitops.h>?

It has been included indirectly, because the code compiled fine.

snip

> >  static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
> >  {
> > -	int group, offset, pend_offset, mask_offset;
> > -	int real_irq;
> > +	int group, pend_offset, mask_offset;
> >  	unsigned int pend, mask;
> >
> >  	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
> > -		pend_offset = group << 2;
> > -		pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) +
> > -				pend_offset);
> > +		struct s3c_gpio_chip *chip = irq_chips[group];
> > +		if (!chip)
> > +			continue;
> > +
> > +		pend_offset = REG_OFFSET(group);
> > +		pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET +
> > pend_offset);
> >  		if (!pend)
> >  			continue;
> >
> > -		mask_offset = group << 2;
> > -		mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) +
> > -				mask_offset);
> > +		mask_offset = REG_OFFSET(group);
> > +		mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET +
> > mask_offset);
> >  		pend &= ~mask;
> >
> > -		for (offset = 0; offset < 8; offset++) {
> > -			if (pend & (1 << offset)) {
> > -				struct s3c_gpio_chip *chip =
> irq_chips[group];
> > -				if (chip) {
> > -					real_irq = chip->irq_base + offset;
> > -					generic_handle_irq(real_irq);
> > -				}
> > -			}
> > +		while (pend) {
> > +			int offset = fls(pend) - 1;
> 
> __ffs?

I don't see much difference between ffs and fls here...

> And hmm...do we really need while loop here?

Yes, because more than one gpio pin in a group can issue an interrupt at the
same time. The previous version used for() loop here.

> 
> > +			int real_irq = chip->irq_base + offset;
> > +			generic_handle_irq(real_irq);
> > +			pend &= ~BIT(offset);
> >  		}
> >  	}
> >  }
> > @@ -202,7 +188,7 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip
> > *chip)
> >  	for (i = 0; i < chip->chip.ngpio; i++) {
> >  		irq = chip->irq_base + i;
> >  		set_irq_chip(irq, &s5p_gpioint);
> > -		set_irq_data(irq, &chip->chip);
> > +		set_irq_data(irq, chip);
> 
> ?

This simplifies all the functions that use get_irq_data. Now they get s3c_gpio_chip
directly and don't need to extract it with contrainer_of().

Best regards
--
Marek Szyprowski
Samsung Poland R&D Center

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update
  2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
                   ` (4 preceding siblings ...)
  2011-02-17  7:25 ` [PATCH 5/5] ARM: S5PC210: add a placeholder for board specific interrupts Marek Szyprowski
@ 2011-03-12  3:23 ` Kukjin Kim
  5 siblings, 0 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-03-12  3:23 UTC (permalink / raw)
  To: linux-arm-kernel

Marek Szyprowski wrote:
> 
> Hello,
> 
> This patch series perform an update on interrupts support for
> S5PC210/S5PV310/EXYNOS4 platform. Two optional features have been added.
> The first one is GPIO interrupts handler, a second is support for board
> specific interrupts. The patches have been prepared to maximise the code
> reuse, so common code for gpio interrupts for s5pc100, s5pc110 & s5pc210
> have been prepared.
> 
> The patches have been prepared against
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
> for-next branch (commit 857ddb87db).
> 
> Patches that make use of these 2 optional features for universal c210
> board will follow soon.
> 
> Best regards
> --
> Marek Szyprowski
> Samsung Poland R&D Center
> 
> 
> 
> Patch summary:
> 
> Marek Szyprowski (5):
>   ARM: S5PV310: Add missing GPYx banks.
>   ARM: Samsung: cleanup S5P gpio interrupt code
>   ARM: Samsung: add function to register gpio interrupt bank data
>   ARM: S5PC210: add support for gpio interrupts
>   ARM: S5PC210: add a placeholder for board specific interrupts
> 
>  arch/arm/mach-s5pc100/gpiolib.c               |    1 +
>  arch/arm/mach-s5pv210/gpiolib.c               |    1 +
>  arch/arm/mach-s5pv310/gpiolib.c               |   67 ++++++++++-
>  arch/arm/mach-s5pv310/include/mach/gpio.h     |   23 ++++-
>  arch/arm/mach-s5pv310/include/mach/irqs.h     |   16 ++-
>  arch/arm/plat-s5p/irq-gpioint.c               |  169
+++++++++++++++--------
> --
>  arch/arm/plat-samsung/include/plat/gpio-cfg.h |   16 +++
>  7 files changed, 220 insertions(+), 73 deletions(-)
> 
> --
> 1.7.1.569.g6f426

Marek,

Could you please re-send this based on my latest for-next which includes
Exynos4 changes?
And would be better to be separate gpio interrupt and board specific
interrupt.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-03-12  3:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-17  7:25 [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Marek Szyprowski
2011-02-17  7:25 ` [PATCH 1/5] ARM: S5PV310: Add missing GPYx banks Marek Szyprowski
2011-02-23  6:57   ` Kukjin Kim
2011-02-17  7:25 ` [PATCH 2/5] ARM: Samsung: cleanup S5P gpio interrupt code Marek Szyprowski
2011-02-23 10:15   ` Kukjin Kim
2011-02-25  9:00     ` Marek Szyprowski
2011-02-17  7:25 ` [PATCH 3/5] ARM: Samsung: add function to register gpio interrupt bank data Marek Szyprowski
2011-02-17  7:25 ` [PATCH 4/5] ARM: S5PC210: add support for gpio interrupts Marek Szyprowski
2011-02-17  7:25 ` [PATCH 5/5] ARM: S5PC210: add a placeholder for board specific interrupts Marek Szyprowski
2011-03-12  3:23 ` [PATCH 0/5] S5PC210/S5PV310/EXYNOS4 interrupts update Kukjin Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).