aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-ep93xx/core.c147
-rw-r--r--include/asm-arm/arch-ep93xx/gpio.h27
-rw-r--r--include/asm-arm/arch-ep93xx/irqs.h6
3 files changed, 82 insertions, 98 deletions
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 8a7340661377..58957d7a5763 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -157,35 +157,35 @@ static unsigned char gpio_int_enabled[3];
157static unsigned char gpio_int_type1[3]; 157static unsigned char gpio_int_type1[3];
158static unsigned char gpio_int_type2[3]; 158static unsigned char gpio_int_type2[3];
159 159
160static void update_gpio_int_params(int abf) 160/* Port ordering is: A B F */
161static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
162static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
163static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
164static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x5c };
165
166static void update_gpio_int_params(unsigned port)
161{ 167{
162 if (abf == 0) { 168 BUG_ON(port > 2);
163 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
164 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
165 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
166 __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
167 } else if (abf == 1) {
168 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
169 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
170 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
171 __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
172 } else if (abf == 2) {
173 __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
174 __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
175 __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
176 __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
177 } else {
178 BUG();
179 }
180}
181 169
170 __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
171
172 __raw_writeb(gpio_int_type2[port],
173 EP93XX_GPIO_REG(int_type2_register_offset[port]));
174
175 __raw_writeb(gpio_int_type1[port],
176 EP93XX_GPIO_REG(int_type1_register_offset[port]));
177
178 __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
179 EP93XX_GPIO_REG(int_en_register_offset[port]));
180}
182 181
183static unsigned char data_register_offset[8] = { 182/* Port ordering is: A B F D E C G H */
184 0x00, 0x04, 0x08, 0x0c, 0x20, 0x30, 0x38, 0x40, 183static const u8 data_register_offset[8] = {
184 0x00, 0x04, 0x30, 0x0c, 0x20, 0x08, 0x38, 0x40,
185}; 185};
186 186
187static unsigned char data_direction_register_offset[8] = { 187static const u8 data_direction_register_offset[8] = {
188 0x10, 0x14, 0x18, 0x1c, 0x24, 0x34, 0x3c, 0x44, 188 0x10, 0x14, 0x34, 0x1c, 0x24, 0x18, 0x3c, 0x44,
189}; 189};
190 190
191static void ep93xx_gpio_set_direction(unsigned line, int direction) 191static void ep93xx_gpio_set_direction(unsigned line, int direction)
@@ -199,14 +199,10 @@ static void ep93xx_gpio_set_direction(unsigned line, int direction)
199 199
200 local_irq_save(flags); 200 local_irq_save(flags);
201 if (direction == GPIO_OUT) { 201 if (direction == GPIO_OUT) {
202 if (line >= 0 && line < 16) { 202 if (line >= 0 && line <= EP93XX_GPIO_LINE_MAX_IRQ) {
203 /* Port A/B. */ 203 /* Port A/B/F */
204 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); 204 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
205 update_gpio_int_params(line >> 3); 205 update_gpio_int_params(line >> 3);
206 } else if (line >= 40 && line < 48) {
207 /* Port F. */
208 gpio_int_unmasked[2] &= ~(1 << (line & 7));
209 update_gpio_int_params(2);
210 } 206 }
211 207
212 v = __raw_readb(data_direction_register); 208 v = __raw_readb(data_direction_register);
@@ -228,7 +224,7 @@ EXPORT_SYMBOL(gpio_line_config);
228 224
229int gpio_direction_input(unsigned gpio) 225int gpio_direction_input(unsigned gpio)
230{ 226{
231 if (gpio > EP93XX_GPIO_LINE_H(7)) 227 if (gpio > EP93XX_GPIO_LINE_MAX)
232 return -EINVAL; 228 return -EINVAL;
233 229
234 ep93xx_gpio_set_direction(gpio, GPIO_IN); 230 ep93xx_gpio_set_direction(gpio, GPIO_IN);
@@ -239,7 +235,7 @@ EXPORT_SYMBOL(gpio_direction_input);
239 235
240int gpio_direction_output(unsigned gpio, int value) 236int gpio_direction_output(unsigned gpio, int value)
241{ 237{
242 if (gpio > EP93XX_GPIO_LINE_H(7)) 238 if (gpio > EP93XX_GPIO_LINE_MAX)
243 return -EINVAL; 239 return -EINVAL;
244 240
245 gpio_set_value(gpio, value); 241 gpio_set_value(gpio, value);
@@ -290,47 +286,50 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
290 status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); 286 status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
291 for (i = 0; i < 8; i++) { 287 for (i = 0; i < 8; i++) {
292 if (status & (1 << i)) { 288 if (status & (1 << i)) {
293 desc = irq_desc + IRQ_EP93XX_GPIO(0) + i; 289 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
294 desc_handle_irq(IRQ_EP93XX_GPIO(0) + i, desc); 290 desc = irq_desc + gpio_irq;
291 desc_handle_irq(gpio_irq, desc);
295 } 292 }
296 } 293 }
297 294
298 status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); 295 status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
299 for (i = 0; i < 8; i++) { 296 for (i = 0; i < 8; i++) {
300 if (status & (1 << i)) { 297 if (status & (1 << i)) {
301 desc = irq_desc + IRQ_EP93XX_GPIO(8) + i; 298 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
302 desc_handle_irq(IRQ_EP93XX_GPIO(8) + i, desc); 299 desc = irq_desc + gpio_irq;
300 desc_handle_irq(gpio_irq, desc);
303 } 301 }
304 } 302 }
305} 303}
306 304
307static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) 305static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
308{ 306{
309 int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4); 307 /*
308 * map discontiguous hw irq range to continous sw irq range:
309 *
310 * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
311 */
312 int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
313 int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
310 314
311 desc_handle_irq(gpio_irq, irq_desc + gpio_irq); 315 desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
312} 316}
313 317
314static void ep93xx_gpio_irq_mask_ack(unsigned int irq) 318static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
315{ 319{
316 int line = irq - IRQ_EP93XX_GPIO(0); 320 int line = irq_to_gpio(irq);
317 int port = line >> 3; 321 int port = line >> 3;
322 int port_mask = 1 << (line & 7);
318 323
319 gpio_int_unmasked[port] &= ~(1 << (line & 7)); 324 gpio_int_unmasked[port] &= ~port_mask;
320 update_gpio_int_params(port); 325 update_gpio_int_params(port);
321 326
322 if (port == 0) { 327 __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
323 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
324 } else if (port == 1) {
325 __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
326 } else if (port == 2) {
327 __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
328 }
329} 328}
330 329
331static void ep93xx_gpio_irq_mask(unsigned int irq) 330static void ep93xx_gpio_irq_mask(unsigned int irq)
332{ 331{
333 int line = irq - IRQ_EP93XX_GPIO(0); 332 int line = irq_to_gpio(irq);
334 int port = line >> 3; 333 int port = line >> 3;
335 334
336 gpio_int_unmasked[port] &= ~(1 << (line & 7)); 335 gpio_int_unmasked[port] &= ~(1 << (line & 7));
@@ -339,7 +338,7 @@ static void ep93xx_gpio_irq_mask(unsigned int irq)
339 338
340static void ep93xx_gpio_irq_unmask(unsigned int irq) 339static void ep93xx_gpio_irq_unmask(unsigned int irq)
341{ 340{
342 int line = irq - IRQ_EP93XX_GPIO(0); 341 int line = irq_to_gpio(irq);
343 int port = line >> 3; 342 int port = line >> 3;
344 343
345 gpio_int_unmasked[port] |= 1 << (line & 7); 344 gpio_int_unmasked[port] |= 1 << (line & 7);
@@ -354,37 +353,30 @@ static void ep93xx_gpio_irq_unmask(unsigned int irq)
354 */ 353 */
355static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) 354static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
356{ 355{
357 int port; 356 const int gpio = irq_to_gpio(irq);
358 int line; 357 const int port = gpio >> 3;
358 const int port_mask = 1 << (gpio & 7);
359 359
360 line = irq - IRQ_EP93XX_GPIO(0); 360 ep93xx_gpio_set_direction(gpio, GPIO_IN);
361 if (line >= 0 && line < 16) {
362 ep93xx_gpio_set_direction(line, GPIO_IN);
363 } else {
364 ep93xx_gpio_set_direction(EP93XX_GPIO_LINE_F(line-16), GPIO_IN);
365 }
366
367 port = line >> 3;
368 line &= 7;
369 361
370 if (type & IRQT_RISING) { 362 if (type & IRQT_RISING) {
371 gpio_int_enabled[port] |= 1 << line; 363 gpio_int_enabled[port] |= port_mask;
372 gpio_int_type1[port] |= 1 << line; 364 gpio_int_type1[port] |= port_mask;
373 gpio_int_type2[port] |= 1 << line; 365 gpio_int_type2[port] |= port_mask;
374 } else if (type & IRQT_FALLING) { 366 } else if (type & IRQT_FALLING) {
375 gpio_int_enabled[port] |= 1 << line; 367 gpio_int_enabled[port] |= port_mask;
376 gpio_int_type1[port] |= 1 << line; 368 gpio_int_type1[port] |= port_mask;
377 gpio_int_type2[port] &= ~(1 << line); 369 gpio_int_type2[port] &= ~port_mask;
378 } else if (type & IRQT_HIGH) { 370 } else if (type & IRQT_HIGH) {
379 gpio_int_enabled[port] |= 1 << line; 371 gpio_int_enabled[port] |= port_mask;
380 gpio_int_type1[port] &= ~(1 << line); 372 gpio_int_type1[port] &= ~port_mask;
381 gpio_int_type2[port] |= 1 << line; 373 gpio_int_type2[port] |= port_mask;
382 } else if (type & IRQT_LOW) { 374 } else if (type & IRQT_LOW) {
383 gpio_int_enabled[port] |= 1 << line; 375 gpio_int_enabled[port] |= port_mask;
384 gpio_int_type1[port] &= ~(1 << line); 376 gpio_int_type1[port] &= ~port_mask;
385 gpio_int_type2[port] &= ~(1 << line); 377 gpio_int_type2[port] &= ~port_mask;
386 } else { 378 } else {
387 gpio_int_enabled[port] &= ~(1 << line); 379 gpio_int_enabled[port] &= ~port_mask;
388 } 380 }
389 update_gpio_int_params(port); 381 update_gpio_int_params(port);
390 382
@@ -402,15 +394,16 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
402 394
403void __init ep93xx_init_irq(void) 395void __init ep93xx_init_irq(void)
404{ 396{
405 int irq; 397 int gpio_irq;
406 398
407 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); 399 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
408 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); 400 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
409 401
410 for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) { 402 for (gpio_irq = gpio_to_irq(0);
411 set_irq_chip(irq, &ep93xx_gpio_irq_chip); 403 gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
412 set_irq_handler(irq, handle_level_irq); 404 set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
413 set_irq_flags(irq, IRQF_VALID); 405 set_irq_handler(gpio_irq, handle_level_irq);
406 set_irq_flags(gpio_irq, IRQF_VALID);
414 } 407 }
415 408
416 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); 409 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h
index fc1e57db5fac..cebb64be7e4b 100644
--- a/include/asm-arm/arch-ep93xx/gpio.h
+++ b/include/asm-arm/arch-ep93xx/gpio.h
@@ -28,7 +28,7 @@
28#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) 28#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7)
29 29
30/* GPIO port C. */ 30/* GPIO port C. */
31#define EP93XX_GPIO_LINE_C(x) ((x) + 16) 31#define EP93XX_GPIO_LINE_C(x) ((x) + 40)
32#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) 32#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0)
33#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) 33#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1)
34#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) 34#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2)
@@ -61,7 +61,7 @@
61#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) 61#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7)
62 62
63/* GPIO port F. */ 63/* GPIO port F. */
64#define EP93XX_GPIO_LINE_F(x) ((x) + 40) 64#define EP93XX_GPIO_LINE_F(x) ((x) + 16)
65#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) 65#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0)
66#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) 66#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1)
67#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) 67#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2)
@@ -93,11 +93,17 @@
93#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) 93#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6)
94#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) 94#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7)
95 95
96/* maximum value for gpio line identifiers */
97#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7)
98
99/* maximum value for irq capable line identifiers */
100#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7)
101
96/* new generic GPIO API - see Documentation/gpio.txt */ 102/* new generic GPIO API - see Documentation/gpio.txt */
97 103
98static inline int gpio_request(unsigned gpio, const char *label) 104static inline int gpio_request(unsigned gpio, const char *label)
99{ 105{
100 if (gpio > EP93XX_GPIO_LINE_H(7)) 106 if (gpio > EP93XX_GPIO_LINE_MAX)
101 return -EINVAL; 107 return -EINVAL;
102 return 0; 108 return 0;
103} 109}
@@ -116,29 +122,20 @@ void gpio_set_value(unsigned gpio, int value);
116/* 122/*
117 * Map GPIO A0..A7 (0..7) to irq 64..71, 123 * Map GPIO A0..A7 (0..7) to irq 64..71,
118 * B0..B7 (7..15) to irq 72..79, and 124 * B0..B7 (7..15) to irq 72..79, and
119 * F0..F7 (40..47) to irq 80..87. 125 * F0..F7 (16..24) to irq 80..87.
120 */ 126 */
121 127
122static inline int gpio_to_irq(unsigned gpio) 128static inline int gpio_to_irq(unsigned gpio)
123{ 129{
124 if (gpio <= EP93XX_GPIO_LINE_EGPIO15) 130 if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ)
125 return 64 + gpio; 131 return 64 + gpio;
126 132
127 if (gpio >= EP93XX_GPIO_LINE_F(0) && gpio <= EP93XX_GPIO_LINE_F(7))
128 return 80 + (gpio - EP93XX_GPIO_LINE_F(0));
129
130 return -EINVAL; 133 return -EINVAL;
131} 134}
132 135
133static inline int irq_to_gpio(unsigned irq) 136static inline int irq_to_gpio(unsigned irq)
134{ 137{
135 if (irq >= 64 && irq <= 79) 138 return irq - gpio_to_irq(0);
136 return irq - 64;
137
138 if (irq >= 80 && irq <= 87)
139 return (irq - 80) + EP93XX_GPIO_LINE_F(0);
140
141 return -EINVAL;
142} 139}
143 140
144/* obsolete specific GPIO API */ 141/* obsolete specific GPIO API */
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
index 2a8c63638c5e..53d4a68bfc88 100644
--- a/include/asm-arm/arch-ep93xx/irqs.h
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -67,12 +67,6 @@
67#define IRQ_EP93XX_SAI 60 67#define IRQ_EP93XX_SAI 60
68#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff 68#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
69 69
70/*
71 * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
72 * F0..F7 to 80..87.
73 */
74#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
75
76#define NR_EP93XX_IRQS (64 + 24) 70#define NR_EP93XX_IRQS (64 + 24)
77 71
78#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) 72#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))