]> git.karo-electronics.de Git - mv-sheeva.git/blob - arch/arm/mach-orion/irq.c
[ARM] Orion: IRQ support
[mv-sheeva.git] / arch / arm / mach-orion / irq.c
1 /*
2  * arch/arm/mach-orion/irq.c
3  *
4  * Core IRQ functions for Marvell Orion System On Chip
5  *
6  * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2. This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/irq.h>
16 #include <asm/gpio.h>
17 #include <asm/arch/orion.h>
18 #include "common.h"
19
20 /*****************************************************************************
21  * Orion GPIO IRQ
22  ****************************************************************************/
23 static void orion_gpio_irq_mask(u32 irq)
24 {
25         int pin = irq_to_gpio(irq);
26         orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
27 }
28
29 static void orion_gpio_irq_unmask(u32 irq)
30 {
31         int pin = irq_to_gpio(irq);
32         orion_setbits(GPIO_LEVEL_MASK, 1 << pin);
33 }
34
35 static int orion_gpio_set_irq_type(u32 irq, u32 type)
36 {
37         int pin = irq_to_gpio(irq);
38
39         if ((orion_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
40                 printk(KERN_ERR "orion_gpio_set_irq_type failed "
41                                 "(irq %d, pin %d).\n", irq, pin);
42                 return -EINVAL;
43         }
44
45         switch (type) {
46         case IRQT_HIGH:
47                 orion_clrbits(GPIO_IN_POL, (1 << pin));
48                 break;
49         case IRQT_LOW:
50                 orion_setbits(GPIO_IN_POL, (1 << pin));
51                 break;
52         default:
53                 printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
54                 return -EINVAL;
55         }
56
57         return 0;
58 }
59
60 static struct irq_chip orion_gpio_irq_chip = {
61         .name           = "Orion-IRQ-GPIO",
62         .ack            = orion_gpio_irq_mask,
63         .mask           = orion_gpio_irq_mask,
64         .unmask         = orion_gpio_irq_unmask,
65         .set_type       = orion_gpio_set_irq_type,
66 };
67
68 static void orion_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
69 {
70         int i;
71         u32 cause, shift;
72
73         BUG_ON(irq < IRQ_ORION_GPIO_0_7 || irq > IRQ_ORION_GPIO_24_31);
74         shift = (irq - IRQ_ORION_GPIO_0_7) * 8;
75         cause = orion_read(GPIO_EDGE_CAUSE) & orion_read(GPIO_LEVEL_MASK);
76         cause &= (0xff << shift);
77
78         for (i = shift; i < shift + 8; i++) {
79                 if (cause & (1 << i)) {
80                         int gpio_irq = i + IRQ_ORION_GPIO_START;
81                         if (gpio_irq > 0) {
82                                 desc = irq_desc + gpio_irq;
83                                 desc_handle_irq(gpio_irq, desc);
84                         } else {
85                                 printk(KERN_ERR "orion_gpio_irq_handler error, "
86                                                 "invalid irq %d\n", gpio_irq);
87                         }
88                 }
89         }
90 }
91
92 static void __init orion_init_gpio_irq(void)
93 {
94         int i;
95
96         /*
97          * Mask and clear GPIO IRQ interrupts
98          */
99         orion_write(GPIO_LEVEL_MASK, 0x0);
100         orion_write(GPIO_EDGE_CAUSE, 0x0);
101
102         /*
103          * Register chained level handlers for GPIO IRQs
104          */
105         for (i = IRQ_ORION_GPIO_START; i < NR_IRQS; i++) {
106                 set_irq_chip(i, &orion_gpio_irq_chip);
107                 set_irq_handler(i, handle_level_irq);
108                 set_irq_flags(i, IRQF_VALID);
109         }
110         set_irq_chained_handler(IRQ_ORION_GPIO_0_7, orion_gpio_irq_handler);
111         set_irq_chained_handler(IRQ_ORION_GPIO_8_15, orion_gpio_irq_handler);
112         set_irq_chained_handler(IRQ_ORION_GPIO_16_23, orion_gpio_irq_handler);
113         set_irq_chained_handler(IRQ_ORION_GPIO_24_31, orion_gpio_irq_handler);
114 }
115
116 /*****************************************************************************
117  * Orion Main IRQ
118  ****************************************************************************/
119 static void orion_main_irq_mask(u32 irq)
120 {
121         orion_clrbits(MAIN_IRQ_MASK, 1 << irq);
122 }
123
124 static void orion_main_irq_unmask(u32 irq)
125 {
126         orion_setbits(MAIN_IRQ_MASK, 1 << irq);
127 }
128
129 static struct irq_chip orion_main_irq_chip = {
130         .name           = "Orion-IRQ-Main",
131         .ack            = orion_main_irq_mask,
132         .mask           = orion_main_irq_mask,
133         .unmask         = orion_main_irq_unmask,
134 };
135
136 static void __init orion_init_main_irq(void)
137 {
138         int i;
139
140         /*
141          * Mask and clear Main IRQ interrupts
142          */
143         orion_write(MAIN_IRQ_MASK, 0x0);
144         orion_write(MAIN_IRQ_CAUSE, 0x0);
145
146         /*
147          * Register level handler for Main IRQs
148          */
149         for (i = 0; i < IRQ_ORION_GPIO_START; i++) {
150                 set_irq_chip(i, &orion_main_irq_chip);
151                 set_irq_handler(i, handle_level_irq);
152                 set_irq_flags(i, IRQF_VALID);
153         }
154 }
155
156 void __init orion_init_irq(void)
157 {
158         orion_init_main_irq();
159         orion_init_gpio_irq();
160 }