config CPU_HAS_INTC2_IRQ
        bool
 
+config CPU_HAS_IPR_IRQ
+       bool
+
 config CPU_HAS_SR_RB
        bool "CPU has SR.RB"
        depends on CPU_SH3 || CPU_SH4
 
 /*
- *     Setup for Titan
+ * arch/sh/boards/titan/setup.c - Setup for Titan
+ *
+ *  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
+ * for more details.
  */
-
 #include <linux/init.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <asm/titan.h>
 #include <asm/io.h>
 
-extern void __init pcibios_init_platform(void);
-
 static struct ipr_data titan_ipr_map[] = {
-       { TITAN_IRQ_WAN,        IRL0_IPR_ADDR,  IRL0_IPR_POS,   IRL0_PRIORITY },
-       { TITAN_IRQ_LAN,        IRL1_IPR_ADDR,  IRL1_IPR_POS,   IRL1_PRIORITY },
-       { TITAN_IRQ_MPCIA,      IRL2_IPR_ADDR,  IRL2_IPR_POS,   IRL2_PRIORITY },
-       { TITAN_IRQ_USB,        IRL3_IPR_ADDR,  IRL3_IPR_POS,   IRL3_PRIORITY },
+       /* IRQ, IPR idx, shift, prio */
+       { TITAN_IRQ_WAN,   3, 12, 8 },  /* eth0 (WAN) */
+       { TITAN_IRQ_LAN,   3,  8, 8 },  /* eth1 (LAN) */
+       { TITAN_IRQ_MPCIA, 3,  4, 8 },  /* mPCI A (top) */
+       { TITAN_IRQ_USB,   3,  0, 8 },  /* mPCI B (bottom), USB */
 };
 
 static void __init init_titan_irq(void)
 {
        /* enable individual interrupt mode for externals */
-       ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
-
+       ipr_irq_enable_irlm();
+       /* register ipr irqs */
        make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map));
 }
 
        .mv_ioport_map = titan_ioport_map,
 
        .mv_init_irq =  init_titan_irq,
-       .mv_init_pci =  pcibios_init_platform,
 };
 ALIAS_MV(titan)
 
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/titan.h>
 #include "pci-sh4.h"
 
+static char titan_irq_tab[] __initdata = {
+       TITAN_IRQ_WAN,
+       TITAN_IRQ_LAN,
+       TITAN_IRQ_MPCIA,
+       TITAN_IRQ_MPCIB,
+       TITAN_IRQ_USB,
+};
+
 int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
-       int irq = -1;
-
-       switch (slot) {
-       case 0: irq = TITAN_IRQ_WAN;   break;   /* eth0 (WAN) */
-       case 1: irq = TITAN_IRQ_LAN;   break;   /* eth1 (LAN) */
-       case 2: irq = TITAN_IRQ_MPCIA; break;   /* mPCI A */
-       case 3: irq = TITAN_IRQ_MPCIB; break;   /* mPCI B */
-       case 4: irq = TITAN_IRQ_USB;   break;   /* USB */
-       default:
-               printk(KERN_INFO "PCI: Bad IRQ mapping "
-                                "request for slot %d\n", slot);
-               return -1;
-       }
+       int irq = titan_irq_tab[slot];
 
        printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
                slot, pin - 1 + 'A', irq);
 
 #
 # 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
 
 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 = {
 
        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");
 }
 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)
 {
 
  * 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
 #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[] = {
                                    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
+}
 
 #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>
 #endif
 
 #ifdef CONFIG_CPU_HAS_INTEVT
-       irq = (ctrl_inl(INTEVT) >> 5) - 16;
+       irq = evt2irq(ctrl_inl(INTEVT));
 #else
        irq = r4;
 #endif
 }
 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());
+}
 
 config CPU_SUBTYPE_SH7750
        bool "Support SH7750 processor"
        select CPU_SH4
