diff options
| author | David Daney <david.daney@cavium.com> | 2012-07-05 12:12:37 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2012-07-23 08:54:51 -0400 |
| commit | 6d1ab4c22d43bd2b17cc42513c2fbbde9af93031 (patch) | |
| tree | f3a7f657f75e82f41efc4cd5fa35717561fa9d4c | |
| parent | 05b8c8c1288c078f8920f5894854086f0e10f095 (diff) | |
MIPS: Octeon: Add irq handlers for GPIO interrupts.
This is needed for follow-on on patches for Octeon to use the Device
Tree to configure GPIO interrupts.
Signed-off-by: David Daney <david.daney@cavium.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3932/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 111 |
1 files changed, 110 insertions, 1 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index ffd4ae660f79..168b4891d7a9 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c | |||
| @@ -505,6 +505,85 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) | |||
| 505 | } | 505 | } |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static void octeon_irq_gpio_setup(struct irq_data *data) | ||
| 509 | { | ||
| 510 | union cvmx_gpio_bit_cfgx cfg; | ||
| 511 | union octeon_ciu_chip_data cd; | ||
| 512 | u32 t = irqd_get_trigger_type(data); | ||
| 513 | |||
| 514 | cd.p = irq_data_get_irq_chip_data(data); | ||
| 515 | |||
| 516 | cfg.u64 = 0; | ||
| 517 | cfg.s.int_en = 1; | ||
| 518 | cfg.s.int_type = (t & IRQ_TYPE_EDGE_BOTH) != 0; | ||
| 519 | cfg.s.rx_xor = (t & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) != 0; | ||
| 520 | |||
| 521 | /* 140 nS glitch filter*/ | ||
| 522 | cfg.s.fil_cnt = 7; | ||
| 523 | cfg.s.fil_sel = 3; | ||
| 524 | |||
| 525 | cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), cfg.u64); | ||
| 526 | } | ||
| 527 | |||
| 528 | static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data) | ||
| 529 | { | ||
| 530 | octeon_irq_gpio_setup(data); | ||
| 531 | octeon_irq_ciu_enable_v2(data); | ||
| 532 | } | ||
| 533 | |||
| 534 | static void octeon_irq_ciu_enable_gpio(struct irq_data *data) | ||
| 535 | { | ||
| 536 | octeon_irq_gpio_setup(data); | ||
| 537 | octeon_irq_ciu_enable(data); | ||
| 538 | } | ||
| 539 | |||
| 540 | static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t) | ||
| 541 | { | ||
| 542 | irqd_set_trigger_type(data, t); | ||
| 543 | octeon_irq_gpio_setup(data); | ||
| 544 | |||
| 545 | return IRQ_SET_MASK_OK; | ||
| 546 | } | ||
| 547 | |||
| 548 | static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data) | ||
| 549 | { | ||
| 550 | union octeon_ciu_chip_data cd; | ||
| 551 | |||
| 552 | cd.p = irq_data_get_irq_chip_data(data); | ||
| 553 | cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); | ||
| 554 | |||
| 555 | octeon_irq_ciu_disable_all_v2(data); | ||
| 556 | } | ||
| 557 | |||
| 558 | static void octeon_irq_ciu_disable_gpio(struct irq_data *data) | ||
| 559 | { | ||
| 560 | union octeon_ciu_chip_data cd; | ||
| 561 | |||
| 562 | cd.p = irq_data_get_irq_chip_data(data); | ||
| 563 | cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); | ||
| 564 | |||
| 565 | octeon_irq_ciu_disable_all(data); | ||
| 566 | } | ||
| 567 | |||
| 568 | static void octeon_irq_ciu_gpio_ack(struct irq_data *data) | ||
| 569 | { | ||
| 570 | union octeon_ciu_chip_data cd; | ||
| 571 | u64 mask; | ||
| 572 | |||
| 573 | cd.p = irq_data_get_irq_chip_data(data); | ||
| 574 | mask = 1ull << (cd.s.bit - 16); | ||
| 575 | |||
| 576 | cvmx_write_csr(CVMX_GPIO_INT_CLR, mask); | ||
| 577 | } | ||
| 578 | |||
| 579 | static void octeon_irq_handle_gpio(unsigned int irq, struct irq_desc *desc) | ||
| 580 | { | ||
| 581 | if (irqd_get_trigger_type(irq_desc_get_irq_data(desc)) & IRQ_TYPE_EDGE_BOTH) | ||
| 582 | handle_edge_irq(irq, desc); | ||
| 583 | else | ||
| 584 | handle_level_irq(irq, desc); | ||
| 585 | } | ||
| 586 | |||
| 508 | #ifdef CONFIG_SMP | 587 | #ifdef CONFIG_SMP |
| 509 | 588 | ||
| 510 | static void octeon_irq_cpu_offline_ciu(struct irq_data *data) | 589 | static void octeon_irq_cpu_offline_ciu(struct irq_data *data) |
| @@ -717,6 +796,33 @@ static struct irq_chip octeon_irq_chip_ciu_mbox = { | |||
| 717 | .flags = IRQCHIP_ONOFFLINE_ENABLED, | 796 | .flags = IRQCHIP_ONOFFLINE_ENABLED, |
| 718 | }; | 797 | }; |
| 719 | 798 | ||
| 799 | static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = { | ||
| 800 | .name = "CIU-GPIO", | ||
| 801 | .irq_enable = octeon_irq_ciu_enable_gpio_v2, | ||
| 802 | .irq_disable = octeon_irq_ciu_disable_gpio_v2, | ||
| 803 | .irq_ack = octeon_irq_ciu_gpio_ack, | ||
| 804 | .irq_mask = octeon_irq_ciu_disable_local_v2, | ||
| 805 | .irq_unmask = octeon_irq_ciu_enable_v2, | ||
| 806 | .irq_set_type = octeon_irq_ciu_gpio_set_type, | ||
| 807 | #ifdef CONFIG_SMP | ||
| 808 | .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, | ||
| 809 | #endif | ||
| 810 | .flags = IRQCHIP_SET_TYPE_MASKED, | ||
| 811 | }; | ||
| 812 | |||
| 813 | static struct irq_chip octeon_irq_chip_ciu_gpio = { | ||
| 814 | .name = "CIU-GPIO", | ||
| 815 | .irq_enable = octeon_irq_ciu_enable_gpio, | ||
| 816 | .irq_disable = octeon_irq_ciu_disable_gpio, | ||
| 817 | .irq_mask = octeon_irq_dummy_mask, | ||
| 818 | .irq_ack = octeon_irq_ciu_gpio_ack, | ||
| 819 | .irq_set_type = octeon_irq_ciu_gpio_set_type, | ||
| 820 | #ifdef CONFIG_SMP | ||
| 821 | .irq_set_affinity = octeon_irq_ciu_set_affinity, | ||
| 822 | #endif | ||
| 823 | .flags = IRQCHIP_SET_TYPE_MASKED, | ||
| 824 | }; | ||
| 825 | |||
| 720 | /* | 826 | /* |
| 721 | * Watchdog interrupts are special. They are associated with a single | 827 | * Watchdog interrupts are special. They are associated with a single |
| 722 | * core, so we hardwire the affinity to that core. | 828 | * core, so we hardwire the affinity to that core. |
| @@ -890,6 +996,7 @@ static void __init octeon_irq_init_ciu(void) | |||
| 890 | struct irq_chip *chip_edge; | 996 | struct irq_chip *chip_edge; |
| 891 | struct irq_chip *chip_mbox; | 997 | struct irq_chip *chip_mbox; |
| 892 | struct irq_chip *chip_wd; | 998 | struct irq_chip *chip_wd; |
| 999 | struct irq_chip *chip_gpio; | ||
| 893 | 1000 | ||
| 894 | octeon_irq_init_ciu_percpu(); | 1001 | octeon_irq_init_ciu_percpu(); |
| 895 | octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; | 1002 | octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; |
| @@ -904,6 +1011,7 @@ static void __init octeon_irq_init_ciu(void) | |||
| 904 | chip_edge = &octeon_irq_chip_ciu_edge_v2; | 1011 | chip_edge = &octeon_irq_chip_ciu_edge_v2; |
| 905 | chip_mbox = &octeon_irq_chip_ciu_mbox_v2; | 1012 | chip_mbox = &octeon_irq_chip_ciu_mbox_v2; |
| 906 | chip_wd = &octeon_irq_chip_ciu_wd_v2; | 1013 | chip_wd = &octeon_irq_chip_ciu_wd_v2; |
| 1014 | chip_gpio = &octeon_irq_chip_ciu_gpio_v2; | ||
| 907 | } else { | 1015 | } else { |
| 908 | octeon_irq_ip2 = octeon_irq_ip2_v1; | 1016 | octeon_irq_ip2 = octeon_irq_ip2_v1; |
| 909 | octeon_irq_ip3 = octeon_irq_ip3_v1; | 1017 | octeon_irq_ip3 = octeon_irq_ip3_v1; |
| @@ -911,6 +1019,7 @@ static void __init octeon_irq_init_ciu(void) | |||
| 911 | chip_edge = &octeon_irq_chip_ciu_edge; | 1019 | chip_edge = &octeon_irq_chip_ciu_edge; |
| 912 | chip_mbox = &octeon_irq_chip_ciu_mbox; | 1020 | chip_mbox = &octeon_irq_chip_ciu_mbox; |
| 913 | chip_wd = &octeon_irq_chip_ciu_wd; | 1021 | chip_wd = &octeon_irq_chip_ciu_wd; |
| 1022 | chip_gpio = &octeon_irq_chip_ciu_gpio; | ||
| 914 | } | 1023 | } |
| 915 | octeon_irq_ip4 = octeon_irq_ip4_mask; | 1024 | octeon_irq_ip4 = octeon_irq_ip4_mask; |
| 916 | 1025 | ||
| @@ -921,7 +1030,7 @@ static void __init octeon_irq_init_ciu(void) | |||
| 921 | for (i = 0; i < 16; i++) | 1030 | for (i = 0; i < 16; i++) |
| 922 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); | 1031 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); |
| 923 | for (i = 0; i < 16; i++) | 1032 | for (i = 0; i < 16; i++) |
| 924 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq); | 1033 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip_gpio, octeon_irq_handle_gpio); |
| 925 | 1034 | ||
| 926 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); | 1035 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); |
| 927 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); | 1036 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); |
