summary refs log tree commit diff
diff options
context:
space:
mode:
authorYoshihiro Shimoda <shimoda.yoshihiro@renesas.com>2008-07-04 12:37:12 +0900
committerPaul Mundt <lethal@linux-sh.org>2008-07-28 18:10:33 +0900
commit6bdfb22a8e1ffa37ae4ad35b87cb02958d1901e5 (patch)
treeafc8f27f1044be5787fb38d181292dd861f9a1c5
parentf12ae6bc4ad0054386b380dbf90e63617cd5ab92 (diff)
downloadlinux-6bdfb22a8e1ffa37ae4ad35b87cb02958d1901e5.tar.gz
sh: add interrupt ack code to sh4a
This patch is based on interrupt acknowledge code for external
interrupt sources on sh3 processors and adds on sh4a processors.

Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/cpu/irq/intc.c31
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c10
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c10
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c10
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7763.c11
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c11
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7785.c17
-rw-r--r--include/asm-sh/hw_irq.h4
8 files changed, 76 insertions, 28 deletions
diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c
index da5dae787888..8c70e201bde0 100644
--- a/arch/sh/kernel/cpu/irq/intc.c
+++ b/arch/sh/kernel/cpu/irq/intc.c
@@ -62,7 +62,7 @@ struct intc_desc_int {
 #endif
 
 static unsigned int intc_prio_level[NR_IRQS]; /* for now */
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 static unsigned long ack_handle[NR_IRQS];
 #endif
 
@@ -231,7 +231,7 @@ static void intc_disable(unsigned int irq)
 	}
 }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 static void intc_mask_ack(unsigned int irq)
 {
 	struct intc_desc_int *d = get_intc_desc(irq);
@@ -244,8 +244,23 @@ static void intc_mask_ack(unsigned int irq)
 
 	if (handle) {
 		addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-		ctrl_inb(addr);
-		ctrl_outb(0x3f ^ set_field(0, 1, handle), addr);
+		switch (_INTC_FN(handle)) {
+		case REG_FN_MODIFY_BASE + 0:	/* 8bit */
+			ctrl_inb(addr);
+			ctrl_outb(0xff ^ set_field(0, 1, handle), addr);
+			break;
+		case REG_FN_MODIFY_BASE + 1:	/* 16bit */
+			ctrl_inw(addr);
+			ctrl_outw(0xffff ^ set_field(0, 1, handle), addr);
+			break;
+		case REG_FN_MODIFY_BASE + 3:	/* 32bit */
+			ctrl_inl(addr);
+			ctrl_outl(0xffffffff ^ set_field(0, 1, handle), addr);
+			break;
+		default:
+			BUG();
+			break;
+		}
 	}
 }
 #endif
@@ -466,7 +481,7 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
 	return 0;
 }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 static unsigned int __init intc_ack_data(struct intc_desc *desc,
 					  struct intc_desc_int *d,
 					  intc_enum enum_id)
