summaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile3
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c103
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c70
-rw-r--r--arch/sh/kernel/irq.c25
4 files changed, 101 insertions, 100 deletions
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index 1c034c283f59..0049d217561a 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -1,8 +1,9 @@
#
# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
#
-obj-y += ipr.o imask.o
+obj-y += imask.o
+obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o
obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o
obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index a181ccdf2906..35eb5751a3aa 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -25,17 +25,15 @@
static void disable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
- int shift = p->shift*4;
/* Set the priority in IPR to 0 */
- ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr);
+ ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
}
static void enable_ipr_irq(unsigned int irq)
{
struct ipr_data *p = get_irq_chip_data(irq);
- int shift = p->shift*4;
/* Set priority in IPR back to original value */
- ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr);
+ ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
}
static struct irq_chip ipr_irq_chip = {
@@ -51,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
for (i = 0; i < nr_irqs; i++) {
unsigned int irq = table[i].irq;
+ table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
+ /* could the IPR index be mapped, if not we ignore this */
+ if (table[i].addr == 0)
+ continue;
disable_irq_nosync(irq);
set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
handle_level_irq, "level");
@@ -60,99 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
}
EXPORT_SYMBOL(make_ipr_irq);
-/*
- * XXX: Move this garbage in to the drivers, and kill off the ridiculous CPU
- * subtype checks.
- */
-static struct ipr_data sys_ipr_map[] = {
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
- { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY },
- { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY },
-#ifdef RTC_IRQ
- { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY },
-#endif
-#ifdef SCI_ERI_IRQ
- { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
- { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
- { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY },
-#endif
-#ifdef SCIF1_ERI_IRQ
- { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
- { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
- { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
- { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY },
-#endif
-#ifdef SCIF2_ERI_IRQ
- { SCIF2_ERI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
- { SCIF2_RXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
- { SCIF2_BRI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
- { SCIF2_TXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY },
-#endif
-#ifdef SCIF3_ERI_IRQ
- { SCIF3_ERI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
- { SCIF3_RXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
- { SCIF3_BRI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
- { SCIF3_TXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY },
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
- { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY },
- { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
- { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY },
- { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY },
-#endif
-#ifdef SCIF_ERI_IRQ
- { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
- { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
- { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
- { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY },
-#endif
-#ifdef IRDA_ERI_IRQ
- { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
- { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
- { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
- { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY },
-#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
- defined(CONFIG_CPU_SUBTYPE_SH7706) || \
- defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
- /*
- * Initialize the Interrupt Controller (INTC)
- * registers to their power on values
- */
-
- /*
- * Enable external irq (INTC IRQ mode).
- * You should set corresponding bits of PFC to "00"
- * to enable these interrupts.
- */
- { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY },
- { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY },
- { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY },
- { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY },
- { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY },
- { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY },
-#endif
-#endif
-};
-
-void __init init_IRQ(void)
-{
- make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map));
-
-#ifdef CONFIG_CPU_HAS_PINT_IRQ
- init_IRQ_pint();
-#endif
-
-#ifdef CONFIG_CPU_HAS_INTC2_IRQ
- init_IRQ_intc2();
-#endif
- /* Perform the machine specific initialisation */
- if (sh_mv.mv_init_irq != NULL)
- sh_mv.mv_init_irq();
-
- irq_ctx_init(smp_processor_id());
-}
-
#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
int ipr_irq_demux(int irq)
{
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 50812d57c1c1..bbcb06f18b04 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -2,6 +2,7 @@
* SH7750/SH7751 Setup
*
* Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2006 Jamie Lenehan
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -10,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/io.h>
#include <asm/sci.h>
static struct plat_sci_port sci_platform_data[] = {
@@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void)
ARRAY_SIZE(sh7750_devices));
}
__initcall(sh7750_devices_setup);
+
+static struct ipr_data sh7750_ipr_map[] = {
+ /* IRQ, IPR-idx, shift, priority */
+ { 16, 0, 12, 2 }, /* TMU0 TUNI*/
+ { 17, 0, 12, 2 }, /* TMU1 TUNI */
+ { 18, 0, 4, 2 }, /* TMU2 TUNI */
+ { 19, 0, 4, 2 }, /* TMU2 TIPCI */
+ { 27, 1, 12, 2 }, /* WDT ITI */
+ { 20, 0, 0, 2 }, /* RTC ATI (alarm) */
+ { 21, 0, 0, 2 }, /* RTC PRI (period) */
+ { 22, 0, 0, 2 }, /* RTC CUI (carry) */
+ { 23, 1, 4, 3 }, /* SCI ERI */
+ { 24, 1, 4, 3 }, /* SCI RXI */
+ { 25, 1, 4, 3 }, /* SCI TXI */
+ { 40, 2, 4, 3 }, /* SCIF ERI */
+ { 41, 2, 4, 3 }, /* SCIF RXI */
+ { 42, 2, 4, 3 }, /* SCIF BRI */
+ { 43, 2, 4, 3 }, /* SCIF TXI */
+ { 34, 2, 8, 7 }, /* DMAC DMTE0 */
+ { 35, 2, 8, 7 }, /* DMAC DMTE1 */
+ { 36, 2, 8, 7 }, /* DMAC DMTE2 */
+ { 37, 2, 8, 7 }, /* DMAC DMTE3 */
+ { 28, 2, 8, 7 }, /* DMAC DMAE */
+};
+
+static struct ipr_data sh7751_ipr_map[] = {
+ { 44, 2, 8, 7 }, /* DMAC DMTE4 */
+ { 45, 2, 8, 7 }, /* DMAC DMTE5 */
+ { 46, 2, 8, 7 }, /* DMAC DMTE6 */
+ { 47, 2, 8, 7 }, /* DMAC DMTE7 */
+ /* The following use INTC_INPRI00 for masking, which is a 32-bit
+ register, not a 16-bit register like the IPRx registers, so it
+ would need special support */
+ /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
+ /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
+};
+
+static unsigned long ipr_offsets[] = {
+ 0xffd00004UL, /* 0: IPRA */
+ 0xffd00008UL, /* 1: IPRB */
+ 0xffd0000cUL, /* 2: IPRC */
+ 0xffd00010UL, /* 3: IPRD */
+};
+
+/* given the IPR index return the address of the IPR register */
+unsigned int map_ipridx_to_addr(int idx)
+{
+ if (idx >= ARRAY_SIZE(ipr_offsets))
+ return 0;
+ return ipr_offsets[idx];
+}
+
+#define INTC_ICR 0xffd00000UL
+#define INTC_ICR_IRLM (1<<7)
+
+/* enable individual interrupt mode for external interupts */
+void ipr_irq_enable_irlm(void)
+{
+ ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+}
+
+void __init init_IRQ_ipr()
+{
+ make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
+#ifdef CONFIG_CPU_SUBTYPE_SH7751
+ make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
+#endif
+}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 46a19e07abd3..67be2b6e8cd1 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -12,7 +12,7 @@
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/io.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/thread_info.h>
@@ -112,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
#endif
#ifdef CONFIG_CPU_HAS_INTEVT
- irq = (ctrl_inl(INTEVT) >> 5) - 16;
+ irq = evt2irq(ctrl_inl(INTEVT));
#else
irq = r4;
#endif
@@ -261,3 +261,24 @@ asmlinkage void do_softirq(void)
}
EXPORT_SYMBOL(do_softirq);
#endif
+
+void __init init_IRQ(void)
+{
+#ifdef CONFIG_CPU_HAS_PINT_IRQ
+ init_IRQ_pint();
+#endif
+
+#ifdef CONFIG_CPU_HAS_INTC2_IRQ
+ init_IRQ_intc2();
+#endif
+
+#ifdef CONFIG_CPU_HAS_IPR_IRQ
+ init_IRQ_ipr();
+#endif
+
+ /* Perform the machine specific initialisation */
+ if (sh_mv.mv_init_irq)
+ sh_mv.mv_init_irq();
+
+ irq_ctx_init(smp_processor_id());
+}