Merge branch 'msm-mmc_sdcc' of git://codeaurora.org/quic/kernel/dwalker/linux-msm
[safe/jmp/linux-2.6] / drivers / spi / amba-pl022.c
index 958a3ff..e9aeee1 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 
 /*
  * This macro is used to define some register default values.
@@ -363,6 +364,7 @@ struct pl022 {
        void                            *rx_end;
        enum ssp_reading                read;
        enum ssp_writing                write;
+       u32                             exp_fifo_level;
 };
 
 /**
@@ -501,6 +503,9 @@ static int flush(struct pl022 *pl022)
                while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
                        readw(SSP_DR(pl022->virtbase));
        } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--);
+
+       pl022->exp_fifo_level = 0;
+
        return limit;
 }
 
@@ -583,10 +588,9 @@ static void readwriter(struct pl022 *pl022)
         * errons in 8bit wide transfers on ARM variants (just 8 words
         * FIFO, means only 8x8 = 64 bits in FIFO) at least.
         *
-        * FIXME: currently we have no logic to account for this.
-        * perhaps there is even something broken in HW regarding
-        * 8bit transfers (it doesn't fail on 16bit) so this needs
-        * more investigation...
+        * To prevent this issue, the TX FIFO is only filled to the
+        * unused RX FIFO fill length, regardless of what the TX
+        * FIFO status flag indicates.
         */
        dev_dbg(&pl022->adev->dev,
                "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n",
@@ -613,11 +617,12 @@ static void readwriter(struct pl022 *pl022)
                        break;
                }
                pl022->rx += (pl022->cur_chip->n_bytes);
+               pl022->exp_fifo_level--;
        }
        /*
-        * Write as much as you can, while keeping an eye on the RX FIFO!
+        * Write as much as possible up to the RX FIFO size
         */
-       while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
+       while ((pl022->exp_fifo_level < pl022->vendor->fifodepth)
               && (pl022->tx < pl022->tx_end)) {
                switch (pl022->write) {
                case WRITING_NULL:
@@ -634,6 +639,7 @@ static void readwriter(struct pl022 *pl022)
                        break;
                }
                pl022->tx += (pl022->cur_chip->n_bytes);
+               pl022->exp_fifo_level++;
                /*
                 * This inner reader takes care of things appearing in the RX
                 * FIFO as we're transmitting. This will happen a lot since the
@@ -660,6 +666,7 @@ static void readwriter(struct pl022 *pl022)
                                break;
                        }
                        pl022->rx += (pl022->cur_chip->n_bytes);
+                       pl022->exp_fifo_level--;
                }
        }
        /*
@@ -1826,7 +1833,7 @@ static struct amba_id pl022_ids[] = {
                 * ST Micro derivative, this has 32bit wide
                 * and 32 locations deep TX/RX FIFO
                 */
-               .id     = 0x00108022,
+               .id     = 0x01080022,
                .mask   = 0xffffffff,
                .data   = &vendor_st,
        },