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
25static 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
32static 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
39static 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
46unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
47unsigned int map_ipridx_to_addr(int idx)
48{
49	return 0;
50}
51
52void 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}
76EXPORT_SYMBOL(make_ipr_irq);
77
78#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
79int ipr_irq_demux(int irq)
80{
81	return irq;
82}
83#endif
84