Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / arch / mips / emma2rh / markeins / irq_markeins.c
1 /*
2  *  arch/mips/emma2rh/markeins/irq_markeins.c
3  *      This file defines the irq handler for Mark-eins.
4  *
5  *  Copyright (C) NEC Electronics Corporation 2004-2006
6  *
7  *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
8  *
9  *      Copyright 2001 MontaVista Software Inc.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25 #include <linux/interrupt.h>
26 #include <linux/irq.h>
27 #include <linux/types.h>
28 #include <linux/ptrace.h>
29
30 #include <asm/debug.h>
31 #include <asm/emma2rh/emma2rh.h>
32
33 static int emma2rh_sw_irq_base = -1;
34 static int emma2rh_gpio_irq_base = -1;
35
36 void ll_emma2rh_sw_irq_enable(int reg);
37 void ll_emma2rh_sw_irq_disable(int reg);
38 void ll_emma2rh_gpio_irq_enable(int reg);
39 void ll_emma2rh_gpio_irq_disable(int reg);
40
41 static void emma2rh_sw_irq_enable(unsigned int irq)
42 {
43         ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
44 }
45
46 static void emma2rh_sw_irq_disable(unsigned int irq)
47 {
48         ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
49 }
50
51 static unsigned int emma2rh_sw_irq_startup(unsigned int irq)
52 {
53         emma2rh_sw_irq_enable(irq);
54         return 0;
55 }
56
57 #define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable
58
59 static void emma2rh_sw_irq_ack(unsigned int irq)
60 {
61         ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
62 }
63
64 static void emma2rh_sw_irq_end(unsigned int irq)
65 {
66         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
67                 ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
68 }
69
70 struct irq_chip emma2rh_sw_irq_controller = {
71         .typename = "emma2rh_sw_irq",
72         .startup = emma2rh_sw_irq_startup,
73         .shutdown = emma2rh_sw_irq_shutdown,
74         .enable = emma2rh_sw_irq_enable,
75         .disable = emma2rh_sw_irq_disable,
76         .ack = emma2rh_sw_irq_ack,
77         .end = emma2rh_sw_irq_end,
78         .set_affinity = NULL,
79 };
80
81 void emma2rh_sw_irq_init(u32 irq_base)
82 {
83         u32 i;
84
85         for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) {
86                 irq_desc[i].status = IRQ_DISABLED;
87                 irq_desc[i].action = NULL;
88                 irq_desc[i].depth = 2;
89                 irq_desc[i].handler = &emma2rh_sw_irq_controller;
90         }
91
92         emma2rh_sw_irq_base = irq_base;
93 }
94
95 void ll_emma2rh_sw_irq_enable(int irq)
96 {
97         u32 reg;
98
99         db_assert(irq >= 0);
100         db_assert(irq < NUM_EMMA2RH_IRQ_SW);
101
102         reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
103         reg |= 1 << irq;
104         emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
105 }
106
107 void ll_emma2rh_sw_irq_disable(int irq)
108 {
109         u32 reg;
110
111         db_assert(irq >= 0);
112         db_assert(irq < 32);
113
114         reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
115         reg &= ~(1 << irq);
116         emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
117 }
118
119 static void emma2rh_gpio_irq_enable(unsigned int irq)
120 {
121         ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
122 }
123
124 static void emma2rh_gpio_irq_disable(unsigned int irq)
125 {
126         ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base);
127 }
128
129 static unsigned int emma2rh_gpio_irq_startup(unsigned int irq)
130 {
131         emma2rh_gpio_irq_enable(irq);
132         return 0;
133 }
134
135 #define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable
136
137 static void emma2rh_gpio_irq_ack(unsigned int irq)
138 {
139         irq -= emma2rh_gpio_irq_base;
140         emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
141         ll_emma2rh_gpio_irq_disable(irq);
142 }
143
144 static void emma2rh_gpio_irq_end(unsigned int irq)
145 {
146         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
147                 ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
148 }
149
150 struct irq_chip emma2rh_gpio_irq_controller = {
151         .typename = "emma2rh_gpio_irq",
152         .startup = emma2rh_gpio_irq_startup,
153         .shutdown = emma2rh_gpio_irq_shutdown,
154         .enable = emma2rh_gpio_irq_enable,
155         .disable = emma2rh_gpio_irq_disable,
156         .ack = emma2rh_gpio_irq_ack,
157         .end = emma2rh_gpio_irq_end,
158         .set_affinity = NULL,
159 };
160
161 void emma2rh_gpio_irq_init(u32 irq_base)
162 {
163         u32 i;
164
165         for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) {
166                 irq_desc[i].status = IRQ_DISABLED;
167                 irq_desc[i].action = NULL;
168                 irq_desc[i].depth = 2;
169                 irq_desc[i].handler = &emma2rh_gpio_irq_controller;
170         }
171
172         emma2rh_gpio_irq_base = irq_base;
173 }
174
175 void ll_emma2rh_gpio_irq_enable(int irq)
176 {
177         u32 reg;
178
179         db_assert(irq >= 0);
180         db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
181
182         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
183         reg |= 1 << irq;
184         emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
185 }
186
187 void ll_emma2rh_gpio_irq_disable(int irq)
188 {
189         u32 reg;
190
191         db_assert(irq >= 0);
192         db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
193
194         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
195         reg &= ~(1 << irq);
196         emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
197 }