Blackfin: bf537: demux port H mask A and emac rx ints
Mike Frysinger [Fri, 15 Apr 2011 17:04:59 +0000 (13:04 -0400)]
The BF537 SIC combines the gpio port H mask A interrupts with the
emac rx interrupt, so we need to demux this in software.

It also combines the gpio port H mask B and the emac tx interrupts,
and the watchdog and port F mask B interrupts, but since we don't
support mask B yet, just add the defines for now.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>

arch/blackfin/include/asm/irq_handler.h
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/mach-bf537/include/mach/irq.h
arch/blackfin/mach-bf537/ints-priority.c
arch/blackfin/mach-common/ints-priority.c

index 77341b3..ee73f79 100644 (file)
@@ -60,5 +60,6 @@ extern void bfin_internal_unmask_irq(unsigned int irq);
 
 struct irq_desc;
 extern void bfin_demux_mac_status_irq(unsigned int, struct irq_desc *);
+extern void bfin_demux_gpio_irq(unsigned int, struct irq_desc *);
 
 #endif
index 207bb6b..f9306bb 100644 (file)
@@ -535,7 +535,7 @@ static const unsigned int sic_iwr_irqs[] = {
 #if defined(BF533_FAMILY)
        IRQ_PROG_INTB
 #elif defined(BF537_FAMILY)
-       IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX
+       IRQ_PF_INTB_WATCH, IRQ_PORTG_INTB, IRQ_PH_INTB_MAC_TX
 #elif defined(BF538_FAMILY)
        IRQ_PORTF_INTB
 #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
index cc31323..b6ed823 100644 (file)
@@ -28,8 +28,8 @@
 #define IRQ_UART1_TX           BFIN_IRQ(14)    /* DMA11 Interrupt (UART1 TX) */
 #define IRQ_CAN_RX             BFIN_IRQ(15)    /* CAN Receive Interrupt */
 #define IRQ_CAN_TX             BFIN_IRQ(16)    /* CAN Transmit Interrupt */
-#define IRQ_MAC_RX             BFIN_IRQ(17)    /* DMA1 (Ethernet RX) Interrupt */
-#define IRQ_MAC_TX             BFIN_IRQ(18)    /* DMA2 (Ethernet TX) Interrupt */
+#define IRQ_PH_INTA_MAC_RX     BFIN_IRQ(17)    /* Port H Interrupt A & DMA1 Interrupt (Ethernet RX) */
+#define IRQ_PH_INTB_MAC_TX     BFIN_IRQ(18)    /* Port H Interrupt B & DMA2 Interrupt (Ethernet TX) */
 #define IRQ_TIMER0             BFIN_IRQ(19)    /* Timer 0 */
 #define IRQ_TIMER1             BFIN_IRQ(20)    /* Timer 1 */
 #define IRQ_TIMER2             BFIN_IRQ(21)    /* Timer 2 */
 #define IRQ_TIMER5             BFIN_IRQ(24)    /* Timer 5 */
 #define IRQ_TIMER6             BFIN_IRQ(25)    /* Timer 6 */
 #define IRQ_TIMER7             BFIN_IRQ(26)    /* Timer 7 */
-#define IRQ_PROG_INTA          BFIN_IRQ(27)    /* PF Ports F&G (PF15:0) Interrupt A */
-#define IRQ_PORTG_INTB         BFIN_IRQ(28)    /* PF Port G (PF15:0) Interrupt B */
+#define IRQ_PF_INTA_PG_INTA    BFIN_IRQ(27)    /* Ports F&G Interrupt A */
+#define IRQ_PORTG_INTB         BFIN_IRQ(28)    /* Port G Interrupt B */
 #define IRQ_MEM_DMA0           BFIN_IRQ(29)    /* (Memory DMA Stream 0) */
 #define IRQ_MEM_DMA1           BFIN_IRQ(30)    /* (Memory DMA Stream 1) */
-#define IRQ_PROG_INTB          BFIN_IRQ(31)    /* PF Ports F (PF15:0) Interrupt B */
-#define IRQ_WATCH              BFIN_IRQ(32)    /* Watch Dog Timer */
+#define IRQ_PF_INTB_WATCH      BFIN_IRQ(31)    /* Watchdog & Port F Interrupt B */
 
 #define SYS_IRQS               39
 
 #define IRQ_MAC_TXDMAERR       104     /* TX DMA Direction Error Interrupt */
 #define IRQ_MAC_STMDONE                105     /* Station Mgt. Transfer Done Interrupt */
 
-#define NR_MACH_IRQS           (IRQ_MAC_STMDONE + 1)
+#define IRQ_MAC_RX             106     /* DMA1 Interrupt (Ethernet RX) */
+#define IRQ_PORTH_INTA         107     /* Port H Interrupt A */
+
+#if 0 /* No Interrupt B support (yet) */
+#define IRQ_MAC_TX             108     /* DMA2 Interrupt (Ethernet TX) */
+#define IRQ_PORTH_INTB         109     /* Port H Interrupt B */
+#else
+#define IRQ_MAC_TX             IRQ_PH_INTB_MAC_TX
+#endif
+
+#define IRQ_PORTF_INTA         110     /* Port F Interrupt A */
+#define IRQ_PORTG_INTA         111     /* Port G Interrupt A */
+
+#if 0 /* No Interrupt B support (yet) */
+#define IRQ_WATCH              112     /* Watchdog Timer */
+#define IRQ_PORTF_INTB         113     /* Port F Interrupt B */
+#else
+#define IRQ_WATCH              IRQ_PF_INTB_WATCH
+#endif
+
+#define NR_MACH_IRQS           (113 + 1)
 
 /* IAR0 BIT FIELDS */
 #define IRQ_PLL_WAKEUP_POS     0
index cbf1901..2137a20 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/bfin5xx_spi.h>
 #include <asm/bfin_sport.h>
 #include <asm/bfin_can.h>
+#include <asm/bfin_dma.h>
 #include <asm/dpmc.h>
 
 void __init program_IAR(void)
@@ -157,6 +158,40 @@ static void bf537_demux_error_irq(unsigned int int_err_irq,
 
 }
 
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static int mac_rx_int_mask;
+
+static void bf537_mac_rx_mask_irq(struct irq_data *d)
+{
+       mac_rx_int_mask &= ~(1L << (d->irq - IRQ_MAC_RX));
+       if (!mac_rx_int_mask)
+               bfin_internal_mask_irq(IRQ_PH_INTA_MAC_RX);
+}
+
+static void bf537_mac_rx_unmask_irq(struct irq_data *d)
+{
+       bfin_internal_unmask_irq(IRQ_PH_INTA_MAC_RX);
+       mac_rx_int_mask |= 1L << (d->irq - IRQ_MAC_RX);
+}
+
+static struct irq_chip bf537_mac_rx_irqchip = {
+       .name = "ERROR",
+       .irq_ack = bfin_ack_noop,
+       .irq_mask_ack = bf537_mac_rx_mask_irq,
+       .irq_mask = bf537_mac_rx_mask_irq,
+       .irq_unmask = bf537_mac_rx_unmask_irq,
+};
+
+static void bf537_demux_mac_rx_irq(unsigned int int_irq,
+                                  struct irq_desc *desc)
+{
+       if (bfin_read_DMA1_IRQ_STATUS() & (DMA_DONE | DMA_ERR))
+               bfin_handle_irq(IRQ_MAC_RX);
+       else
+               bfin_demux_gpio_irq(int_irq, desc);
+}
+#endif
+
 void __init init_mach_irq(void)
 {
        int irq;
@@ -172,6 +207,10 @@ void __init init_mach_irq(void)
                                         handle_level_irq);
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+       irq_set_chained_handler(IRQ_PH_INTA_MAC_RX, bf537_demux_mac_rx_irq);
+       irq_set_chip_and_handler(IRQ_MAC_RX, &bf537_mac_rx_irqchip, handle_level_irq);
+       irq_set_chip_and_handler(IRQ_PORTH_INTA, &bf537_mac_rx_irqchip, handle_level_irq);
+
        irq_set_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq);
 #endif
 }
