* [PATCH 1/3] ARM: S3C24XX: include first 4 bits of the eint register in irq mapping
2013-02-12 0:02 [PATCH 0/3] ARM: S3C24XX: integrate special s3c2412 eint handling Heiko Stübner
@ 2013-02-12 0:03 ` Heiko Stübner
2013-02-12 0:03 ` [PATCH 2/3] ARM: S3C24XX: add soc_is_s3c2412 option Heiko Stübner
2013-02-12 0:05 ` [PATCH 3/3] ARM: S3C24XX: handle s3c2412 eints using new infrastructure Heiko Stübner
2 siblings, 0 replies; 7+ messages in thread
From: Heiko Stübner @ 2013-02-12 0:03 UTC (permalink / raw)
To: linux-arm-kernel
This patch moves the irq numbers starting with EINT4 4 points down to
enable the inclusion of the first 4 bits of EINT register into the mapping
removing the need for special offset handling.
For most S3C24XX architectures this will simply create 4 additional unused
interrupts, but enables the S3C2412 to make use of the new infrastructure
to realize its special handling of the EINT0 to EINT3 interrupts.
All affected parts of the Samsung code (arch + drivers) seem to use the
real interrupt defines (IRQ_something) and not any form of S3C2410_IRQ(x)
whose numbering is changed here starting from S3C2410_IRQ(32).
This patch was runtime-tested on a s3c2416 based board.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/include/mach/irqs.h | 54 ++++++++++++++--------------
arch/arm/mach-s3c24xx/irq.c | 9 +----
2 files changed, 29 insertions(+), 34 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index b7a9f4d..ea589e4 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -59,49 +59,49 @@
#define IRQ_ADCPARENT S3C2410_IRQ(31)
/* interrupts generated from the external interrupts sources */
-#define IRQ_EINT4 S3C2410_IRQ(32) /* 48 */
-#define IRQ_EINT5 S3C2410_IRQ(33)
-#define IRQ_EINT6 S3C2410_IRQ(34)
-#define IRQ_EINT7 S3C2410_IRQ(35)
-#define IRQ_EINT8 S3C2410_IRQ(36)
-#define IRQ_EINT9 S3C2410_IRQ(37)
-#define IRQ_EINT10 S3C2410_IRQ(38)
-#define IRQ_EINT11 S3C2410_IRQ(39)
-#define IRQ_EINT12 S3C2410_IRQ(40)
-#define IRQ_EINT13 S3C2410_IRQ(41)
-#define IRQ_EINT14 S3C2410_IRQ(42)
-#define IRQ_EINT15 S3C2410_IRQ(43)
-#define IRQ_EINT16 S3C2410_IRQ(44)
-#define IRQ_EINT17 S3C2410_IRQ(45)
-#define IRQ_EINT18 S3C2410_IRQ(46)
-#define IRQ_EINT19 S3C2410_IRQ(47)
-#define IRQ_EINT20 S3C2410_IRQ(48) /* 64 */
-#define IRQ_EINT21 S3C2410_IRQ(49)
-#define IRQ_EINT22 S3C2410_IRQ(50)
-#define IRQ_EINT23 S3C2410_IRQ(51)
+#define IRQ_EINT4 S3C2410_IRQ(36) /* 52 */
+#define IRQ_EINT5 S3C2410_IRQ(37)
+#define IRQ_EINT6 S3C2410_IRQ(38)
+#define IRQ_EINT7 S3C2410_IRQ(39)
+#define IRQ_EINT8 S3C2410_IRQ(40)
+#define IRQ_EINT9 S3C2410_IRQ(41)
+#define IRQ_EINT10 S3C2410_IRQ(42)
+#define IRQ_EINT11 S3C2410_IRQ(43)
+#define IRQ_EINT12 S3C2410_IRQ(44)
+#define IRQ_EINT13 S3C2410_IRQ(45)
+#define IRQ_EINT14 S3C2410_IRQ(46)
+#define IRQ_EINT15 S3C2410_IRQ(47)
+#define IRQ_EINT16 S3C2410_IRQ(48)
+#define IRQ_EINT17 S3C2410_IRQ(49)
+#define IRQ_EINT18 S3C2410_IRQ(50)
+#define IRQ_EINT19 S3C2410_IRQ(51)
+#define IRQ_EINT20 S3C2410_IRQ(52) /* 68 */
+#define IRQ_EINT21 S3C2410_IRQ(53)
+#define IRQ_EINT22 S3C2410_IRQ(54)
+#define IRQ_EINT23 S3C2410_IRQ(55)
#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT4 + 4)
#define IRQ_EINT(x) (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x)))
-#define IRQ_LCD_FIFO S3C2410_IRQ(52)
-#define IRQ_LCD_FRAME S3C2410_IRQ(53)
+#define IRQ_LCD_FIFO S3C2410_IRQ(56)
+#define IRQ_LCD_FRAME S3C2410_IRQ(57)
/* IRQs for the interal UARTs, and ADC
* these need to be ordered in number of appearance in the
* SUBSRC mask register
*/
-#define S3C2410_IRQSUB(x) S3C2410_IRQ((x)+54)
+#define S3C2410_IRQSUB(x) S3C2410_IRQ((x)+58)
-#define IRQ_S3CUART_RX0 S3C2410_IRQSUB(0) /* 70 */
+#define IRQ_S3CUART_RX0 S3C2410_IRQSUB(0) /* 74 */
#define IRQ_S3CUART_TX0 S3C2410_IRQSUB(1)
#define IRQ_S3CUART_ERR0 S3C2410_IRQSUB(2)
-#define IRQ_S3CUART_RX1 S3C2410_IRQSUB(3) /* 73 */
+#define IRQ_S3CUART_RX1 S3C2410_IRQSUB(3) /* 77 */
#define IRQ_S3CUART_TX1 S3C2410_IRQSUB(4)
#define IRQ_S3CUART_ERR1 S3C2410_IRQSUB(5)
-#define IRQ_S3CUART_RX2 S3C2410_IRQSUB(6) /* 76 */
+#define IRQ_S3CUART_RX2 S3C2410_IRQSUB(6) /* 80 */
#define IRQ_S3CUART_TX2 S3C2410_IRQSUB(7)
#define IRQ_S3CUART_ERR2 S3C2410_IRQSUB(8)
@@ -136,7 +136,7 @@
/* second interrupt-register of s3c2416/s3c2450 */
-#define S3C2416_IRQ(x) S3C2410_IRQ((x) + 54 + 29)
+#define S3C2416_IRQ(x) S3C2410_IRQ((x) + 58 + 29)
#define IRQ_S3C2416_2D S3C2416_IRQ(0)
#define IRQ_S3C2416_IIC1 S3C2416_IRQ(1)
#define IRQ_S3C2416_RESERVED2 S3C2416_IRQ(2)
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c
index 1cb1962..67e8d82 100644
--- a/arch/arm/mach-s3c24xx/irq.c
+++ b/arch/arm/mach-s3c24xx/irq.c
@@ -452,7 +452,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
void __iomem *base = (void *)0xf6000000; /* static mapping */
int irq_num;
int irq_start;
- int irq_offset;
int ret;
intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
@@ -476,7 +475,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
intc->reg_intpnd = base + 0x10;
irq_num = 32;
irq_start = S3C2410_IRQ(0);
- irq_offset = 0;
break;
case 0x4a000018:
pr_debug("irq: found subintc\n");
@@ -484,7 +482,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
intc->reg_mask = base + 0x1c;
irq_num = 29;
irq_start = S3C2410_IRQSUB(0);
- irq_offset = 0;
break;
case 0x4a000040:
pr_debug("irq: found intc2\n");
@@ -493,7 +490,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
intc->reg_intpnd = base + 0x50;
irq_num = 8;
irq_start = S3C2416_IRQ(0);
- irq_offset = 0;
break;
case 0x560000a4:
pr_debug("irq: found eintc\n");
@@ -501,9 +497,8 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
intc->reg_mask = base + 0xa4;
intc->reg_pending = base + 0x08;
- irq_num = 20;
+ irq_num = 24;
irq_start = S3C2410_IRQ(32);
- irq_offset = 4;
break;
default:
pr_err("irq: unsupported controller address\n");
@@ -514,7 +509,7 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
/* now that all the data is complete, init the irq-domain */
s3c24xx_clear_intc(intc);
intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
- irq_offset, &s3c24xx_irq_ops,
+ 0, &s3c24xx_irq_ops,
intc);
if (!intc->domain) {
pr_err("irq: could not create irq-domain\n");
--
1.7.2.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/3] ARM: S3C24XX: handle s3c2412 eints using new infrastructure
2013-02-12 0:02 [PATCH 0/3] ARM: S3C24XX: integrate special s3c2412 eint handling Heiko Stübner
2013-02-12 0:03 ` [PATCH 1/3] ARM: S3C24XX: include first 4 bits of the eint register in irq mapping Heiko Stübner
2013-02-12 0:03 ` [PATCH 2/3] ARM: S3C24XX: add soc_is_s3c2412 option Heiko Stübner
@ 2013-02-12 0:05 ` Heiko Stübner
2013-02-15 14:48 ` Linus Walleij
2 siblings, 1 reply; 7+ messages in thread
From: Heiko Stübner @ 2013-02-12 0:05 UTC (permalink / raw)
To: linux-arm-kernel
The s3c2412 handles the eints 0 to 3 different than all the other SoCs
of the 24xx range. These eints must be acked and masked in the regular
bits as well as the bits 0 to 3 of the eint registers, which are unused
on the other SoCs.
This of course can be realized using the new infrastructure with the
eint bits in the main register being the parent interrupts of the
same bits in the eint register.
The s3c2412 therefore gets its own IRQ_EINT0 to 4 constants that
reside in the newly created gap before IRQ_EINT4. gpio-samsung, as the
only user of these is modified to return the correct values when
handling gpio_to_irq requests on s3c2412 based machines.
Due to lack of hardware this is compile tested only, but should
hopefully work as intended.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/include/mach/irqs.h | 4 +
arch/arm/mach-s3c24xx/irq.c | 118 +++++++++--------------------
drivers/gpio/gpio-samsung.c | 5 +-
3 files changed, 44 insertions(+), 83 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index ea589e4..43cada8 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -59,6 +59,10 @@
#define IRQ_ADCPARENT S3C2410_IRQ(31)
/* interrupts generated from the external interrupts sources */
+#define IRQ_EINT0_2412 S3C2410_IRQ(32)
+#define IRQ_EINT1_2412 S3C2410_IRQ(33)
+#define IRQ_EINT2_2412 S3C2410_IRQ(34)
+#define IRQ_EINT3_2412 S3C2410_IRQ(35)
#define IRQ_EINT4 S3C2410_IRQ(36) /* 52 */
#define IRQ_EINT5 S3C2410_IRQ(37)
#define IRQ_EINT6 S3C2410_IRQ(38)
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c
index 67e8d82..debf606 100644
--- a/arch/arm/mach-s3c24xx/irq.c
+++ b/arch/arm/mach-s3c24xx/irq.c
@@ -344,7 +344,10 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
case S3C_IRQTYPE_NONE:
return 0;
case S3C_IRQTYPE_EINT:
- if (irq_data->parent_irq)
+ /* On the S3C2412, the EINT0to3 have a parent irq
+ * but need the s3c_irq_eint0t4 chip
+ */
+ if (irq_data->parent_irq && (!soc_is_s3c2412() || hw >= 4))
irq_set_chip_and_handler(virq, &s3c_irqext_chip,
handle_edge_irq);
else
@@ -625,10 +628,10 @@ void __init s3c24xx_init_irq(void)
#ifdef CONFIG_CPU_S3C2412
static struct s3c_irq_data init_s3c2412base[32] = {
- { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
- { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
- { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
- { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
{ .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
{ .type = S3C_IRQTYPE_NONE, }, /* reserved */
@@ -659,6 +662,33 @@ static struct s3c_irq_data init_s3c2412base[32] = {
{ .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
};
+static struct s3c_irq_data init_s3c2412eint[32] = {
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
+
static struct s3c_irq_data init_s3c2412subint[32] = {
{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
@@ -677,77 +707,9 @@ static struct s3c_irq_data init_s3c2412subint[32] = {
{ .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
};
-/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
- * having them turn up in both the INT* and the EINT* registers. Whilst
- * both show the status, they both now need to be acked when the IRQs
- * go off.
-*/
-
-static void
-s3c2412_irq_mask(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
- unsigned long mask;
-
- mask = __raw_readl(S3C2410_INTMSK);
- __raw_writel(mask | bitval, S3C2410_INTMSK);
-
- mask = __raw_readl(S3C2412_EINTMASK);
- __raw_writel(mask | bitval, S3C2412_EINTMASK);
-}
-
-static inline void
-s3c2412_irq_ack(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-
- __raw_writel(bitval, S3C2412_EINTPEND);
- __raw_writel(bitval, S3C2410_SRCPND);
- __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c2412_irq_maskack(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
- unsigned long mask;
-
- mask = __raw_readl(S3C2410_INTMSK);
- __raw_writel(mask|bitval, S3C2410_INTMSK);
-
- mask = __raw_readl(S3C2412_EINTMASK);
- __raw_writel(mask | bitval, S3C2412_EINTMASK);
-
- __raw_writel(bitval, S3C2412_EINTPEND);
- __raw_writel(bitval, S3C2410_SRCPND);
- __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static void
-s3c2412_irq_unmask(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
- unsigned long mask;
-
- mask = __raw_readl(S3C2412_EINTMASK);
- __raw_writel(mask & ~bitval, S3C2412_EINTMASK);
-
- mask = __raw_readl(S3C2410_INTMSK);
- __raw_writel(mask & ~bitval, S3C2410_INTMSK);
-}
-
-static struct irq_chip s3c2412_irq_eint0t4 = {
- .irq_ack = s3c2412_irq_ack,
- .irq_mask = s3c2412_irq_mask,
- .irq_unmask = s3c2412_irq_unmask,
- .irq_set_wake = s3c_irq_wake,
- .irq_set_type = s3c_irqext_type,
-};
-
void s3c2412_init_irq(void)
{
struct s3c_irq_intc *main_intc;
- unsigned int irqno;
pr_info("S3C2412: IRQ Support\n");
@@ -761,16 +723,8 @@ void s3c2412_init_irq(void)
return;
}
- s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
+ s3c24xx_init_intc(NULL, &init_s3c2412eint[0], main_intc, 0x560000a4);
s3c24xx_init_intc(NULL, &init_s3c2412subint[0], main_intc, 0x4a000018);
-
- /* special handling for eints 0 to 3 */
-
- for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
- irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
- handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
}
#endif
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 49b4292..cb4a55b 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -1123,7 +1123,10 @@ int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
{
if (offset < 4)
- return IRQ_EINT0 + offset;
+ if (soc_is_s3c2412())
+ return IRQ_EINT0_2412 + offset;
+ else
+ return IRQ_EINT0 + offset;
if (offset < 8)
return IRQ_EINT4 + offset - 4;
--
1.7.2.3
^ permalink raw reply related [flat|nested] 7+ messages in thread