diff options
Diffstat (limited to 'arch/mips/jz4740/gpio.c')
-rw-r--r-- | arch/mips/jz4740/gpio.c | 140 |
1 files changed, 38 insertions, 102 deletions
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 4397972949fa..e1ddb95c05e3 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | 19 | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/syscore_ops.h> | ||
22 | #include <linux/io.h> | 20 | #include <linux/io.h> |
23 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
24 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
@@ -30,6 +28,8 @@ | |||
30 | 28 | ||
31 | #include <asm/mach-jz4740/base.h> | 29 | #include <asm/mach-jz4740/base.h> |
32 | 30 | ||
31 | #include "irq.h" | ||
32 | |||
33 | #define JZ4740_GPIO_BASE_A (32*0) | 33 | #define JZ4740_GPIO_BASE_A (32*0) |
34 | #define JZ4740_GPIO_BASE_B (32*1) | 34 | #define JZ4740_GPIO_BASE_B (32*1) |
35 | #define JZ4740_GPIO_BASE_C (32*2) | 35 | #define JZ4740_GPIO_BASE_C (32*2) |
@@ -77,14 +77,10 @@ | |||
77 | struct jz_gpio_chip { | 77 | struct jz_gpio_chip { |
78 | unsigned int irq; | 78 | unsigned int irq; |
79 | unsigned int irq_base; | 79 | unsigned int irq_base; |
80 | uint32_t wakeup; | ||
81 | uint32_t suspend_mask; | ||
82 | uint32_t edge_trigger_both; | 80 | uint32_t edge_trigger_both; |
83 | 81 | ||
84 | void __iomem *base; | 82 | void __iomem *base; |
85 | 83 | ||
86 | spinlock_t lock; | ||
87 | |||
88 | struct gpio_chip gpio_chip; | 84 | struct gpio_chip gpio_chip; |
89 | }; | 85 | }; |
90 | 86 | ||
@@ -102,7 +98,8 @@ static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *g | |||
102 | 98 | ||
103 | static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data) | 99 | static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data) |
104 | { | 100 | { |
105 | return irq_data_get_irq_chip_data(data); | 101 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); |
102 | return gc->private; | ||
106 | } | 103 | } |
107 | 104 | ||
108 | static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) | 105 | static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) |
@@ -304,21 +301,15 @@ static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) | |||
304 | { | 301 | { |
305 | uint32_t flag; | 302 | uint32_t flag; |
306 | unsigned int gpio_irq; | 303 | unsigned int gpio_irq; |
307 | unsigned int gpio_bank; | ||
308 | struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc); | 304 | struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc); |
309 | 305 | ||
310 | gpio_bank = JZ4740_IRQ_GPIO0 - irq; | ||
311 | |||
312 | flag = readl(chip->base + JZ_REG_GPIO_FLAG); | 306 | flag = readl(chip->base + JZ_REG_GPIO_FLAG); |
313 | |||
314 | if (!flag) | 307 | if (!flag) |
315 | return; | 308 | return; |
316 | 309 | ||
317 | gpio_irq = __fls(flag); | 310 | gpio_irq = chip->irq_base + __fls(flag); |
318 | 311 | ||
319 | jz_gpio_check_trigger_both(chip, irq); | 312 | jz_gpio_check_trigger_both(chip, gpio_irq); |
320 | |||
321 | gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0); | ||
322 | 313 | ||
323 | generic_handle_irq(gpio_irq); | 314 | generic_handle_irq(gpio_irq); |
324 | }; | 315 | }; |
@@ -329,18 +320,12 @@ static inline void jz_gpio_set_irq_bit(struct irq_data *data, unsigned int reg) | |||
329 | writel(IRQ_TO_BIT(data->irq), chip->base + reg); | 320 | writel(IRQ_TO_BIT(data->irq), chip->base + reg); |
330 | } | 321 | } |
331 | 322 | ||
332 | static void jz_gpio_irq_mask(struct irq_data *data) | ||
333 | { | ||
334 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET); | ||
335 | }; | ||
336 | |||
337 | static void jz_gpio_irq_unmask(struct irq_data *data) | 323 | static void jz_gpio_irq_unmask(struct irq_data *data) |
338 | { | 324 | { |
339 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); | 325 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); |
340 | 326 | ||
341 | jz_gpio_check_trigger_both(chip, data->irq); | 327 | jz_gpio_check_trigger_both(chip, data->irq); |
342 | 328 | irq_gc_unmask_enable_reg(data); | |
343 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR); | ||
344 | }; | 329 | }; |
345 | 330 | ||
346 | /* TODO: Check if function is gpio */ | 331 | /* TODO: Check if function is gpio */ |
@@ -353,18 +338,13 @@ static unsigned int jz_gpio_irq_startup(struct irq_data *data) | |||
353 | 338 | ||
354 | static void jz_gpio_irq_shutdown(struct irq_data *data) | 339 | static void jz_gpio_irq_shutdown(struct irq_data *data) |
355 | { | 340 | { |
356 | jz_gpio_irq_mask(data); | 341 | irq_gc_mask_disable_reg(data); |
357 | 342 | ||
358 | /* Set direction to input */ | 343 | /* Set direction to input */ |
359 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); | 344 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR); |
360 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR); | 345 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR); |
361 | } | 346 | } |
362 | 347 | ||
363 | static void jz_gpio_irq_ack(struct irq_data *data) | ||
364 | { | ||
365 | jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR); | ||
366 | }; | ||
367 | |||
368 | static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) | 348 | static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) |
369 | { | 349 | { |
370 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); | 350 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); |
@@ -408,35 +388,13 @@ static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) | |||
408 | static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) | 388 | static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on) |
409 | { | 389 | { |
410 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); | 390 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data); |
411 | spin_lock(&chip->lock); | ||
412 | if (on) | ||
413 | chip->wakeup |= IRQ_TO_BIT(data->irq); | ||
414 | else | ||
415 | chip->wakeup &= ~IRQ_TO_BIT(data->irq); | ||
416 | spin_unlock(&chip->lock); | ||
417 | 391 | ||
392 | irq_gc_set_wake(data, on); | ||
418 | irq_set_irq_wake(chip->irq, on); | 393 | irq_set_irq_wake(chip->irq, on); |
394 | |||
419 | return 0; | 395 | return 0; |
420 | } | 396 | } |
421 | 397 | ||
422 | static struct irq_chip jz_gpio_irq_chip = { | ||
423 | .name = "GPIO", | ||
424 | .irq_mask = jz_gpio_irq_mask, | ||
425 | .irq_unmask = jz_gpio_irq_unmask, | ||
426 | .irq_ack = jz_gpio_irq_ack, | ||
427 | .irq_startup = jz_gpio_irq_startup, | ||
428 | .irq_shutdown = jz_gpio_irq_shutdown, | ||
429 | .irq_set_type = jz_gpio_irq_set_type, | ||
430 | .irq_set_wake = jz_gpio_irq_set_wake, | ||
431 | .flags = IRQCHIP_SET_TYPE_MASKED, | ||
432 | }; | ||
433 | |||
434 | /* | ||
435 | * This lock class tells lockdep that GPIO irqs are in a different | ||
436 | * category than their parents, so it won't report false recursion. | ||
437 | */ | ||
438 | static struct lock_class_key gpio_lock_class; | ||
439 | |||
440 | #define JZ4740_GPIO_CHIP(_bank) { \ | 398 | #define JZ4740_GPIO_CHIP(_bank) { \ |
441 | .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ | 399 | .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ |
442 | .gpio_chip = { \ | 400 | .gpio_chip = { \ |
@@ -458,64 +416,44 @@ static struct jz_gpio_chip jz4740_gpio_chips[] = { | |||
458 | JZ4740_GPIO_CHIP(D), | 416 | JZ4740_GPIO_CHIP(D), |
459 | }; | 417 | }; |
460 | 418 | ||
461 | static void jz4740_gpio_suspend_chip(struct jz_gpio_chip *chip) | 419 | static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) |
462 | { | ||
463 | chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); | ||
464 | writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); | ||
465 | writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); | ||
466 | } | ||
467 | |||
468 | static int jz4740_gpio_suspend(void) | ||
469 | { | ||
470 | int i; | ||
471 | |||
472 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); i++) | ||
473 | jz4740_gpio_suspend_chip(&jz4740_gpio_chips[i]); | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static void jz4740_gpio_resume_chip(struct jz_gpio_chip *chip) | ||
479 | { | 420 | { |
480 | uint32_t mask = chip->suspend_mask; | 421 | struct irq_chip_generic *gc; |
422 | struct irq_chip_type *ct; | ||
481 | 423 | ||
482 | writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); | 424 | chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); |
483 | writel(mask, chip->base + JZ_REG_GPIO_MASK_SET); | ||
484 | } | ||
485 | 425 | ||
486 | static void jz4740_gpio_resume(void) | 426 | chip->irq = JZ4740_IRQ_INTC_GPIO(id); |
487 | { | 427 | irq_set_handler_data(chip->irq, chip); |
488 | int i; | 428 | irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler); |
489 | 429 | ||
490 | for (i = ARRAY_SIZE(jz4740_gpio_chips) - 1; i >= 0 ; i--) | 430 | gc = irq_alloc_generic_chip(chip->gpio_chip.label, 1, chip->irq_base, |
491 | jz4740_gpio_resume_chip(&jz4740_gpio_chips[i]); | 431 | chip->base, handle_level_irq); |
492 | } | ||
493 | 432 | ||
494 | static struct syscore_ops jz4740_gpio_syscore_ops = { | 433 | gc->wake_enabled = IRQ_MSK(chip->gpio_chip.ngpio); |
495 | .suspend = jz4740_gpio_suspend, | 434 | gc->private = chip; |
496 | .resume = jz4740_gpio_resume, | ||
497 | }; | ||
498 | 435 | ||
499 | static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) | 436 | ct = gc->chip_types; |
500 | { | 437 | ct->regs.enable = JZ_REG_GPIO_MASK_CLEAR; |
501 | int irq; | 438 | ct->regs.disable = JZ_REG_GPIO_MASK_SET; |
439 | ct->regs.ack = JZ_REG_GPIO_FLAG_CLEAR; | ||
502 | 440 | ||
503 | spin_lock_init(&chip->lock); | 441 | ct->chip.name = "GPIO"; |
442 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | ||
443 | ct->chip.irq_unmask = jz_gpio_irq_unmask; | ||
444 | ct->chip.irq_ack = irq_gc_ack_set_bit; | ||
445 | ct->chip.irq_suspend = jz4740_irq_suspend; | ||
446 | ct->chip.irq_resume = jz4740_irq_resume; | ||
447 | ct->chip.irq_startup = jz_gpio_irq_startup; | ||
448 | ct->chip.irq_shutdown = jz_gpio_irq_shutdown; | ||
449 | ct->chip.irq_set_type = jz_gpio_irq_set_type; | ||
450 | ct->chip.irq_set_wake = jz_gpio_irq_set_wake; | ||
451 | ct->chip.flags = IRQCHIP_SET_TYPE_MASKED; | ||
504 | 452 | ||
505 | chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); | 453 | irq_setup_generic_chip(gc, IRQ_MSK(chip->gpio_chip.ngpio), |
454 | IRQ_GC_INIT_NESTED_LOCK, 0, IRQ_NOPROBE | IRQ_LEVEL); | ||
506 | 455 | ||
507 | gpiochip_add(&chip->gpio_chip); | 456 | gpiochip_add(&chip->gpio_chip); |
508 | |||
509 | chip->irq = JZ4740_IRQ_INTC_GPIO(id); | ||
510 | irq_set_handler_data(chip->irq, chip); | ||
511 | irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler); | ||
512 | |||
513 | for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { | ||
514 | irq_set_lockdep_class(irq, &gpio_lock_class); | ||
515 | irq_set_chip_data(irq, chip); | ||
516 | irq_set_chip_and_handler(irq, &jz_gpio_irq_chip, | ||
517 | handle_level_irq); | ||
518 | } | ||
519 | } | 457 | } |
520 | 458 | ||
521 | static int __init jz4740_gpio_init(void) | 459 | static int __init jz4740_gpio_init(void) |
@@ -525,8 +463,6 @@ static int __init jz4740_gpio_init(void) | |||
525 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) | 463 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) |
526 | jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); | 464 | jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); |
527 | 465 | ||
528 | register_syscore_ops(&jz4740_gpio_syscore_ops); | ||
529 | |||
530 | printk(KERN_INFO "JZ4740 GPIO initialized\n"); | 466 | printk(KERN_INFO "JZ4740 GPIO initialized\n"); |
531 | 467 | ||
532 | return 0; | 468 | return 0; |