sh: Add SH7785 Highlander board support (R7785RP).
[linux-block.git] / arch / sh / kernel / cpu / irq / intc2.c
CommitLineData
bf3a00f8
PM
1/*
2 * Interrupt handling for INTC2-based IRQ.
3 *
4 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
5 * Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org)
6 *
7 * May be copied or modified under the terms of the GNU General Public
8 * License. See linux/COPYING for more information.
9 *
10 * These are the "new Hitachi style" interrupts, as present on the
11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
12 */
bf3a00f8 13#include <linux/kernel.h>
9a7ef6d5 14#include <linux/interrupt.h>
66a74057 15#include <linux/io.h>
9a7ef6d5
PM
16
17#if defined(CONFIG_CPU_SUBTYPE_SH7760)
18#define INTC2_BASE 0xfe080000
19#define INTC2_INTMSK (INTC2_BASE + 0x40)
20#define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
32351a28
PM
21#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
22 defined(CONFIG_CPU_SUBTYPE_SH7785)
9a7ef6d5
PM
23#define INTC2_BASE 0xffd40000
24#define INTC2_INTMSK (INTC2_BASE + 0x38)
25#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
26#endif
bf3a00f8
PM
27
28static void disable_intc2_irq(unsigned int irq)
29{
525ccc45 30 struct intc2_data *p = get_irq_chip_data(irq);
9a7ef6d5 31 ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
bf3a00f8
PM
32}
33
34static void enable_intc2_irq(unsigned int irq)
35{
525ccc45 36 struct intc2_data *p = get_irq_chip_data(irq);
9a7ef6d5 37 ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
bf3a00f8
PM
38}
39
525ccc45 40static struct irq_chip intc2_irq_chip = {
709bc44c 41 .name = "INTC2",
525ccc45
PM
42 .mask = disable_intc2_irq,
43 .unmask = enable_intc2_irq,
44 .mask_ack = disable_intc2_irq,
45};
bf3a00f8
PM
46
47/*
48 * Setup an INTC2 style interrupt.
49 * NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
50 * allowing the use of the numbers straight out of the datasheet.
51 * For example:
52 * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
53 * would be: ^ ^ ^ ^
54 * | | | |
66a74057
PM
55 * { 84, 0, 16, 0, 13 },
56 *
57 * in the intc2_data table.
bf3a00f8 58 */
66a74057 59void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
bf3a00f8 60{
66a74057 61 int i;
bf3a00f8 62
66a74057
PM
63 for (i = 0; i < nr_irqs; i++) {
64 unsigned long ipr, flags;
65 struct intc2_data *p = table + i;
bf3a00f8 66
66a74057 67 disable_irq_nosync(p->irq);
bf3a00f8 68
66a74057
PM
69 /* Set the priority level */
70 local_irq_save(flags);
bf3a00f8 71
9a7ef6d5 72 ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
66a74057
PM
73 ipr &= ~(0xf << p->ipr_shift);
74 ipr |= p->priority << p->ipr_shift;
9a7ef6d5 75 ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
bf3a00f8 76
66a74057 77 local_irq_restore(flags);
bf3a00f8 78
66a74057
PM
79 set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
80 handle_level_irq, "level");
81 set_irq_chip_data(p->irq, p);
bf3a00f8 82
66a74057
PM
83 enable_intc2_irq(p->irq);
84 }
bf3a00f8 85}