rapidio:powerpc/85xx: modify RIO port-write interrupt handler
[pandora-kernel.git] / arch / powerpc / sysdev / fsl_rio.c
index 3017532..ed2ec71 100644 (file)
@@ -87,6 +87,9 @@
 #define RIO_IPWSR_PWD          0x00000008
 #define RIO_IPWSR_PWB          0x00000004
 
+#define RIO_EPWISR_PINT                0x80000000
+#define RIO_EPWISR_PW          0x00000001
+
 #define RIO_MSG_DESC_SIZE      32
 #define RIO_MSG_BUFFER_SIZE    4096
 #define RIO_MIN_TX_RING_SIZE   2
@@ -117,44 +120,59 @@ struct rio_atmu_regs {
 };
 
 struct rio_msg_regs {
-       u32 omr;
-       u32 osr;
+       u32 omr;        /* 0xD_3000 - Outbound message 0 mode register */
+       u32 osr;        /* 0xD_3004 - Outbound message 0 status register */
        u32 pad1;
-       u32 odqdpar;
+       u32 odqdpar;    /* 0xD_300C - Outbound message 0 descriptor queue
+                          dequeue pointer address register */
        u32 pad2;
-       u32 osar;
-       u32 odpr;
-       u32 odatr;
-       u32 odcr;
+       u32 osar;       /* 0xD_3014 - Outbound message 0 source address
+                          register */
+       u32 odpr;       /* 0xD_3018 - Outbound message 0 destination port
+                          register */
+       u32 odatr;      /* 0xD_301C - Outbound message 0 destination attributes
+                          Register*/
+       u32 odcr;       /* 0xD_3020 - Outbound message 0 double-word count
+                          register */
        u32 pad3;
-       u32 odqepar;
+       u32 odqepar;    /* 0xD_3028 - Outbound message 0 descriptor queue
+                          enqueue pointer address register */
        u32 pad4[13];
-       u32 imr;
-       u32 isr;
+       u32 imr;        /* 0xD_3060 - Inbound message 0 mode register */
+       u32 isr;        /* 0xD_3064 - Inbound message 0 status register */
        u32 pad5;
-       u32 ifqdpar;
+       u32 ifqdpar;    /* 0xD_306C - Inbound message 0 frame queue dequeue
+                          pointer address register*/
        u32 pad6;
-       u32 ifqepar;
+       u32 ifqepar;    /* 0xD_3074 - Inbound message 0 frame queue enqueue
+                          pointer address register */
        u32 pad7[226];
-       u32 odmr;
-       u32 odsr;
+       u32 odmr;       /* 0xD_3400 - Outbound doorbell mode register */
+       u32 odsr;       /* 0xD_3404 - Outbound doorbell status register */
        u32 res0[4];
-       u32 oddpr;
-       u32 oddatr;
+       u32 oddpr;      /* 0xD_3418 - Outbound doorbell destination port
+                          register */
+       u32 oddatr;     /* 0xD_341c - Outbound doorbell destination attributes
+                          register */
        u32 res1[3];
-       u32 odretcr;
+       u32 odretcr;    /* 0xD_342C - Outbound doorbell retry error threshold
+                          configuration register */
        u32 res2[12];
-       u32 dmr;
-       u32 dsr;
+       u32 dmr;        /* 0xD_3460 - Inbound doorbell mode register */
+       u32 dsr;        /* 0xD_3464 - Inbound doorbell status register */
        u32 pad8;
-       u32 dqdpar;
+       u32 dqdpar;     /* 0xD_346C - Inbound doorbell queue dequeue Pointer
+                          address register */
        u32 pad9;
-       u32 dqepar;
+       u32 dqepar;     /* 0xD_3474 - Inbound doorbell Queue enqueue pointer
+                          address register */
        u32 pad10[26];
-       u32 pwmr;
-       u32 pwsr;
-       u32 epwqbar;
-       u32 pwqbar;
+       u32 pwmr;       /* 0xD_34E0 - Inbound port-write mode register */
+       u32 pwsr;       /* 0xD_34E4 - Inbound port-write status register */
+       u32 epwqbar;    /* 0xD_34E8 - Extended Port-Write Queue Base Address
+                          register */
+       u32 pwqbar;     /* 0xD_34EC - Inbound port-write queue base address
+                          register */
 };
 
 struct rio_tx_desc {
@@ -1067,18 +1085,12 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
        struct rio_priv *priv = port->priv;
        u32 epwisr, tmp;
 
-       ipwmr = in_be32(&priv->msg_regs->pwmr);
-       ipwsr = in_be32(&priv->msg_regs->pwsr);
-
        epwisr = in_be32(priv->regs_win + RIO_EPWISR);
-       if (epwisr & 0x80000000) {
-               tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
-               pr_info("RIO_LTLEDCSR = 0x%x\n", tmp);
-               out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
-       }
+       if (!(epwisr & RIO_EPWISR_PW))
+               goto pw_done;
 
-       if (!(epwisr & 0x00000001))
-               return IRQ_HANDLED;
+       ipwmr = in_be32(&priv->msg_regs->pwmr);
+       ipwsr = in_be32(&priv->msg_regs->pwsr);
 
 #ifdef DEBUG_PW
        pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
@@ -1094,20 +1106,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
                pr_debug(" PWB");
        pr_debug(" )\n");
 #endif
-       out_be32(&priv->msg_regs->pwsr,
-                ipwsr & (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
-
-       if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
-               priv->port_write_msg.err_count++;
-               pr_info("RIO: Port-Write Transaction Err (%d)\n",
-                        priv->port_write_msg.err_count);
-       }
-       if (ipwsr & RIO_IPWSR_PWD) {
-               priv->port_write_msg.discard_count++;
-               pr_info("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
-                        priv->port_write_msg.discard_count);
-       }
-
        /* Schedule deferred processing if PW was received */
        if (ipwsr & RIO_IPWSR_QFI) {
                /* Save PW message (if there is room in FIFO),
@@ -1119,16 +1117,43 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
                                 RIO_PW_MSG_SIZE);
                } else {
                        priv->port_write_msg.discard_count++;
-                       pr_info("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
+                       pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
                                 priv->port_write_msg.discard_count);
                }
+               /* Clear interrupt and issue Clear Queue command. This allows
+                * another port-write to be received.
+                */
+               out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_QFI);
+               out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
+
                schedule_work(&priv->pw_work);
        }
 
-       /* Issue Clear Queue command. This allows another
-        * port-write to be received.
-        */
-       out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
+       if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
+               priv->port_write_msg.err_count++;
+               pr_debug("RIO: Port-Write Transaction Err (%d)\n",
+                        priv->port_write_msg.err_count);
+               /* Clear Transaction Error: port-write controller should be
+                * disabled when clearing this error
+                */
+               out_be32(&priv->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE);
+               out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_TE);
+               out_be32(&priv->msg_regs->pwmr, ipwmr);
+       }
+
+       if (ipwsr & RIO_IPWSR_PWD) {
+               priv->port_write_msg.discard_count++;
+               pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
+                        priv->port_write_msg.discard_count);
+               out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_PWD);
+       }
+
+pw_done:
+       if (epwisr & RIO_EPWISR_PINT) {
+               tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
+               pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
+               out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
+       }
 
        return IRQ_HANDLED;
 }