1 /* 2 * Interrupt handling for IPR-based IRQ. 3 * 4 * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi 5 * Copyright (C) 2000 Kazumoto Kojima 6 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp> 7 * Copyright (C) 2006 Paul Mundt 8 * 9 * Supported system: 10 * On-chip supporting modules (TMU, RTC, etc.). 11 * On-chip supporting modules for SH7709/SH7709A/SH7729/SH7300. 12 * Hitachi SolutionEngine external I/O: 13 * MS7709SE01, MS7709ASE01, and MS7750SE01 14 * 15 * This file is subject to the terms and conditions of the GNU General Public 16 * License. See the file "COPYING" in the main directory of this archive 17 * for more details. 18 */ 19 #include <linux/init.h> 20 #include <linux/irq.h> 21 #include <linux/module.h> 22 #include <asm/system.h> 23 #include <asm/io.h> 24 #include <asm/machvec.h> 25 26 27 static void disable_ipr_irq(unsigned int irq) 28 { 29 struct ipr_data *p = get_irq_chip_data(irq); 30 int shift = p->shift*4; 31 /* Set the priority in IPR to 0 */ 32 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); 33 } 34 35 static void enable_ipr_irq(unsigned int irq) 36 { 37 struct ipr_data *p = get_irq_chip_data(irq); 38 int shift = p->shift*4; 39 /* Set priority in IPR back to original value */ 40 ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); 41 } 42 43 static struct irq_chip ipr_irq_chip = { 44 .name = "IPR", 45 .mask = disable_ipr_irq, 46 .unmask = enable_ipr_irq, 47 .mask_ack = disable_ipr_irq, 48 }; 49 50 void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) 51 { 52 int i; 53 54 for (i = 0; i < nr_irqs; i++) { 55 unsigned int irq = table[i].irq; 56 disable_irq_nosync(irq); 57 set_irq_chip_and_handler_name(irq, &ipr_irq_chip, 58 handle_level_irq, "level"); 59 set_irq_chip_data(irq, &table[i]); 60 enable_ipr_irq(irq); 61 } 62 } 63 EXPORT_SYMBOL(make_ipr_irq); 64 65 /* 66 * XXX: Move this garbage in to the drivers, and kill off the ridiculous CPU 67 * subtype checks. 68 */ 69 static struct ipr_data sys_ipr_map[] = { 70 #ifndef CONFIG_CPU_SUBTYPE_SH7780 71 { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, 72 { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY }, 73 #ifdef RTC_IRQ 74 { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY }, 75 #endif 76 #ifdef SCI_ERI_IRQ 77 { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, 78 { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, 79 { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, 80 #endif 81 #ifdef SCIF1_ERI_IRQ 82 { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, 83 { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, 84 { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, 85 { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, 86 #endif 87 #ifdef SCIF2_ERI_IRQ 88 { SCIF2_ERI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, 89 { SCIF2_RXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, 90 { SCIF2_BRI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, 91 { SCIF2_TXI_IRQ, SCIF2_IPR_ADDR, SCIF2_IPR_POS, SCIF2_PRIORITY }, 92 #endif 93 #ifdef SCIF3_ERI_IRQ 94 { SCIF3_ERI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, 95 { SCIF3_RXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, 96 { SCIF3_BRI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, 97 { SCIF3_TXI_IRQ, SCIF3_IPR_ADDR, SCIF3_IPR_POS, SCIF3_PRIORITY }, 98 #endif 99 #if defined(CONFIG_CPU_SUBTYPE_SH7300) 100 { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, 101 { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, 102 { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, 103 { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, 104 #endif 105 #ifdef SCIF_ERI_IRQ 106 { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, 107 { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, 108 { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, 109 { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, 110 #endif 111 #ifdef IRDA_ERI_IRQ 112 { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, 113 { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, 114 { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, 115 { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, 116 #endif 117 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ 118 defined(CONFIG_CPU_SUBTYPE_SH7706) || \ 119 defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) 120 /* 121 * Initialize the Interrupt Controller (INTC) 122 * registers to their power on values 123 */ 124 125 /* 126 * Enable external irq (INTC IRQ mode). 127 * You should set corresponding bits of PFC to "00" 128 * to enable these interrupts. 129 */ 130 { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY }, 131 { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, 132 { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, 133 { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY }, 134 { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY }, 135 { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY }, 136 #endif 137 #endif 138 }; 139 140 void __init init_IRQ(void) 141 { 142 make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map)); 143 144 #ifdef CONFIG_CPU_HAS_PINT_IRQ 145 init_IRQ_pint(); 146 #endif 147 148 #ifdef CONFIG_CPU_HAS_INTC2_IRQ 149 init_IRQ_intc2(); 150 #endif 151 /* Perform the machine specific initialisation */ 152 if (sh_mv.mv_init_irq != NULL) 153 sh_mv.mv_init_irq(); 154 155 irq_ctx_init(smp_processor_id()); 156 } 157 158 #if !defined(CONFIG_CPU_HAS_PINT_IRQ) 159 int ipr_irq_demux(int irq) 160 { 161 return irq; 162 } 163 #endif 164