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 /arch/mips | |
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>
Diffstat (limited to 'arch/mips')
-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); |