diff options
| -rw-r--r-- | arch/blackfin/mach-common/ints-priority-sc.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index 36ef4d17dd35..dec42acb5de0 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c | |||
| @@ -483,6 +483,10 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq, | |||
| 483 | static unsigned char irq2pint_lut[NR_PINTS]; | 483 | static unsigned char irq2pint_lut[NR_PINTS]; |
| 484 | static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; | 484 | static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS]; |
| 485 | 485 | ||
| 486 | static unsigned int gpio_both_edge_triggered[NR_PINT_SYS_IRQS]; | ||
| 487 | static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; | ||
| 488 | |||
| 489 | |||
| 486 | struct pin_int_t { | 490 | struct pin_int_t { |
| 487 | unsigned int mask_set; | 491 | unsigned int mask_set; |
| 488 | unsigned int mask_clear; | 492 | unsigned int mask_clear; |
| @@ -549,13 +553,20 @@ void init_pint_lut(void) | |||
| 549 | 553 | ||
| 550 | } | 554 | } |
| 551 | 555 | ||
| 552 | static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; | ||
| 553 | |||
| 554 | static void bfin_gpio_ack_irq(unsigned int irq) | 556 | static void bfin_gpio_ack_irq(unsigned int irq) |
| 555 | { | 557 | { |
| 556 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; | 558 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; |
| 559 | u32 pintbit = PINT_BIT(pint_val); | ||
| 560 | u8 bank = PINT_2_BANK(pint_val); | ||
| 561 | |||
| 562 | if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) { | ||
| 563 | if (pint[bank]->invert_set & pintbit) | ||
| 564 | pint[bank]->invert_clear = pintbit; | ||
| 565 | else | ||
| 566 | pint[bank]->invert_set = pintbit; | ||
| 567 | } | ||
| 568 | pint[bank]->request = pintbit; | ||
| 557 | 569 | ||
| 558 | pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val); | ||
| 559 | SSYNC(); | 570 | SSYNC(); |
| 560 | } | 571 | } |
| 561 | 572 | ||
| @@ -565,6 +576,13 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq) | |||
| 565 | u32 pintbit = PINT_BIT(pint_val); | 576 | u32 pintbit = PINT_BIT(pint_val); |
| 566 | u8 bank = PINT_2_BANK(pint_val); | 577 | u8 bank = PINT_2_BANK(pint_val); |
| 567 | 578 | ||
| 579 | if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) { | ||
| 580 | if (pint[bank]->invert_set & pintbit) | ||
| 581 | pint[bank]->invert_clear = pintbit; | ||
| 582 | else | ||
| 583 | pint[bank]->invert_set = pintbit; | ||
| 584 | } | ||
| 585 | |||
| 568 | pint[bank]->request = pintbit; | 586 | pint[bank]->request = pintbit; |
| 569 | pint[bank]->mask_clear = pintbit; | 587 | pint[bank]->mask_clear = pintbit; |
| 570 | SSYNC(); | 588 | SSYNC(); |
| @@ -593,7 +611,7 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) | |||
| 593 | { | 611 | { |
| 594 | unsigned int ret; | 612 | unsigned int ret; |
| 595 | char buf[8]; | 613 | char buf[8]; |
| 596 | u16 gpionr = irq - IRQ_PA0; | 614 | u16 gpionr = irq_to_gpio(irq); |
| 597 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; | 615 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; |
| 598 | 616 | ||
| 599 | if (pint_val == IRQ_NOT_AVAIL) { | 617 | if (pint_val == IRQ_NOT_AVAIL) { |
| @@ -618,9 +636,11 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq) | |||
| 618 | 636 | ||
| 619 | static void bfin_gpio_irq_shutdown(unsigned int irq) | 637 | static void bfin_gpio_irq_shutdown(unsigned int irq) |
| 620 | { | 638 | { |
| 639 | u16 gpionr = irq_to_gpio(irq); | ||
| 640 | |||
| 621 | bfin_gpio_mask_irq(irq); | 641 | bfin_gpio_mask_irq(irq); |
| 622 | gpio_free(irq - IRQ_PA0); | 642 | gpio_free(gpionr); |
| 623 | gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0); | 643 | gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); |
| 624 | } | 644 | } |
| 625 | 645 | ||
| 626 | static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | 646 | static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) |
| @@ -628,7 +648,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
| 628 | 648 | ||
| 629 | unsigned int ret; | 649 | unsigned int ret; |
| 630 | char buf[8]; | 650 | char buf[8]; |
| 631 | u16 gpionr = irq - IRQ_PA0; | 651 | u16 gpionr = irq_to_gpio(irq); |
| 632 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; | 652 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; |
| 633 | u32 pintbit = PINT_BIT(pint_val); | 653 | u32 pintbit = PINT_BIT(pint_val); |
| 634 | u8 bank = PINT_2_BANK(pint_val); | 654 | u8 bank = PINT_2_BANK(pint_val); |
| @@ -660,28 +680,33 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
| 660 | 680 | ||
| 661 | gpio_direction_input(gpionr); | 681 | gpio_direction_input(gpionr); |
| 662 | 682 | ||
| 663 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | ||
| 664 | pint[bank]->edge_set = pintbit; | ||
| 665 | } else { | ||
| 666 | pint[bank]->edge_clear = pintbit; | ||
| 667 | } | ||
| 668 | |||
| 669 | if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) | 683 | if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) |
| 670 | pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ | 684 | pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */ |
| 671 | else | 685 | else |
| 672 | pint[bank]->invert_set = pintbit; /* high or rising edge denoted by zero */ | 686 | pint[bank]->invert_clear = pintbit; /* high or rising edge denoted by zero */ |
| 673 | 687 | ||
| 674 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | 688 | if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) |
| 675 | pint[bank]->invert_set = pintbit; | 689 | == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { |
| 676 | else | ||
| 677 | pint[bank]->invert_set = pintbit; | ||
| 678 | 690 | ||
| 679 | SSYNC(); | 691 | gpio_both_edge_triggered[bank] |= pintbit; |
| 680 | 692 | ||
| 681 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | 693 | if (gpio_get_value(gpionr)) |
| 694 | pint[bank]->invert_set = pintbit; | ||
| 695 | else | ||
| 696 | pint[bank]->invert_clear = pintbit; | ||
| 697 | } else { | ||
| 698 | gpio_both_edge_triggered[bank] &= ~pintbit; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | ||
| 702 | pint[bank]->edge_set = pintbit; | ||
| 682 | set_irq_handler(irq, handle_edge_irq); | 703 | set_irq_handler(irq, handle_edge_irq); |
| 683 | else | 704 | } else { |
| 705 | pint[bank]->edge_clear = pintbit; | ||
| 684 | set_irq_handler(irq, handle_level_irq); | 706 | set_irq_handler(irq, handle_level_irq); |
| 707 | } | ||
| 708 | |||
| 709 | SSYNC(); | ||
| 685 | 710 | ||
| 686 | return 0; | 711 | return 0; |
| 687 | } | 712 | } |
