Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / powerpc / sysdev / fsl_rio.c
index 3017532..9725369 100644 (file)
@@ -50,6 +50,7 @@
 #define RIO_ATMU_REGS_OFFSET   0x10c00
 #define RIO_P_MSG_REGS_OFFSET  0x11000
 #define RIO_S_MSG_REGS_OFFSET  0x13000
+#define RIO_GCCSR              0x13c
 #define RIO_ESCSR              0x158
 #define RIO_CCSR               0x15c
 #define RIO_LTLEDCSR           0x0608
@@ -87,6 +88,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 +121,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 +1086,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 +1107,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 +1118,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;
 }
@@ -1446,6 +1472,7 @@ int fsl_rio_setup(struct platform_device *dev)
        port->host_deviceid = fsl_rio_get_hdid(port->id);
 
        port->priv = priv;
+       port->phys_efptr = 0x100;
        rio_register_mport(port);
 
        priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
@@ -1493,6 +1520,12 @@ int fsl_rio_setup(struct platform_device *dev)
        dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
                        port->sys_size ? 65536 : 256);
 
+       if (port->host_deviceid >= 0)
+               out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
+                       RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
+       else
+               out_be32(priv->regs_win + RIO_GCCSR, 0x00000000);
+
        priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
                                        + RIO_ATMU_REGS_OFFSET);
        priv->maint_atmu_regs = priv->atmu_regs + 1;