+       select CPU_HAS_IPR_IRQ
        help
          Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
 
        bool "Support SH7750R processor"
        select CPU_SH4
        select CPU_SUBTYPE_SH7750
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7750S
        bool "Support SH7750S processor"
        select CPU_SH4
        select CPU_SUBTYPE_SH7750
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7751
        bool "Support SH7751 processor"
        select CPU_SH4
+       select CPU_HAS_IPR_IRQ
        help
          Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
          or if you have a HD6417751R CPU.
        bool "Support SH7751R processor"
        select CPU_SH4
        select CPU_SUBTYPE_SH7751
+       select CPU_HAS_IPR_IRQ
 
 config CPU_SUBTYPE_SH7760
        bool "Support SH7760 processor"
 
 /* NR_IRQS. 1+2+3 */
 #define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS)
 
+/*
+ * Convert back and forth between INTEVT and IRQ values.
+ */
+#define evt2irq(evt)           (((evt) >> 5) - 16)
+#define irq2evt(irq)           (((irq) + 16) << 5)
+
 /*
  * Simple Mask Register Support
  */
  */
 void init_IRQ_pint(void);
 
+/*
+ * The shift value is now the number of bits to shift, not the number of
+ * bits/4. This is to make it easier to read the value directly from the
+ * datasheets. The IPR address, addr, will be set from ipr_idx via the
+ * map_ipridx_to_addr function.
+ */
 struct ipr_data {
        unsigned int irq;
-       unsigned int addr;      /* Address of Interrupt Priority Register */
-       int shift;              /* Shifts of the 16-bit data */
+       int ipr_idx;            /* Index for the IPR registered */
+       int shift;              /* Number of bits to shift the data */
        int priority;           /* The priority */
+       unsigned int addr;      /* Address of Interrupt Priority Register */
 };
 
+/*
+ * Given an IPR IDX, map the value to an IPR register address.
+ */
+unsigned int map_ipridx_to_addr(int idx);
+
+/*
+ * Enable individual interrupt mode for external IPR IRQs.
+ */
+void ipr_irq_enable_irlm(void);
+
 /*
  * Function for "on chip support modules".
  */
-extern void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
-extern void make_imask_irq(unsigned int irq);
+void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
+void make_imask_irq(unsigned int irq);
+void init_IRQ_ipr(void);
 
 struct intc2_data {
        unsigned short irq;
 
 /*
  * Platform defintions for Titan
  */
-
-#ifndef _ASM_SH_TITAN_TITAN_H
-#define _ASM_SH_TITAN_TITAN_H
+#ifndef _ASM_SH_TITAN_H
+#define _ASM_SH_TITAN_H
 
 #define __IO_PREFIX titan
 #include <asm/io_generic.h>
 #define TITAN_IRQ_MPCIB                11      /* mPCI B */
 #define TITAN_IRQ_USB          11      /* USB */
 
-/*
- * The external interrupt lines, these take up ints 0 - 15 inclusive
- * depending on the priority for the interrupt.  In fact the priority
- * is the interrupt :-)
- */
-#define IRL0_IRQ       0
-#define IRL0_IPR_ADDR  INTC_IPRD
-#define IRL0_IPR_POS   3
-#define IRL0_PRIORITY  8
-
-#define IRL1_IRQ       1
-#define IRL1_IPR_ADDR  INTC_IPRD
-#define IRL1_IPR_POS   2
-#define IRL1_PRIORITY  8
-
-#define IRL2_IRQ       2
-#define IRL2_IPR_ADDR  INTC_IPRD
-#define IRL2_IPR_POS   1
-#define IRL2_PRIORITY  8
-
-#define IRL3_IRQ       3
-#define IRL3_IPR_ADDR  INTC_IPRD
-#define IRL3_IPR_POS   0
-#define IRL3_PRIORITY  8
-
-#endif
+#endif /* __ASM_SH_TITAN_H */