aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ep93xx/core.c')
-rw-r--r--arch/arm/mach-ep93xx/core.c224
1 files changed, 2 insertions, 222 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index a334914b59ff..1905676b08b2 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -137,236 +137,16 @@ struct sys_timer ep93xx_timer = {
137 137
138 138
139/************************************************************************* 139/*************************************************************************
140 * GPIO handling for EP93xx
141 *************************************************************************/
142static unsigned char gpio_int_unmasked[3];
143static unsigned char gpio_int_enabled[3];
144static unsigned char gpio_int_type1[3];
145static unsigned char gpio_int_type2[3];
146static unsigned char gpio_int_debounce[3];
147
148/* Port ordering is: A B F */
149static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
150static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
151static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
152static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
153static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
154
155void ep93xx_gpio_update_int_params(unsigned port)
156{
157 BUG_ON(port > 2);
158
159 __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
160
161 __raw_writeb(gpio_int_type2[port],
162 EP93XX_GPIO_REG(int_type2_register_offset[port]));
163
164 __raw_writeb(gpio_int_type1[port],
165 EP93XX_GPIO_REG(int_type1_register_offset[port]));
166
167 __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
168 EP93XX_GPIO_REG(int_en_register_offset[port]));
169}
170
171void ep93xx_gpio_int_mask(unsigned line)
172{
173 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
174}
175
176void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
177{
178 int line = irq_to_gpio(irq);
179 int port = line >> 3;
180 int port_mask = 1 << (line & 7);
181
182 if (enable)
183 gpio_int_debounce[port] |= port_mask;
184 else
185 gpio_int_debounce[port] &= ~port_mask;
186
187 __raw_writeb(gpio_int_debounce[port],
188 EP93XX_GPIO_REG(int_debounce_register_offset[port]));
189}
190EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
191
192/*************************************************************************
193 * EP93xx IRQ handling 140 * EP93xx IRQ handling
194 *************************************************************************/ 141 *************************************************************************/
195static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) 142extern void ep93xx_gpio_init_irq(void);
196{
197 unsigned char status;
198 int i;
199
200 status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
201 for (i = 0; i < 8; i++) {
202 if (status & (1 << i)) {
203 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
204 generic_handle_irq(gpio_irq);
205 }
206 }
207
208 status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
209 for (i = 0; i < 8; i++) {
210 if (status & (1 << i)) {
211 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
212 generic_handle_irq(gpio_irq);
213 }
214 }
215}
216
217static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
218{
219 /*
220 * map discontiguous hw irq range to continous sw irq range:
221 *
222 * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
223 */
224 int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
225 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
226
227 generic_handle_irq(gpio_irq);
228}
229
230static void ep93xx_gpio_irq_ack(unsigned int irq)
231{
232 int line = irq_to_gpio(irq);
233 int port = line >> 3;
234 int port_mask = 1 << (line & 7);
235
236 if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
237 gpio_int_type2[port] ^= port_mask; /* switch edge direction */
238 ep93xx_gpio_update_int_params(port);
239 }
240
241 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
242}
243
244static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
245{
246 int line = irq_to_gpio(irq);
247 int port = line >> 3;
248 int port_mask = 1 << (line & 7);
249
250 if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
251 gpio_int_type2[port] ^= port_mask; /* switch edge direction */
252
253 gpio_int_unmasked[port] &= ~port_mask;
254 ep93xx_gpio_update_int_params(port);
255
256 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
257}
258
259static void ep93xx_gpio_irq_mask(unsigned int irq)
260{
261 int line = irq_to_gpio(irq);
262 int port = line >> 3;
263
264 gpio_int_unmasked[port] &= ~(1 << (line & 7));
265 ep93xx_gpio_update_int_params(port);
266}
267
268static void ep93xx_gpio_irq_unmask(unsigned int irq)
269{
270 int line = irq_to_gpio(irq);
271 int port = line >> 3;
272
273 gpio_int_unmasked[port] |= 1 << (line & 7);
274 ep93xx_gpio_update_int_params(port);
275}
276
277
278/*
279 * gpio_int_type1 controls whether the interrupt is level (0) or
280 * edge (1) triggered, while gpio_int_type2 controls whether it
281 * triggers on low/falling (0) or high/rising (1).
282 */
283static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
284{
285 struct irq_desc *desc = irq_desc + irq;
286 const int gpio = irq_to_gpio(irq);
287 const int port = gpio >> 3;
288 const int port_mask = 1 << (gpio & 7);
289
290 gpio_direction_input(gpio);
291
292 switch (type) {
293 case IRQ_TYPE_EDGE_RISING:
294 gpio_int_type1[port] |= port_mask;
295 gpio_int_type2[port] |= port_mask;
296 desc->handle_irq = handle_edge_irq;
297 break;
298 case IRQ_TYPE_EDGE_FALLING:
299 gpio_int_type1[port] |= port_mask;
300 gpio_int_type2[port] &= ~port_mask;
301 desc->handle_irq = handle_edge_irq;
302 break;
303 case IRQ_TYPE_LEVEL_HIGH:
304 gpio_int_type1[port] &= ~port_mask;
305 gpio_int_type2[port] |= port_mask;
306 desc->handle_irq = handle_level_irq;
307 break;
308 case IRQ_TYPE_LEVEL_LOW:
309 gpio_int_type1[port] &= ~port_mask;
310 gpio_int_type2[port] &= ~port_mask;
311 desc->handle_irq = handle_level_irq;
312 break;
313 case IRQ_TYPE_EDGE_BOTH:
314 gpio_int_type1[port] |= port_mask;
315 /* set initial polarity based on current input level */
316 if (gpio_get_value(gpio))
317 gpio_int_type2[port] &= ~port_mask; /* falling */
318 else
319 gpio_int_type2[port] |= port_mask; /* rising */
320 desc->handle_irq = handle_edge_irq;
321 break;
322 default:
323 pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
324 return -EINVAL;
325 }
326
327 gpio_int_enabled[port] |= port_mask;
328
329 desc->status &= ~IRQ_TYPE_SENSE_MASK;
330 desc->status |= type & IRQ_TYPE_SENSE_MASK;
331
332 ep93xx_gpio_update_int_params(port);
333
334 return 0;
335}
336
337static struct irq_chip ep93xx_gpio_irq_chip = {
338 .name = "GPIO",
339 .ack = ep93xx_gpio_irq_ack,
340 .mask_ack = ep93xx_gpio_irq_mask_ack,
341 .mask = ep93xx_gpio_irq_mask,
342 .unmask = ep93xx_gpio_irq_unmask,
343 .set_type = ep93xx_gpio_irq_type,
344};
345
346 143
347void __init ep93xx_init_irq(void) 144void __init ep93xx_init_irq(void)
348{ 145{
349 int gpio_irq;
350
351 vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0); 146 vic_init(EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
352 vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0); 147 vic_init(EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK, 0);
353 148
354 for (gpio_irq = gpio_to_irq(0); 149 ep93xx_gpio_init_irq();
355 gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
356 set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
357 set_irq_handler(gpio_irq, handle_level_irq);
358 set_irq_flags(gpio_irq, IRQF_VALID);
359 }
360
361 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
362 set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
363 set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
364 set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
365 set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
366 set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
367 set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
368 set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
369 set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
370} 150}
371 151
372 152