index ad28eb1..1177369 100644 (file)
@@ -582,22 +582,20 @@ static void bfin_demux_gpio_block(unsigned int irq)
        }
 }
 
-static void bfin_demux_gpio_irq(unsigned int inta_irq,
-                               struct irq_desc *desc)
+void bfin_demux_gpio_irq(unsigned int inta_irq,
+                        struct irq_desc *desc)
 {
        unsigned int irq;
 
        switch (inta_irq) {
 #if defined(BF537_FAMILY)
-       case IRQ_PROG_INTA:
+       case IRQ_PF_INTA_PG_INTA:
                bfin_demux_gpio_block(IRQ_PF0);
                irq = IRQ_PG0;
                break;
-# if !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
-       case IRQ_MAC_RX:
+       case IRQ_PH_INTA_MAC_RX:
                irq = IRQ_PH0;
                break;
-# endif
 #elif defined(BF533_FAMILY)
        case IRQ_PROG_INTA:
                irq = IRQ_PF0;
@@ -881,8 +879,8 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 # define bfin_gpio_set_wake NULL
 #endif
 
-static void bfin_demux_gpio_irq(unsigned int inta_irq,
-                               struct irq_desc *desc)
+void bfin_demux_gpio_irq(unsigned int inta_irq,
+                        struct irq_desc *desc)
 {
        u32 bank, pint_val;
        u32 request, irq;
@@ -1001,11 +999,11 @@ int __init init_arch_irq(void)
                        irq_set_chip(irq, &bfin_internal_irqchip);
 
                switch (irq) {
-#if defined(CONFIG_BF53x)
+#if defined(BF537_FAMILY)
+               case IRQ_PH_INTA_MAC_RX:
+               case IRQ_PF_INTA_PG_INTA:
+#elif defined(BF533_FAMILY)
                case IRQ_PROG_INTA:
-# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
-               case IRQ_MAC_RX:
-# endif
 #elif defined(CONFIG_BF54x)
                case IRQ_PINT0:
                case IRQ_PINT1: