diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 67 |
1 files changed, 63 insertions, 4 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 1460d0836dc0..0bc79dcede26 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c | |||
@@ -51,9 +51,6 @@ static void octeon_irq_core_eoi(unsigned int irq) | |||
51 | */ | 51 | */ |
52 | if (desc->status & IRQ_DISABLED) | 52 | if (desc->status & IRQ_DISABLED) |
53 | return; | 53 | return; |
54 | |||
55 | /* There is a race here. We should fix it. */ | ||
56 | |||
57 | /* | 54 | /* |
58 | * We don't need to disable IRQs to make these atomic since | 55 | * We don't need to disable IRQs to make these atomic since |
59 | * they are already disabled earlier in the low level | 56 | * they are already disabled earlier in the low level |
@@ -202,6 +199,29 @@ static void octeon_irq_ciu0_ack_v2(unsigned int irq) | |||
202 | } | 199 | } |
203 | 200 | ||
204 | /* | 201 | /* |
202 | * CIU timer type interrupts must be acknoleged by writing a '1' bit | ||
203 | * to their sum0 bit. | ||
204 | */ | ||
205 | static void octeon_irq_ciu0_timer_ack(unsigned int irq) | ||
206 | { | ||
207 | int index = cvmx_get_core_num() * 2; | ||
208 | uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | ||
209 | cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); | ||
210 | } | ||
211 | |||
212 | static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq) | ||
213 | { | ||
214 | octeon_irq_ciu0_timer_ack(irq); | ||
215 | octeon_irq_ciu0_ack(irq); | ||
216 | } | ||
217 | |||
218 | static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq) | ||
219 | { | ||
220 | octeon_irq_ciu0_timer_ack(irq); | ||
221 | octeon_irq_ciu0_ack_v2(irq); | ||
222 | } | ||
223 | |||
224 | /* | ||
205 | * Enable the irq on the current core for chips that have the EN*_W1{S,C} | 225 | * Enable the irq on the current core for chips that have the EN*_W1{S,C} |
206 | * registers. | 226 | * registers. |
207 | */ | 227 | */ |
@@ -304,6 +324,28 @@ static struct irq_chip octeon_irq_chip_ciu0 = { | |||
304 | #endif | 324 | #endif |
305 | }; | 325 | }; |
306 | 326 | ||
327 | static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = { | ||
328 | .name = "CIU0-T", | ||
329 | .enable = octeon_irq_ciu0_enable_v2, | ||
330 | .disable = octeon_irq_ciu0_disable_all_v2, | ||
331 | .ack = octeon_irq_ciu0_timer_ack_v2, | ||
332 | .eoi = octeon_irq_ciu0_eoi_v2, | ||
333 | #ifdef CONFIG_SMP | ||
334 | .set_affinity = octeon_irq_ciu0_set_affinity_v2, | ||
335 | #endif | ||
336 | }; | ||
337 | |||
338 | static struct irq_chip octeon_irq_chip_ciu0_timer = { | ||
339 | .name = "CIU0-T", | ||
340 | .enable = octeon_irq_ciu0_enable, | ||
341 | .disable = octeon_irq_ciu0_disable, | ||
342 | .ack = octeon_irq_ciu0_timer_ack_v1, | ||
343 | .eoi = octeon_irq_ciu0_eoi, | ||
344 | #ifdef CONFIG_SMP | ||
345 | .set_affinity = octeon_irq_ciu0_set_affinity, | ||
346 | #endif | ||
347 | }; | ||
348 | |||
307 | 349 | ||
308 | static void octeon_irq_ciu1_ack(unsigned int irq) | 350 | static void octeon_irq_ciu1_ack(unsigned int irq) |
309 | { | 351 | { |
@@ -587,6 +629,7 @@ void __init arch_init_irq(void) | |||
587 | { | 629 | { |
588 | int irq; | 630 | int irq; |
589 | struct irq_chip *chip0; | 631 | struct irq_chip *chip0; |
632 | struct irq_chip *chip0_timer; | ||
590 | struct irq_chip *chip1; | 633 | struct irq_chip *chip1; |
591 | 634 | ||
592 | #ifdef CONFIG_SMP | 635 | #ifdef CONFIG_SMP |
@@ -602,9 +645,11 @@ void __init arch_init_irq(void) | |||
602 | OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || | 645 | OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || |
603 | OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { | 646 | OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { |
604 | chip0 = &octeon_irq_chip_ciu0_v2; | 647 | chip0 = &octeon_irq_chip_ciu0_v2; |
648 | chip0_timer = &octeon_irq_chip_ciu0_timer_v2; | ||
605 | chip1 = &octeon_irq_chip_ciu1_v2; | 649 | chip1 = &octeon_irq_chip_ciu1_v2; |
606 | } else { | 650 | } else { |
607 | chip0 = &octeon_irq_chip_ciu0; | 651 | chip0 = &octeon_irq_chip_ciu0; |
652 | chip0_timer = &octeon_irq_chip_ciu0_timer; | ||
608 | chip1 = &octeon_irq_chip_ciu1; | 653 | chip1 = &octeon_irq_chip_ciu1; |
609 | } | 654 | } |
610 | 655 | ||
@@ -618,7 +663,21 @@ void __init arch_init_irq(void) | |||
618 | 663 | ||
619 | /* 24 - 87 CIU_INT_SUM0 */ | 664 | /* 24 - 87 CIU_INT_SUM0 */ |
620 | for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { | 665 | for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { |
621 | set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); | 666 | switch (irq) { |
667 | case OCTEON_IRQ_GMX_DRP0: | ||
668 | case OCTEON_IRQ_GMX_DRP1: | ||
669 | case OCTEON_IRQ_IPD_DRP: | ||
670 | case OCTEON_IRQ_KEY_ZERO: | ||
671 | case OCTEON_IRQ_TIMER0: | ||
672 | case OCTEON_IRQ_TIMER1: | ||
673 | case OCTEON_IRQ_TIMER2: | ||
674 | case OCTEON_IRQ_TIMER3: | ||
675 | set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq); | ||
676 | break; | ||
677 | default: | ||
678 | set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); | ||
679 | break; | ||
680 | } | ||
622 | } | 681 | } |
623 | 682 | ||
624 | /* 88 - 151 CIU_INT_SUM1 */ | 683 | /* 88 - 151 CIU_INT_SUM1 */ |