All of lore.kernel.org
 help / color / mirror / Atom feed
From: peter.crosthwaite@xilinx.com
To: peter.maydell@linaro.org, qemu-devel@nongnu.org
Cc: edgar.iglesias@gmail.com
Subject: [Qemu-devel] [PATCH arm-devs v4 11/15] xilinx_spips: Fix striping behaviour
Date: Tue, 21 May 2013 16:36:35 +1000	[thread overview]
Message-ID: <718a61df1bf746ec06f6da44d12f8317af7b08ce.1369117359.git.peter.crosthwaite@xilinx.com> (raw)
In-Reply-To: <cover.1369117359.git.peter.crosthwaite@xilinx.com>

From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

The QSPI controller was using byte-wide stripes when striping across
the two flashes in dual parallel mode. The real hardware however uses
individual bit striping. QEMU misbehaves in the (corner) case where
data is written/read in dual-parallel mode and read/written back in
single mode.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
---
changed from v1:
comment the stipe function (PMM review)

 hw/ssi/xilinx_spips.c | 84 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 63 insertions(+), 21 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 3e9e76c..7222e15 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -273,35 +273,77 @@ static void xilinx_spips_reset(DeviceState *d)
     xilinx_spips_update_cs_lines(s);
 }
 
+/* N way (num) in place bit striper. Lay out row wise bits (LSB to MSB)
+ * column wise (from element 0 to N-1). num is the length of x, and dir
+ * reverses the direction of the transform. Best illustrated by example:
+ * Each digit in the below array is a single bit (num == 3):
+ *
+ * {{ 76543210, }  ----- stripe (dir == false) -----> {{ FCheb630, }
+ *  { hgfedcba, }                                      { GDAfc741, }
+ *  { HGFEDCBA, }} <---- upstripe (dir == true) -----  { HEBgda52, }}
+ */
+
+static inline void stripe8(uint8_t *x, int num, bool dir)
+{
+    uint8_t r[num];
+    memset(r, 0, sizeof(uint8_t) * num);
+    int idx[2] = {0, 0};
+    int bit[2] = {0, 0};
+    int d = dir;
+
+    for (idx[0] = 0; idx[0] < num; ++idx[0]) {
+        for (bit[0] = 0; bit[0] < 8; ++bit[0]) {
+            r[idx[d]] |= x[idx[!d]] & 1 << bit[!d] ? 1 << bit[d] : 0;
+            idx[1] = (idx[1] + 1) % num;
+            if (!idx[1]) {
+                bit[1]++;
+            }
+        }
+    }
+    memcpy(x, r, sizeof(uint8_t) * num);
+}
+
 static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 {
     for (;;) {
         int i;
-        uint8_t rx;
         uint8_t tx = 0;
+        uint8_t tx_rx[num_effective_busses(s)];
 
-        for (i = 0; i < num_effective_busses(s); ++i) {
-            if (!i || s->snoop_state == SNOOP_STRIPING) {
-                if (fifo8_is_empty(&s->tx_fifo)) {
-                    if (!(s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE)) {
-                        s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW;
-                    }
-                    xilinx_spips_update_ixr(s);
-                    return;
-                } else {
-                    tx = fifo8_pop(&s->tx_fifo);
-                }
+        if (fifo8_is_empty(&s->tx_fifo)) {
+            if (!(s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE)) {
+                s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW;
             }
-            rx = ssi_transfer(s->spi[i], (uint32_t)tx);
-            DB_PRINT("tx = %02x rx = %02x\n", tx, rx);
-            if (!i || s->snoop_state == SNOOP_STRIPING) {
-                if (fifo8_is_full(&s->rx_fifo)) {
-                    s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW;
-                    DB_PRINT("rx FIFO overflow");
-                } else {
-                    fifo8_push(&s->rx_fifo, (uint8_t)rx);
-                }
+            xilinx_spips_update_ixr(s);
+            return;
+        } else if (s->snoop_state == SNOOP_STRIPING) {
+            for (i = 0; i < num_effective_busses(s); ++i) {
+                tx_rx[i] = fifo8_pop(&s->tx_fifo);
             }
+            stripe8(tx_rx, num_effective_busses(s), false);
+        } else {
+            tx = fifo8_pop(&s->tx_fifo);
+            for (i = 0; i < num_effective_busses(s); ++i) {
+                tx_rx[i] = tx;
+            }
+        }
+
+        for (i = 0; i < num_effective_busses(s); ++i) {
+            DB_PRINT("tx = %02x\n", tx_rx[i]);
+            tx_rx[i] = ssi_transfer(s->spi[i], (uint32_t)tx_rx[i]);
+            DB_PRINT("rx = %02x\n", tx_rx[i]);
+        }
+
+        if (fifo8_is_full(&s->rx_fifo)) {
+            s->regs[R_INTR_STATUS] |= IXR_RX_FIFO_OVERFLOW;
+            DB_PRINT("rx FIFO overflow");
+        } else if (s->snoop_state == SNOOP_STRIPING) {
+            stripe8(tx_rx, num_effective_busses(s), true);
+            for (i = 0; i < num_effective_busses(s); ++i) {
+                fifo8_push(&s->rx_fifo, (uint8_t)tx_rx[i]);
+            }
+        } else {
+           fifo8_push(&s->rx_fifo, (uint8_t)tx_rx[0]);
         }
 
         switch (s->snoop_state) {
-- 
1.8.3.rc1.44.gb387c77.dirty

  parent reply	other threads:[~2013-05-21  6:40 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
2013-05-21  6:29 ` [Qemu-devel] [PATCH arm-devs v4 01/15] xilinx_spips: seperate SPI and QSPI as two classes peter.crosthwaite
2013-05-21  6:30 ` [Qemu-devel] [PATCH arm-devs v4 02/15] xilinx_spips: Make interrupts clear on read peter.crosthwaite
2013-05-21  6:30 ` [Qemu-devel] [PATCH arm-devs v4 03/15] xilinx_spips: Inhibit interrupts in LQSPI mode peter.crosthwaite
2013-05-21  6:31 ` [Qemu-devel] [PATCH arm-devs v4 04/15] xilinx_spips: Add verbose LQSPI debug output peter.crosthwaite
2013-05-21  6:32 ` [Qemu-devel] [PATCH arm-devs v4 05/15] xilinx_spips: Fix QSPI FIFO size peter.crosthwaite
2013-05-21  6:32 ` [Qemu-devel] [PATCH arm-devs v4 06/15] xilinx_spips: Trash LQ page cache on mode change peter.crosthwaite
2013-05-21  6:33 ` [Qemu-devel] [PATCH arm-devs v4 07/15] xilinx_spips: Add automatic start support peter.crosthwaite
2013-05-21  6:34 ` [Qemu-devel] [PATCH arm-devs v4 08/15] xilinx_spips: Implement automatic CS peter.crosthwaite
2013-05-21  6:35 ` [Qemu-devel] [PATCH arm-devs v4 09/15] xilinx_spips: lqspi: Dont touch config register peter.crosthwaite
2013-05-21  6:35 ` [Qemu-devel] [PATCH arm-devs v4 10/15] xilinx_spips: Fix CTRL register RW bits peter.crosthwaite
2013-05-21  6:36 ` peter.crosthwaite [this message]
2013-05-21  6:37 ` [Qemu-devel] [PATCH arm-devs v4 12/15] xilinx_spips: Debug msgs for Snoop state peter.crosthwaite
2013-05-21  6:38 ` [Qemu-devel] [PATCH arm-devs v4 13/15] xilinx_spips: Multiple debug verbosity levels peter.crosthwaite
2013-05-21  6:38 ` [Qemu-devel] [PATCH arm-devs v4 14/15] xilinx_spips: lqspi: Push more data to tx-fifo peter.crosthwaite
2013-05-21  6:39 ` [Qemu-devel] [PATCH arm-devs v4 15/15] xilinx_spips: lqspi: Fix byte/misaligned access peter.crosthwaite
2013-05-24 12:57 ` [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=718a61df1bf746ec06f6da44d12f8317af7b08ce.1369117359.git.peter.crosthwaite@xilinx.com \
    --to=peter.crosthwaite@xilinx.com \
    --cc=edgar.iglesias@gmail.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.