aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu/irq/ipr.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/irq/ipr.c')
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c102
1 files changed, 27 insertions, 75 deletions
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index f785822cd5de..8944abdf6e1c 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -1,11 +1,10 @@
1/* 1/*
2 * arch/sh/kernel/cpu/irq/ipr.c 2 * Interrupt handling for IPR-based IRQ.
3 * 3 *
4 * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi 4 * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
5 * Copyright (C) 2000 Kazumoto Kojima 5 * Copyright (C) 2000 Kazumoto Kojima
6 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp> 6 * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
7 * 7 * Copyright (C) 2006 Paul Mundt
8 * Interrupt handling for IPR-based IRQ.
9 * 8 *
10 * Supported system: 9 * Supported system:
11 * On-chip supporting modules (TMU, RTC, etc.). 10 * On-chip supporting modules (TMU, RTC, etc.).
@@ -13,12 +12,13 @@
13 * Hitachi SolutionEngine external I/O: 12 * Hitachi SolutionEngine external I/O:
14 * MS7709SE01, MS7709ASE01, and MS7750SE01 13 * MS7709SE01, MS7709ASE01, and MS7750SE01
15 * 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.
16 */ 18 */
17
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/irq.h> 20#include <linux/irq.h>
20#include <linux/module.h> 21#include <linux/module.h>
21
22#include <asm/system.h> 22#include <asm/system.h>
23#include <asm/io.h> 23#include <asm/io.h>
24#include <asm/machvec.h> 24#include <asm/machvec.h>
@@ -28,93 +28,45 @@ struct ipr_data {
28 int shift; /* Shifts of the 16-bit data */ 28 int shift; /* Shifts of the 16-bit data */
29 int priority; /* The priority */ 29 int priority; /* The priority */
30}; 30};
31static struct ipr_data ipr_data[NR_IRQS];
32
33static void enable_ipr_irq(unsigned int irq);
34static void disable_ipr_irq(unsigned int irq);
35
36/* shutdown is same as "disable" */
37#define shutdown_ipr_irq disable_ipr_irq
38
39static void mask_and_ack_ipr(unsigned int);
40static void end_ipr_irq(unsigned int irq);
41
42static unsigned int startup_ipr_irq(unsigned int irq)
43{
44 enable_ipr_irq(irq);
45 return 0; /* never anything pending */
46}
47
48static struct hw_interrupt_type ipr_irq_type = {
49 .typename = "IPR-IRQ",
50 .startup = startup_ipr_irq,
51 .shutdown = shutdown_ipr_irq,
52 .enable = enable_ipr_irq,
53 .disable = disable_ipr_irq,
54 .ack = mask_and_ack_ipr,
55 .end = end_ipr_irq
56};
57 31
58static void disable_ipr_irq(unsigned int irq) 32static void disable_ipr_irq(unsigned int irq)
59{ 33{
60 unsigned long val; 34 struct ipr_data *p = get_irq_chip_data(irq);
61 unsigned int addr = ipr_data[irq].addr;
62 unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
63
64 /* Set the priority in IPR to 0 */ 35 /* Set the priority in IPR to 0 */
65 val = ctrl_inw(addr); 36 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
66 val &= mask;
67 ctrl_outw(val, addr);
68} 37}
69 38
70static void enable_ipr_irq(unsigned int irq) 39static void enable_ipr_irq(unsigned int irq)
71{ 40{
72 unsigned long val; 41 struct ipr_data *p = get_irq_chip_data(irq);
73 unsigned int addr = ipr_data[irq].addr;
74 int priority = ipr_data[irq].priority;
75 unsigned short value = (priority << ipr_data[irq].shift);
76
77 /* Set priority in IPR back to original value */ 42 /* Set priority in IPR back to original value */
78 val = ctrl_inw(addr); 43 ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
79 val |= value;
80 ctrl_outw(val, addr);
81} 44}
82 45
83static void mask_and_ack_ipr(unsigned int irq) 46static struct irq_chip ipr_irq_chip = {
84{ 47 .name = "ipr",
85 disable_ipr_irq(irq); 48 .mask = disable_ipr_irq,
86 49 .unmask = enable_ipr_irq,
87#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ 50 .mask_ack = disable_ipr_irq,
88 defined(CONFIG_CPU_SUBTYPE_SH7706) || \ 51};
89 defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
90 /* This is needed when we use edge triggered setting */
91 /* XXX: Is it really needed? */
92 if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
93 /* Clear external interrupt request */
94 int a = ctrl_inb(INTC_IRR0);
95 a &= ~(1 << (irq - IRQ0_IRQ));
96 ctrl_outb(a, INTC_IRR0);
97 }
98#endif
99}
100
101static void end_ipr_irq(unsigned int irq)
102{
103 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
104 enable_ipr_irq(irq);
105}
106 52
107void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) 53void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
108{ 54{
55 struct ipr_data ipr_data;
56
109 disable_irq_nosync(irq); 57 disable_irq_nosync(irq);
110 ipr_data[irq].addr = addr;
111 ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
112 ipr_data[irq].priority = priority;
113 58
114 irq_desc[irq].chip = &ipr_irq_type; 59 ipr_data.addr = addr;
115 disable_ipr_irq(irq); 60 ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */
61 ipr_data.priority = priority;
62
63 set_irq_chip_and_handler(irq, &ipr_irq_chip, handle_level_irq);
64 set_irq_chip_data(irq, &ipr_data);
65
66 enable_ipr_irq(irq);
116} 67}
117 68
69/* XXX: This needs to die a horrible death.. */
118void __init init_IRQ(void) 70void __init init_IRQ(void)
119{ 71{
120#ifndef CONFIG_CPU_SUBTYPE_SH7780 72#ifndef CONFIG_CPU_SUBTYPE_SH7780