diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2010-02-19 10:09:10 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-03-09 00:30:52 -0500 |
commit | aec59c911307639c77076bdc9d9b546a4a767a73 (patch) | |
tree | 84dea13756d7a2093322dc25f6e2efda2c10f169 /arch/blackfin/mach-common | |
parent | b2740801457b2fbbe14812c0fda24bd689025886 (diff) |
Blackfin: add support for the on-chip MAC status interrupts
This patch provides infrastructure for MAC Wake-On-Lan and PHYINT use in
phylib. New Interrupts added:
IRQ_MAC_PHYINT /* PHY_INT Interrupt */
IRQ_MAC_MMCINT /* MMC Counter Interrupt */
IRQ_MAC_RXFSINT /* RX Frame-Status Interrupt */
IRQ_MAC_TXFSINT /* TX Frame-Status Interrupt */
IRQ_MAC_WAKEDET /* Wake-Up Interrupt */
IRQ_MAC_RXDMAERR /* RX DMA Direction Error Interrupt */
IRQ_MAC_TXDMAERR /* TX DMA Direction Error Interrupt */
IRQ_MAC_STMDONE /* Station Mgt. Transfer Done Interrupt */
On BF537/6 the implementation is not straight forward since there are now
two chained chained_handlers. A cleaner approach would have been to add
latter IRQs to the demux of IRQ_GENERIC_ERROR.
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 140 |
1 files changed, 136 insertions, 4 deletions
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index ebf886091187..11c05f3e178b 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -325,7 +325,6 @@ static int error_int_mask; | |||
325 | static void bfin_generic_error_mask_irq(unsigned int irq) | 325 | static void bfin_generic_error_mask_irq(unsigned int irq) |
326 | { | 326 | { |
327 | error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR)); | 327 | error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR)); |
328 | |||
329 | if (!error_int_mask) | 328 | if (!error_int_mask) |
330 | bfin_internal_mask_irq(IRQ_GENERIC_ERROR); | 329 | bfin_internal_mask_irq(IRQ_GENERIC_ERROR); |
331 | } | 330 | } |
@@ -416,6 +415,127 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, | |||
416 | } | 415 | } |
417 | #endif /* BF537_GENERIC_ERROR_INT_DEMUX */ | 416 | #endif /* BF537_GENERIC_ERROR_INT_DEMUX */ |
418 | 417 | ||
418 | #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) | ||
419 | static int mac_stat_int_mask; | ||
420 | |||
421 | static void bfin_mac_status_ack_irq(unsigned int irq) | ||
422 | { | ||
423 | switch (irq) { | ||
424 | case IRQ_MAC_MMCINT: | ||
425 | bfin_write_EMAC_MMC_TIRQS( | ||
426 | bfin_read_EMAC_MMC_TIRQE() & | ||
427 | bfin_read_EMAC_MMC_TIRQS()); | ||
428 | bfin_write_EMAC_MMC_RIRQS( | ||
429 | bfin_read_EMAC_MMC_RIRQE() & | ||
430 | bfin_read_EMAC_MMC_RIRQS()); | ||
431 | break; | ||
432 | case IRQ_MAC_RXFSINT: | ||
433 | bfin_write_EMAC_RX_STKY( | ||
434 | bfin_read_EMAC_RX_IRQE() & | ||
435 | bfin_read_EMAC_RX_STKY()); | ||
436 | break; | ||
437 | case IRQ_MAC_TXFSINT: | ||
438 | bfin_write_EMAC_TX_STKY( | ||
439 | bfin_read_EMAC_TX_IRQE() & | ||
440 | bfin_read_EMAC_TX_STKY()); | ||
441 | break; | ||
442 | case IRQ_MAC_WAKEDET: | ||
443 | bfin_write_EMAC_WKUP_CTL( | ||
444 | bfin_read_EMAC_WKUP_CTL() | MPKS | RWKS); | ||
445 | break; | ||
446 | default: | ||
447 | /* These bits are W1C */ | ||
448 | bfin_write_EMAC_SYSTAT(1L << (irq - IRQ_MAC_PHYINT)); | ||
449 | break; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | static void bfin_mac_status_mask_irq(unsigned int irq) | ||
454 | { | ||
455 | mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT)); | ||
456 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX | ||
457 | switch (irq) { | ||
458 | case IRQ_MAC_PHYINT: | ||
459 | bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() & ~PHYIE); | ||
460 | break; | ||
461 | default: | ||
462 | break; | ||
463 | } | ||
464 | #else | ||
465 | if (!mac_stat_int_mask) | ||
466 | bfin_internal_mask_irq(IRQ_MAC_ERROR); | ||
467 | #endif | ||
468 | bfin_mac_status_ack_irq(irq); | ||
469 | } | ||
470 | |||
471 | static void bfin_mac_status_unmask_irq(unsigned int irq) | ||
472 | { | ||
473 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX | ||
474 | switch (irq) { | ||
475 | case IRQ_MAC_PHYINT: | ||
476 | bfin_write_EMAC_SYSCTL(bfin_read_EMAC_SYSCTL() | PHYIE); | ||
477 | break; | ||
478 | default: | ||
479 | break; | ||
480 | } | ||
481 | #else | ||
482 | if (!mac_stat_int_mask) | ||
483 | bfin_internal_unmask_irq(IRQ_MAC_ERROR); | ||
484 | #endif | ||
485 | mac_stat_int_mask |= 1L << (irq - IRQ_MAC_PHYINT); | ||
486 | } | ||
487 | |||
488 | #ifdef CONFIG_PM | ||
489 | int bfin_mac_status_set_wake(unsigned int irq, unsigned int state) | ||
490 | { | ||
491 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX | ||
492 | return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state); | ||
493 | #else | ||
494 | return bfin_internal_set_wake(IRQ_MAC_ERROR, state); | ||
495 | #endif | ||
496 | } | ||
497 | #endif | ||
498 | |||
499 | static struct irq_chip bfin_mac_status_irqchip = { | ||
500 | .name = "MACST", | ||
501 | .ack = bfin_ack_noop, | ||
502 | .mask_ack = bfin_mac_status_mask_irq, | ||
503 | .mask = bfin_mac_status_mask_irq, | ||
504 | .unmask = bfin_mac_status_unmask_irq, | ||
505 | #ifdef CONFIG_PM | ||
506 | .set_wake = bfin_mac_status_set_wake, | ||
507 | #endif | ||
508 | }; | ||
509 | |||
510 | static void bfin_demux_mac_status_irq(unsigned int int_err_irq, | ||
511 | struct irq_desc *inta_desc) | ||
512 | { | ||
513 | int i, irq = 0; | ||
514 | u32 status = bfin_read_EMAC_SYSTAT(); | ||
515 | |||
516 | for (i = 0; i < (IRQ_MAC_STMDONE - IRQ_MAC_PHYINT); i++) | ||
517 | if (status & (1L << i)) { | ||
518 | irq = IRQ_MAC_PHYINT + i; | ||
519 | break; | ||
520 | } | ||
521 | |||
522 | if (irq) { | ||
523 | if (mac_stat_int_mask & (1L << (irq - IRQ_MAC_PHYINT))) { | ||
524 | bfin_handle_irq(irq); | ||
525 | } else { | ||
526 | bfin_mac_status_ack_irq(irq); | ||
527 | pr_debug("IRQ %d:" | ||
528 | " MASKED MAC ERROR INTERRUPT ASSERTED\n", | ||
529 | irq); | ||
530 | } | ||
531 | } else | ||
532 | printk(KERN_ERR | ||
533 | "%s : %s : LINE %d :\nIRQ ?: MAC ERROR" | ||
534 | " INTERRUPT ASSERTED BUT NO SOURCE FOUND\n", | ||
535 | __func__, __FILE__, __LINE__); | ||
536 | } | ||
537 | #endif | ||
538 | |||
419 | static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) | 539 | static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle) |
420 | { | 540 | { |
421 | #ifdef CONFIG_IPIPE | 541 | #ifdef CONFIG_IPIPE |
@@ -1070,7 +1190,11 @@ int __init init_arch_irq(void) | |||
1070 | set_irq_chained_handler(irq, bfin_demux_error_irq); | 1190 | set_irq_chained_handler(irq, bfin_demux_error_irq); |
1071 | break; | 1191 | break; |
1072 | #endif | 1192 | #endif |
1073 | 1193 | #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) | |
1194 | case IRQ_MAC_ERROR: | ||
1195 | set_irq_chained_handler(irq, bfin_demux_mac_status_irq); | ||
1196 | break; | ||
1197 | #endif | ||
1074 | #ifdef CONFIG_SMP | 1198 | #ifdef CONFIG_SMP |
1075 | case IRQ_SUPPLE_0: | 1199 | case IRQ_SUPPLE_0: |
1076 | case IRQ_SUPPLE_1: | 1200 | case IRQ_SUPPLE_1: |
@@ -1111,14 +1235,22 @@ int __init init_arch_irq(void) | |||
1111 | for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++) | 1235 | for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++) |
1112 | set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip, | 1236 | set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip, |
1113 | handle_level_irq); | 1237 | handle_level_irq); |
1238 | #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) | ||
1239 | set_irq_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq); | ||
1240 | #endif | ||
1114 | #endif | 1241 | #endif |
1115 | 1242 | ||
1243 | #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) | ||
1244 | for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++) | ||
1245 | set_irq_chip_and_handler(irq, &bfin_mac_status_irqchip, | ||
1246 | handle_level_irq); | ||
1247 | #endif | ||
1116 | /* if configured as edge, then will be changed to do_edge_IRQ */ | 1248 | /* if configured as edge, then will be changed to do_edge_IRQ */ |
1117 | for (irq = GPIO_IRQ_BASE; irq < NR_MACH_IRQS; irq++) | 1249 | for (irq = GPIO_IRQ_BASE; |
1250 | irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++) | ||
1118 | set_irq_chip_and_handler(irq, &bfin_gpio_irqchip, | 1251 | set_irq_chip_and_handler(irq, &bfin_gpio_irqchip, |
1119 | handle_level_irq); | 1252 | handle_level_irq); |
1120 | 1253 | ||
1121 | |||
1122 | bfin_write_IMASK(0); | 1254 | bfin_write_IMASK(0); |
1123 | CSYNC(); | 1255 | CSYNC(); |
1124 | ilat = bfin_read_ILAT(); | 1256 | ilat = bfin_read_ILAT(); |