1
2
3
4
5
6
7
8
9
10
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/io.h>
18#include <mach/orion5x.h>
19#include <plat/irq.h>
20#include "common.h"
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47static void orion5x_gpio_irq_ack(u32 irq)
48{
49 int pin = irq_to_gpio(irq);
50 if (irq_desc[irq].status & IRQ_LEVEL)
51
52
53
54 orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
55 else
56
57
58
59 orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
60}
61
62static void orion5x_gpio_irq_mask(u32 irq)
63{
64 int pin = irq_to_gpio(irq);
65 if (irq_desc[irq].status & IRQ_LEVEL)
66 orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
67 else
68 orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
69}
70
71static void orion5x_gpio_irq_unmask(u32 irq)
72{
73 int pin = irq_to_gpio(irq);
74 if (irq_desc[irq].status & IRQ_LEVEL)
75 orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
76 else
77 orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
78}
79
80static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
81{
82 int pin = irq_to_gpio(irq);
83 struct irq_desc *desc;
84
85 if ((readl(GPIO_IO_CONF) & (1 << pin)) == 0) {
86 printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
87 "(irq %d, pin %d).\n", irq, pin);
88 return -EINVAL;
89 }
90
91 desc = irq_desc + irq;
92
93 switch (type) {
94 case IRQ_TYPE_LEVEL_HIGH:
95 desc->handle_irq = handle_level_irq;
96 desc->status |= IRQ_LEVEL;
97 orion5x_clrbits(GPIO_IN_POL, (1 << pin));
98 break;
99 case IRQ_TYPE_LEVEL_LOW:
100 desc->handle_irq = handle_level_irq;
101 desc->status |= IRQ_LEVEL;
102 orion5x_setbits(GPIO_IN_POL, (1 << pin));
103 break;
104 case IRQ_TYPE_EDGE_RISING:
105 desc->handle_irq = handle_edge_irq;
106 desc->status &= ~IRQ_LEVEL;
107 orion5x_clrbits(GPIO_IN_POL, (1 << pin));
108 break;
109 case IRQ_TYPE_EDGE_FALLING:
110 desc->handle_irq = handle_edge_irq;
111 desc->status &= ~IRQ_LEVEL;
112 orion5x_setbits(GPIO_IN_POL, (1 << pin));
113 break;
114 case IRQ_TYPE_EDGE_BOTH:
115 desc->handle_irq = handle_edge_irq;
116 desc->status &= ~IRQ_LEVEL;
117
118
119
120 if ((readl(GPIO_IN_POL) ^ readl(GPIO_DATA_IN))
121 & (1 << pin))
122 orion5x_setbits(GPIO_IN_POL, (1 << pin));
123 else
124 orion5x_clrbits(GPIO_IN_POL, (1 << pin));
125
126 break;
127 default:
128 printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
129 return -EINVAL;
130 }
131
132 desc->status &= ~IRQ_TYPE_SENSE_MASK;
133 desc->status |= type & IRQ_TYPE_SENSE_MASK;
134
135 return 0;
136}
137
138static struct irq_chip orion5x_gpio_irq_chip = {
139 .name = "Orion-IRQ-GPIO",
140 .ack = orion5x_gpio_irq_ack,
141 .mask = orion5x_gpio_irq_mask,
142 .unmask = orion5x_gpio_irq_unmask,
143 .set_type = orion5x_gpio_set_irq_type,
144};
145
146static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
147{
148 u32 cause, offs, pin;
149
150 BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
151 offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
152 cause = (readl(GPIO_DATA_IN) & readl(GPIO_LEVEL_MASK)) |
153 (readl(GPIO_EDGE_CAUSE) & readl(GPIO_EDGE_MASK));
154
155 for (pin = offs; pin < offs + 8; pin++) {
156 if (cause & (1 << pin)) {
157 irq = gpio_to_irq(pin);
158 desc = irq_desc + irq;
159 if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
160
161 u32 polarity = readl(GPIO_IN_POL);
162 polarity ^= 1 << pin;
163 writel(polarity, GPIO_IN_POL);
164 }
165 desc_handle_irq(irq, desc);
166 }
167 }
168}
169
170static void __init orion5x_init_gpio_irq(void)
171{
172 int i;
173 struct irq_desc *desc;
174
175
176
177
178 writel(0x0, GPIO_LEVEL_MASK);
179 writel(0x0, GPIO_EDGE_MASK);
180 writel(0x0, GPIO_EDGE_CAUSE);
181
182
183
184
185
186 for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
187 set_irq_chip(i, &orion5x_gpio_irq_chip);
188 set_irq_handler(i, handle_level_irq);
189 desc = irq_desc + i;
190 desc->status |= IRQ_LEVEL;
191 set_irq_flags(i, IRQF_VALID);
192 }
193 set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
194 set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
195 set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
196 set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
197}
198
199
200
201
202static void __init orion5x_init_main_irq(void)
203{
204 orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
205}
206
207void __init orion5x_init_irq(void)
208{
209 orion5x_init_main_irq();
210 orion5x_init_gpio_irq();
211}
212