@@ -601,7 +616,7 @@ static void __init intc_register_irq(struct intc_desc *desc,
 	/* irq should be disabled by default */
 	d->chip.mask(irq);
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 	if (desc->ack_regs)
 		ack_handle[irq] = intc_ack_data(desc, d, enum_id);
 #endif
@@ -635,7 +650,7 @@ void __init register_intc_controller(struct intc_desc *desc)
 	d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
 	d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 	d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
 #endif
 	d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
@@ -676,7 +691,7 @@ void __init register_intc_controller(struct intc_desc *desc)
 	d->chip.mask_ack = intc_disable;
 	d->chip.set_type = intc_set_sense;
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 	if (desc->ack_regs) {
 		for (i = 0; i < desc->nr_ack_regs; i++)
 			k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index f26b5cdad0d1..f97ea8e0acf5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -163,8 +163,14 @@ static struct intc_sense_reg sense_registers[] __initdata = {
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7366", vectors, groups,
-			 mask_registers, prio_registers, sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+	{ 0xa4140024, 0, 8, /* INTREQ00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7366", vectors, groups,
+			     mask_registers, prio_registers, sense_registers,
+			     ack_registers);
 
 void __init plat_irq_setup(void)
 {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 62ebccf18b3c..d8617b669fad 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -229,8 +229,14 @@ static struct intc_sense_reg sense_registers[] __initdata = {
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7722", vectors, groups,
-			 mask_registers, prio_registers, sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+	{ 0xa4140024, 0, 8, /* INTREQ00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7722", vectors, groups,
+			     mask_registers, prio_registers, sense_registers,
+			     ack_registers);
 
 void __init plat_irq_setup(void)
 {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index a0470f2f5479..abd1ca03f39f 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -326,8 +326,14 @@ static struct intc_sense_reg sense_registers[] __initdata = {
 	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7723", vectors, groups,
-			 mask_registers, prio_registers, sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+	{ 0xa4140024, 0, 8, /* INTREQ00 */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc, "sh7723", vectors, groups,
+			     mask_registers, prio_registers, sense_registers,
+			     ack_registers);
 
 void __init plat_irq_setup(void)
 {
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 3b278df8a53b..3c5b629887a8 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -296,9 +296,14 @@ static struct intc_sense_reg irq_sense_registers[] __initdata = {
 					    IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_irq_desc, "sh7763-irq", irq_vectors,
-			NULL, irq_mask_registers, irq_prio_registers,
-			irq_sense_registers);
+static struct intc_mask_reg irq_ack_registers[] __initdata = {
+	{ 0xffd00024, 0, 32, /* INTREQ */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_irq_desc, "sh7763-irq", irq_vectors,
+			     NULL, irq_mask_registers, irq_prio_registers,
+			     irq_sense_registers, irq_ack_registers);
 
 
 /* External interrupt pins in IRL mode */
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 18dbbe23fea1..fb8200cc7440 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -217,9 +217,14 @@ static struct intc_sense_reg irq_sense_registers[] __initdata = {
 					    IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_irq_desc, "sh7780-irq", irq_vectors,
-			 NULL, irq_mask_registers, irq_prio_registers,
-			 irq_sense_registers);
+static struct intc_mask_reg irq_ack_registers[] __initdata = {
+	{ 0xffd00024, 0, 32, /* INTREQ */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_irq_desc, "sh7780-irq", irq_vectors,
+			     NULL, irq_mask_registers, irq_prio_registers,
+			     irq_sense_registers, irq_ack_registers);
 
 /* External interrupt pins in IRL mode */
 
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 621e7329ec63..30baa63b24c8 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -238,13 +238,18 @@ static struct intc_sense_reg sense_registers[] __initdata = {
 					    IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static DECLARE_INTC_DESC(intc_desc_irq0123, "sh7785-irq0123", vectors_irq0123,
-			 NULL, mask_registers, prio_registers,
-			 sense_registers);
+static struct intc_mask_reg ack_registers[] __initdata = {
+	{ 0xffd00024, 0, 32, /* INTREQ */
+	  { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7785-irq0123",
+			     vectors_irq0123, NULL, mask_registers,
+			     prio_registers, sense_registers, ack_registers);
 
-static DECLARE_INTC_DESC(intc_desc_irq4567, "sh7785-irq4567", vectors_irq4567,
-			 NULL, mask_registers, prio_registers,
-			 sense_registers);
+static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7785-irq4567",
+			     vectors_irq4567, NULL, mask_registers,
+			     prio_registers, sense_registers, ack_registers);
 
 /* External interrupt pins in IRL mode */
 
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 7438d1e21bc9..d557b00111bf 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -79,7 +79,7 @@ struct intc_desc {
 	struct intc_sense_reg *sense_regs;
 	unsigned int nr_sense_regs;
 	char *name;
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 	struct intc_mask_reg *ack_regs;
 	unsigned int nr_ack_regs;
 #endif
@@ -95,7 +95,7 @@ struct intc_desc symbol __initdata = {					\
 	chipname,							\
 }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
 #define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups,	\
 	mask_regs, prio_regs, sense_regs, ack_regs)			\
 struct intc_desc symbol __initdata = {					\