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 <linux/io.h> 23 #include <linux/interrupt.h> 24 25 static void disable_ipr_irq(unsigned int irq) 26 { 27 struct ipr_data *p = get_irq_chip_data(irq); 28 /* Set the priority in IPR to 0 */ 29 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); 30 } 31 32 static void enable_ipr_irq(unsigned int irq) 33 { 34 struct ipr_data *p = get_irq_chip_data(irq); 35 /* Set priority in IPR back to original value */ 36 ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); 37 } 38 39 static struct irq_chip ipr_irq_chip = { 40 .name = "IPR", 41 .mask = disable_ipr_irq, 42 .unmask = enable_ipr_irq, 43 .mask_ack = disable_ipr_irq, 44 }; 45 46 unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak)); 47 unsigned int map_ipridx_to_addr(int idx) 48 { 49 return 0; 50 } 51 52 void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) 53 { 54 int i; 55 56 for (i = 0; i < nr_irqs; i++) { 57 unsigned int irq = table[i].irq; 58 59 if (!irq) 60 irq = table[i].irq = i; 61 62 /* could the IPR index be mapped, if not we ignore this */ 63 if (!table[i].addr) { 64 table[i].addr = map_ipridx_to_addr(table[i].ipr_idx); 65 if (!table[i].addr) 66 continue; 67 } 68 69 disable_irq_nosync(irq); 70 set_irq_chip_and_handler_name(irq, &ipr_irq_chip, 71 handle_level_irq, "level"); 72 set_irq_chip_data(irq, &table[i]); 73 enable_ipr_irq(irq); 74 } 75 } 76 EXPORT_SYMBOL(make_ipr_irq); 77 78 #if !defined(CONFIG_CPU_HAS_PINT_IRQ) 79 int ipr_irq_demux(int irq) 80 { 81 return irq; 82 } 83 #endif 84