netxen_nic: Fix the tx queue manipulation bug in netxen_nic_probe
[pandora-kernel.git] / drivers / spi / omap2_mcspi.c
index b3a94ca..2a651e6 100644 (file)
@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
        return 0;
 }
 
+static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(1000);
+       while (!(__raw_readl(reg) & bit)) {
+               if (time_after(jiffies, timeout))
+                       return -1;
+               cpu_relax();
+       }
+       return 0;
+}
+
 static unsigned
 omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        u32                     l;
        u8                      * rx;
        const u8                * tx;
+       void __iomem            *chstat_reg;
 
        mcspi = spi_master_get_devdata(spi->master);
        mcspi_dma = &mcspi->dma_channels[spi->chip_select];
        l = mcspi_cached_chconf0(spi);
 
+       chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
+
        count = xfer->len;
        c = count;
        word_len = cs->word_len;
@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        if (tx != NULL) {
                wait_for_completion(&mcspi_dma->dma_tx_completion);
                dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
+
+               /* for TX_ONLY mode, be sure all words have shifted out */
+               if (rx == NULL) {
+                       if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_TXS) < 0)
+                               dev_err(&spi->dev, "TXS timed out\n");
+                       else if (mcspi_wait_for_reg_bit(chstat_reg,
+                                               OMAP2_MCSPI_CHSTAT_EOT) < 0)
+                               dev_err(&spi->dev, "EOT timed out\n");
+               }
        }
 
        if (rx != NULL) {
@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        return count;
 }
 
-static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
-{
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(1000);
-       while (!(__raw_readl(reg) & bit)) {
-               if (time_after(jiffies, timeout))
-                       return -1;
-               cpu_relax();
-       }
-       return 0;
-}
-
 static unsigned
 omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 {
@@ -489,10 +502,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        dev_err(&spi->dev, "TXS timed out\n");
                                        goto out;
                                }
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "write-%d %02x\n",
+                               dev_vdbg(&spi->dev, "write-%d %02x\n",
                                                word_len, *tx);
-#endif
                                __raw_writel(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
@@ -506,10 +517,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
                                        *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                                       dev_dbg(&spi->dev, "read-%d %02x\n",
+                                       dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                    word_len, *(rx - 1));
-#endif
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
                                                OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                                                dev_err(&spi->dev,
@@ -522,10 +531,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
 
                                *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "read-%d %02x\n",
+                               dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                word_len, *(rx - 1));
-#endif
                        }
                } while (c);
        } else if (word_len <= 16) {
@@ -542,10 +549,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        dev_err(&spi->dev, "TXS timed out\n");
                                        goto out;
                                }
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "write-%d %04x\n",
+                               dev_vdbg(&spi->dev, "write-%d %04x\n",
                                                word_len, *tx);
-#endif
                                __raw_writel(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
@@ -559,10 +564,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
                                        *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                                       dev_dbg(&spi->dev, "read-%d %04x\n",
+                                       dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                    word_len, *(rx - 1));
-#endif
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
                                                OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                                                dev_err(&spi->dev,
@@ -575,10 +578,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
 
                                *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "read-%d %04x\n",
+                               dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                word_len, *(rx - 1));
-#endif
                        }
                } while (c);
        } else if (word_len <= 32) {
@@ -595,10 +596,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        dev_err(&spi->dev, "TXS timed out\n");
                                        goto out;
                                }
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "write-%d %08x\n",
+                               dev_vdbg(&spi->dev, "write-%d %08x\n",
                                                word_len, *tx);
-#endif
                                __raw_writel(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
@@ -612,10 +611,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
                                        *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                                       dev_dbg(&spi->dev, "read-%d %08x\n",
+                                       dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                    word_len, *(rx - 1));
-#endif
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
                                                OMAP2_MCSPI_CHSTAT_RXS) < 0) {
                                                dev_err(&spi->dev,
@@ -628,10 +625,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
 
                                *rx++ = __raw_readl(rx_reg);
-#ifdef VERBOSE
-                               dev_dbg(&spi->dev, "read-%d %08x\n",
+                               dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                word_len, *(rx - 1));
-#endif
                        }
                } while (c);
        }
@@ -644,6 +639,12 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                } else if (mcspi_wait_for_reg_bit(chstat_reg,
                                OMAP2_MCSPI_CHSTAT_EOT) < 0)
                        dev_err(&spi->dev, "EOT timed out\n");
+
+               /* disable chan to purge rx datas received in TX_ONLY transfer,
+                * otherwise these rx datas will affect the direct following
+                * RX_ONLY transfer.
+                */
+               omap2_mcspi_set_enable(spi, 0);
        }
 out:
        omap2_mcspi_set_enable(spi, 1);