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 */