aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ep93xx
diff options
context:
space:
mode:
authorHartley Sweeten <hartleys@visionengravers.com>2010-02-23 15:41:17 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-02-24 16:08:36 -0500
commitd056ab78558c03e6d31c031f7b83f0cb10bee7d4 (patch)
tree7ea0c3f75d43986031c352550190bc3bc4f4b7fa /arch/arm/mach-ep93xx
parentba7c6a3bccd25abd3c19d3655ecb1cc4d258271b (diff)
ARM: 5954/1: ep93xx: move gpio interrupt support to gpio.c
The GPIO support in core.c handles the interrupt support for GPIO ports A, B, and F. The gpiolib implementation in gpio.c needs to access the function ep93xx_gpio_int_mask when a gpio pin is made an output and ep93xx_gpio_update_int_params in order to update the registers. Moving this support from core.c to gpio.c allows making the two functions static. It also keeps all the GPIO handling together in one file. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Acked-by: Ryan Mallon <ryan@bluewatersys.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r--arch/arm/mach-ep93xx/core.c224
-rw-r--r--arch/arm/mach-ep93xx/gpio.c235
2 files changed, 233 insertions, 226 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
diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c
index 1ea8871e03a9..cc377ae8c428 100644
--- a/arch/arm/mach-ep93xx/gpio.c
+++ b/arch/arm/mach-ep93xx/gpio.c
@@ -13,6 +13,8 @@
13 * published by the Free Software Foundation. 13 * published by the Free Software Foundation.
14 */ 14 */
15 15
16#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
17
16#include <linux/init.h> 18#include <linux/init.h>
17#include <linux/module.h> 19#include <linux/module.h>
18#include <linux/seq_file.h> 20#include <linux/seq_file.h>
@@ -22,6 +24,235 @@
22 24
23#include <mach/hardware.h> 25#include <mach/hardware.h>
24 26
27/*************************************************************************
28 * GPIO handling for EP93xx
29 *************************************************************************/
30static unsigned char gpio_int_unmasked[3];
31static unsigned char gpio_int_enabled[3];
32static unsigned char gpio_int_type1[3];
33static unsigned char gpio_int_type2[3];
34static unsigned char gpio_int_debounce[3];
35
36/* Port ordering is: A B F */
37static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
38static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
39static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
40static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
41static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
42
43void ep93xx_gpio_update_int_params(unsigned port)
44{
45 BUG_ON(port > 2);
46
47 __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
48
49 __raw_writeb(gpio_int_type2[port],
50 EP93XX_GPIO_REG(int_type2_register_offset[port]));
51
52 __raw_writeb(gpio_int_type1[port],
53 EP93XX_GPIO_REG(int_type1_register_offset[port]));
54
55 __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
56 EP93XX_GPIO_REG(int_en_register_offset[port]));
57}
58
59void ep93xx_gpio_int_mask(unsigned line)
60{
61 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
62}
63
64void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
65{
66 int line = irq_to_gpio(irq);
67 int port = line >> 3;
68 int port_mask = 1 << (line & 7);
69
70 if (enable)
71 gpio_int_debounce[port] |= port_mask;
72 else
73 gpio_int_debounce[port] &= ~port_mask;
74
75 __raw_writeb(gpio_int_debounce[port],
76 EP93XX_GPIO_REG(int_debounce_register_offset[port]));
77}
78EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
79
80static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
81{
82 unsigned char status;
83 int i;
84
85 status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
86 for (i = 0; i < 8; i++) {
87 if (status & (1 << i)) {
88 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
89 generic_handle_irq(gpio_irq);
90 }
91 }
92
93 status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
94 for (i = 0; i < 8; i++) {
95 if (status & (1 << i)) {
96 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
97 generic_handle_irq(gpio_irq);
98 }
99 }
100}
101
102static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
103{
104 /*
105 * map discontiguous hw irq range to continous sw irq range:
106 *
107 * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
108 */
109 int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
110 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
111
112 generic_handle_irq(gpio_irq);
113}
114
115static void ep93xx_gpio_irq_ack(unsigned int irq)
116{
117 int line = irq_to_gpio(irq);
118 int port = line >> 3;
119 int port_mask = 1 << (line & 7);
120
121 if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
122 gpio_int_type2[port] ^= port_mask; /* switch edge direction */
123 ep93xx_gpio_update_int_params(port);
124 }
125
126 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
127}
128
129static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
130{
131 int line = irq_to_gpio(irq);
132 int port = line >> 3;
133 int port_mask = 1 << (line & 7);
134
135 if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
136 gpio_int_type2[port] ^= port_mask; /* switch edge direction */
137
138 gpio_int_unmasked[port] &= ~port_mask;
139 ep93xx_gpio_update_int_params(port);
140
141 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
142}
143
144static void ep93xx_gpio_irq_mask(unsigned int irq)
145{
146 int line = irq_to_gpio(irq);
147 int port = line >> 3;
148
149 gpio_int_unmasked[port] &= ~(1 << (line & 7));
150 ep93xx_gpio_update_int_params(port);
151}
152
153static void ep93xx_gpio_irq_unmask(unsigned int irq)
154{
155 int line = irq_to_gpio(irq);
156 int port = line >> 3;
157
158 gpio_int_unmasked[port] |= 1 << (line & 7);
159 ep93xx_gpio_update_int_params(port);
160}
161
162/*
163 * gpio_int_type1 controls whether the interrupt is level (0) or
164 * edge (1) triggered, while gpio_int_type2 controls whether it
165 * triggers on low/falling (0) or high/rising (1).
166 */
167static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
168{
169 struct irq_desc *desc = irq_desc + irq;
170 const int gpio = irq_to_gpio(irq);
171 const int port = gpio >> 3;
172 const int port_mask = 1 << (gpio & 7);
173
174 gpio_direction_input(gpio);
175
176 switch (type) {
177 case IRQ_TYPE_EDGE_RISING:
178 gpio_int_type1[port] |= port_mask;
179 gpio_int_type2[port] |= port_mask;
180 desc->handle_irq = handle_edge_irq;
181 break;
182 case IRQ_TYPE_EDGE_FALLING:
183 gpio_int_type1[port] |= port_mask;
184 gpio_int_type2[port] &= ~port_mask;
185 desc->handle_irq = handle_edge_irq;
186 break;
187 case IRQ_TYPE_LEVEL_HIGH:
188 gpio_int_type1[port] &= ~port_mask;
189 gpio_int_type2[port] |= port_mask;
190 desc->handle_irq = handle_level_irq;
191 break;
192 case IRQ_TYPE_LEVEL_LOW:
193 gpio_int_type1[port] &= ~port_mask;
194 gpio_int_type2[port] &= ~port_mask;
195 desc->handle_irq = handle_level_irq;
196 break;
197 case IRQ_TYPE_EDGE_BOTH:
198 gpio_int_type1[port] |= port_mask;
199 /* set initial polarity based on current input level */
200 if (gpio_get_value(gpio))
201 gpio_int_type2[port] &= ~port_mask; /* falling */
202 else
203 gpio_int_type2[port] |= port_mask; /* rising */
204 desc->handle_irq = handle_edge_irq;
205 break;
206 default:
207 pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
208 return -EINVAL;
209 }
210
211 gpio_int_enabled[port] |= port_mask;
212
213 desc->status &= ~IRQ_TYPE_SENSE_MASK;
214 desc->status |= type & IRQ_TYPE_SENSE_MASK;
215
216 ep93xx_gpio_update_int_params(port);
217
218 return 0;
219}
220
221static struct irq_chip ep93xx_gpio_irq_chip = {
222 .name = "GPIO",
223 .ack = ep93xx_gpio_irq_ack,
224 .mask_ack = ep93xx_gpio_irq_mask_ack,
225 .mask = ep93xx_gpio_irq_mask,
226 .unmask = ep93xx_gpio_irq_unmask,
227 .set_type = ep93xx_gpio_irq_type,
228};
229
230void __init ep93xx_gpio_init_irq(void)
231{
232 int gpio_irq;
233
234 for (gpio_irq = gpio_to_irq(0);
235 gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
236 set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
237 set_irq_handler(gpio_irq, handle_level_irq);
238 set_irq_flags(gpio_irq, IRQF_VALID);
239 }
240
241 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
242 set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
243 set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
244 set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
245 set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
246 set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
247 set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
248 set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
249 set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
250}
251
252
253/*************************************************************************
254 * gpiolib interface for EP93xx on-chip GPIOs
255 *************************************************************************/
25struct ep93xx_gpio_chip { 256struct ep93xx_gpio_chip {
26 struct gpio_chip chip; 257 struct gpio_chip chip;
27 258
@@ -31,10 +262,6 @@ struct ep93xx_gpio_chip {
31 262
32#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) 263#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip)
33 264
34/* From core.c */
35extern void ep93xx_gpio_int_mask(unsigned line);
36extern void ep93xx_gpio_update_int_params(unsigned port);
37
38static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 265static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
39{ 266{
40 struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); 267 struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);