All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2
@ 2013-05-21  6:28 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
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:28 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

Updates to the Zynq SPI controller. Some QOMifying cleanup, followed by
a number of bugs/incompletnesses found by some (very) rigourous test
vectors.

changed from v4:
Address PMM review (P5 and P8)
changed from v3:
Fixed break after goto (PMM review)


Peter Crosthwaite (15):
  xilinx_spips: seperate SPI and QSPI as two classes
  xilinx_spips: Make interrupts clear on read
  xilinx_spips: Inhibit interrupts in LQSPI mode
  xilinx_spips: Add verbose LQSPI debug output
  xilinx_spips: Fix QSPI FIFO size
  xilinx_spips: Trash LQ page cache on mode change
  xilinx_spips: Add automatic start support
  xilinx_spips: Implement automatic CS
  xilinx_spips: lqspi: Dont touch config register
  xilinx_spips: Fix CTRL register RW bits
  xilinx_spips: Fix striping behaviour
  xilinx_spips: Debug msgs for Snoop state
  xilinx_spips: Multiple debug verbosity levels
  xilinx_spips: lqspi: Push more data to tx-fifo
  xilinx_spips: lqspi: Fix byte/misaligned access

 hw/arm/xilinx_zynq.c  |   2 +-
 hw/ssi/xilinx_spips.c | 320 ++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 249 insertions(+), 73 deletions(-)

-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 01/15] xilinx_spips: seperate SPI and QSPI as two classes
  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 ` peter.crosthwaite
  2013-05-21  6:30 ` [Qemu-devel] [PATCH arm-devs v4 02/15] xilinx_spips: Make interrupts clear on read peter.crosthwaite
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:29 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

Make SPI and QSPI different classes. QSPIPS is setup as a child of SPIPS.
Only QSPI has the LQSPI functionality, so move all that to the child class.

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 v2:
User parent_obj as appropriate for QOM parents (PMM review)
Changed from v1:
Fixed compile bug (s/XILINX_SPIPS/XILINX_QSPIPS on QOM cast)

 hw/arm/xilinx_zynq.c  |  2 +-
 hw/ssi/xilinx_spips.c | 69 ++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 41505c3..4602a6f 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -66,7 +66,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
     int num_busses =  is_qspi ? NUM_QSPI_BUSSES : 1;
     int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
 
-    dev = qdev_create(NULL, "xilinx,spips");
+    dev = qdev_create(NULL, is_qspi ? "xlnx.ps7-qspi" : "xlnx.ps7-spi");
     qdev_prop_set_uint8(dev, "num-txrx-bytes", is_qspi ? 4 : 1);
     qdev_prop_set_uint8(dev, "num-ss-bits", num_ss);
     qdev_prop_set_uint8(dev, "num-busses", num_busses);
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index b2397f4..734adf0 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -129,7 +129,8 @@ typedef enum {
 } FlashCMD;
 
 typedef struct {
-    SysBusDevice busdev;
+    SysBusDevice parent_obj;
+
     MemoryRegion iomem;
     MemoryRegion mmlqspi;
 
@@ -149,15 +150,23 @@ typedef struct {
     uint8_t num_txrx_bytes;
 
     uint32_t regs[R_MAX];
+} XilinxSPIPS;
+
+typedef struct {
+    XilinxSPIPS parent_obj;
 
     uint32_t lqspi_buf[LQSPI_CACHE_SIZE];
     hwaddr lqspi_cached_addr;
-} XilinxSPIPS;
+} XilinxQSPIPS;
+
 
-#define TYPE_XILINX_SPIPS "xilinx,spips"
+#define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
+#define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
 
 #define XILINX_SPIPS(obj) \
      OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS)
+#define XILINX_QSPIPS(obj) \
+     OBJECT_CHECK(XilinxQSPIPS, (obj), TYPE_XILINX_QSPIPS)
 
 static inline int num_effective_busses(XilinxSPIPS *s)
 {
@@ -436,11 +445,12 @@ static uint64_t
 lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 {
     int i;
+    XilinxQSPIPS *q = opaque;
     XilinxSPIPS *s = opaque;
 
-    if (addr >= s->lqspi_cached_addr &&
-            addr <= s->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-        return s->lqspi_buf[(addr - s->lqspi_cached_addr) >> 2];
+    if (addr >= q->lqspi_cached_addr &&
+            addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
+        return q->lqspi_buf[(addr - q->lqspi_cached_addr) >> 2];
     } else {
         int flash_addr = (addr / num_effective_busses(s));
         int slave = flash_addr >> LQSPI_ADDRESS_BITS;
@@ -484,14 +494,14 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
         for (i = 0; i < LQSPI_CACHE_SIZE / 4; ++i) {
             tx_data_bytes(s, 0, 4);
             xilinx_spips_flush_txfifo(s);
-            rx_data_bytes(s, &s->lqspi_buf[cache_entry], 4);
+            rx_data_bytes(s, &q->lqspi_buf[cache_entry], 4);
             cache_entry++;
         }
 
         s->regs[R_CONFIG] |= CS;
         xilinx_spips_update_cs_lines(s);
 
-        s->lqspi_cached_addr = addr;
+        q->lqspi_cached_addr = addr;
         return lqspi_read(opaque, addr, size);
     }
 }
@@ -511,7 +521,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     int i;
 
-    DB_PRINT("inited device model\n");
+    DB_PRINT("realized spips\n");
 
     s->spi = g_new(SSIBus *, s->num_busses);
     for (i = 0; i < s->num_busses; ++i) {
@@ -531,17 +541,32 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
     memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4);
     sysbus_init_mmio(sbd, &s->iomem);
 
-    memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi",
-                          (1 << LQSPI_ADDRESS_BITS) * 2);
-    sysbus_init_mmio(sbd, &s->mmlqspi);
-
     s->irqline = -1;
-    s->lqspi_cached_addr = ~0ULL;
 
     fifo8_create(&s->rx_fifo, RXFF_A);
     fifo8_create(&s->tx_fifo, TXFF_A);
 }
 
+static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
+{
+    XilinxSPIPS *s = XILINX_SPIPS(dev);
+    XilinxQSPIPS *q = XILINX_QSPIPS(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    DB_PRINT("realized qspips\n");
+
+    s->num_busses = 2;
+    s->num_cs = 2;
+    s->num_txrx_bytes = 4;
+
+    xilinx_spips_realize(dev, errp);
+    memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi",
+                          (1 << LQSPI_ADDRESS_BITS) * 2);
+    sysbus_init_mmio(sbd, &s->mmlqspi);
+
+    q->lqspi_cached_addr = ~0ULL;
+}
+
 static int xilinx_spips_post_load(void *opaque, int version_id)
 {
     xilinx_spips_update_ixr((XilinxSPIPS *)opaque);
@@ -570,6 +595,14 @@ static Property xilinx_spips_properties[] = {
     DEFINE_PROP_UINT8("num-txrx-bytes", XilinxSPIPS, num_txrx_bytes, 1),
     DEFINE_PROP_END_OF_LIST(),
 };
+
+static void xilinx_qspips_class_init(ObjectClass *klass, void * data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = xilinx_qspips_realize;
+}
+
 static void xilinx_spips_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -587,9 +620,17 @@ static const TypeInfo xilinx_spips_info = {
     .class_init = xilinx_spips_class_init,
 };
 
+static const TypeInfo xilinx_qspips_info = {
+    .name  = TYPE_XILINX_QSPIPS,
+    .parent = TYPE_XILINX_SPIPS,
+    .instance_size  = sizeof(XilinxQSPIPS),
+    .class_init = xilinx_qspips_class_init,
+};
+
 static void xilinx_spips_register_types(void)
 {
     type_register_static(&xilinx_spips_info);
+    type_register_static(&xilinx_qspips_info);
 }
 
 type_init(xilinx_spips_register_types)
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 02/15] xilinx_spips: Make interrupts clear on read
  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 ` peter.crosthwaite
  2013-05-21  6:30 ` [Qemu-devel] [PATCH arm-devs v4 03/15] xilinx_spips: Inhibit interrupts in LQSPI mode peter.crosthwaite
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:30 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

By default these interrupts are clear on read.

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>
---

 hw/ssi/xilinx_spips.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 734adf0..261d948 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -330,6 +330,10 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
         mask = 0x0002FFFF;
         break;
     case R_INTR_STATUS:
+        ret = s->regs[addr] & IXR_ALL;
+        s->regs[addr] = 0;
+        DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
+        return ret;
     case R_INTR_MASK:
         mask = IXR_ALL;
         break;
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 03/15] xilinx_spips: Inhibit interrupts in LQSPI mode
  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 ` peter.crosthwaite
  2013-05-21  6:31 ` [Qemu-devel] [PATCH arm-devs v4 04/15] xilinx_spips: Add verbose LQSPI debug output peter.crosthwaite
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:30 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

The real hardware does not produce interrupts in LQSPI mode. Inhibit
generation of interrupts when the LQ_MODE bit is set.

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>
---

 hw/ssi/xilinx_spips.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 261d948..a8691d5 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -204,6 +204,9 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
 
 static void xilinx_spips_update_ixr(XilinxSPIPS *s)
 {
+    if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_LQ_MODE) {
+        return;
+    }
     /* These are set/cleared as they occur */
     s->regs[R_INTR_STATUS] &= (IXR_TX_FIFO_UNDERFLOW | IXR_RX_FIFO_OVERFLOW |
                                 IXR_TX_FIFO_MODE_FAIL);
@@ -256,7 +259,9 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
         for (i = 0; i < num_effective_busses(s); ++i) {
             if (!i || s->snoop_state == SNOOP_STRIPING) {
                 if (fifo8_is_empty(&s->tx_fifo)) {
-                    s->regs[R_INTR_STATUS] |= IXR_TX_FIFO_UNDERFLOW;
+                    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 {
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 04/15] xilinx_spips: Add verbose LQSPI debug output
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (2 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-21  6:32 ` [Qemu-devel] [PATCH arm-devs v4 05/15] xilinx_spips: Fix QSPI FIFO size peter.crosthwaite
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:31 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

You really need this is you want to track a guest banging on LQSPI.

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>
---

 hw/ssi/xilinx_spips.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index a8691d5..29636ce 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -456,10 +456,13 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
     int i;
     XilinxQSPIPS *q = opaque;
     XilinxSPIPS *s = opaque;
+    uint32_t ret;
 
     if (addr >= q->lqspi_cached_addr &&
             addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-        return q->lqspi_buf[(addr - q->lqspi_cached_addr) >> 2];
+        ret = q->lqspi_buf[(addr - q->lqspi_cached_addr) >> 2];
+        DB_PRINT("addr: %08x, data: %08x\n", (unsigned)addr, (unsigned)ret);
+        return ret;
     } else {
         int flash_addr = (addr / num_effective_busses(s));
         int slave = flash_addr >> LQSPI_ADDRESS_BITS;
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 05/15] xilinx_spips: Fix QSPI FIFO size
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (3 preceding siblings ...)
  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 ` 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
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:32 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

QSPI has a bigger FIFO than the regular SPI controller. Differentiate
between the two with correct FIFO sizes for each.

This is the first piece of class data for SPIPS, so this patch sees
the creation of the XilinxSPIPSClass definition and assoicated QOM
constructs.

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 v3:
removed space after sizeof (PMM review)
changed from v1:
Reimplemented using class data (PMM review)

 hw/ssi/xilinx_spips.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 29636ce..86f33ef 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -106,6 +106,9 @@
 #define RXFF_A          32
 #define TXFF_A          32
 
+#define RXFF_A_Q          (64 * 4)
+#define TXFF_A_Q          (64 * 4)
+
 /* 16MB per linear region */
 #define LQSPI_ADDRESS_BITS 24
 /* Bite off 4k chunks at a time */
@@ -159,12 +162,23 @@ typedef struct {
     hwaddr lqspi_cached_addr;
 } XilinxQSPIPS;
 
+typedef struct XilinxSPIPSClass {
+    SysBusDeviceClass parent_class;
+
+    uint32_t rx_fifo_size;
+    uint32_t tx_fifo_size;
+} XilinxSPIPSClass;
 
 #define TYPE_XILINX_SPIPS "xlnx.ps7-spi"
 #define TYPE_XILINX_QSPIPS "xlnx.ps7-qspi"
 
 #define XILINX_SPIPS(obj) \
      OBJECT_CHECK(XilinxSPIPS, (obj), TYPE_XILINX_SPIPS)
+#define XILINX_SPIPS_CLASS(klass) \
+     OBJECT_CLASS_CHECK(XilinxSPIPSClass, (klass), TYPE_XILINX_SPIPS)
+#define XILINX_SPIPS_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(XilinxSPIPSClass, (obj), TYPE_XILINX_SPIPS)
+
 #define XILINX_QSPIPS(obj) \
      OBJECT_CHECK(XilinxQSPIPS, (obj), TYPE_XILINX_QSPIPS)
 
@@ -531,6 +545,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
 {
     XilinxSPIPS *s = XILINX_SPIPS(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
     int i;
 
     DB_PRINT("realized spips\n");
@@ -555,8 +570,8 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
 
     s->irqline = -1;
 
-    fifo8_create(&s->rx_fifo, RXFF_A);
-    fifo8_create(&s->tx_fifo, TXFF_A);
+    fifo8_create(&s->rx_fifo, xsc->rx_fifo_size);
+    fifo8_create(&s->tx_fifo, xsc->tx_fifo_size);
 }
 
 static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
@@ -611,18 +626,25 @@ static Property xilinx_spips_properties[] = {
 static void xilinx_qspips_class_init(ObjectClass *klass, void * data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
 
     dc->realize = xilinx_qspips_realize;
+    xsc->rx_fifo_size = RXFF_A_Q;
+    xsc->tx_fifo_size = TXFF_A_Q;
 }
 
 static void xilinx_spips_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
 
     dc->realize = xilinx_spips_realize;
     dc->reset = xilinx_spips_reset;
     dc->props = xilinx_spips_properties;
     dc->vmsd = &vmstate_xilinx_spips;
+
+    xsc->rx_fifo_size = RXFF_A;
+    xsc->tx_fifo_size = TXFF_A;
 }
 
 static const TypeInfo xilinx_spips_info = {
@@ -630,6 +652,7 @@ static const TypeInfo xilinx_spips_info = {
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size  = sizeof(XilinxSPIPS),
     .class_init = xilinx_spips_class_init,
+    .class_size = sizeof(XilinxSPIPSClass),
 };
 
 static const TypeInfo xilinx_qspips_info = {
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 06/15] xilinx_spips: Trash LQ page cache on mode change
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (4 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-21  6:33 ` [Qemu-devel] [PATCH arm-devs v4 07/15] xilinx_spips: Add automatic start support peter.crosthwaite
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:32 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

Invalidate the LQSPI cached page when transitioning into LQSPI mode.
Otherwise there is a possibility that the controller will return stale
data to the guest when transitioning back to LQ_MODE after a page
program.

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 v2:
Removed extraneous break after goto (PMM review)
changed from v1:
Re-implemented using separate SPI/QSPI write handlers.

 hw/ssi/xilinx_spips.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 86f33ef..cf4c43e 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -165,6 +165,8 @@ typedef struct {
 typedef struct XilinxSPIPSClass {
     SysBusDeviceClass parent_class;
 
+    const MemoryRegionOps *reg_ops;
+
     uint32_t rx_fifo_size;
     uint32_t tx_fifo_size;
 } XilinxSPIPSClass;
@@ -462,6 +464,25 @@ static const MemoryRegionOps spips_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void xilinx_qspips_write(void *opaque, hwaddr addr,
+                                uint64_t value, unsigned size)
+{
+    XilinxQSPIPS *q = XILINX_QSPIPS(opaque);
+
+    xilinx_spips_write(opaque, addr, value, size);
+    addr >>= 2;
+
+    if (addr == R_LQSPI_CFG) {
+        q->lqspi_cached_addr = ~0ULL;
+    }
+}
+
+static const MemoryRegionOps qspips_ops = {
+    .read = xilinx_spips_read,
+    .write = xilinx_qspips_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 #define LQSPI_CACHE_SIZE 1024
 
 static uint64_t
@@ -565,7 +586,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
         sysbus_init_irq(sbd, &s->cs_lines[i]);
     }
 
-    memory_region_init_io(&s->iomem, &spips_ops, s, "spi", R_MAX*4);
+    memory_region_init_io(&s->iomem, xsc->reg_ops, s, "spi", R_MAX*4);
     sysbus_init_mmio(sbd, &s->iomem);
 
     s->irqline = -1;
@@ -629,6 +650,7 @@ static void xilinx_qspips_class_init(ObjectClass *klass, void * data)
     XilinxSPIPSClass *xsc = XILINX_SPIPS_CLASS(klass);
 
     dc->realize = xilinx_qspips_realize;
+    xsc->reg_ops = &qspips_ops;
     xsc->rx_fifo_size = RXFF_A_Q;
     xsc->tx_fifo_size = TXFF_A_Q;
 }
@@ -643,6 +665,7 @@ static void xilinx_spips_class_init(ObjectClass *klass, void *data)
     dc->props = xilinx_spips_properties;
     dc->vmsd = &vmstate_xilinx_spips;
 
+    xsc->reg_ops = &spips_ops;
     xsc->rx_fifo_size = RXFF_A;
     xsc->tx_fifo_size = TXFF_A;
 }
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 07/15] xilinx_spips: Add automatic start support
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (5 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-21  6:34 ` [Qemu-devel] [PATCH arm-devs v4 08/15] xilinx_spips: Implement automatic CS peter.crosthwaite
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:33 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

SPI has a mode where it automatically starts based on tx fifo
occupancy. Implemented.

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>
---

 hw/ssi/xilinx_spips.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index cf4c43e..0c04ec9 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -451,7 +451,8 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
     }
     s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
 no_reg_update:
-    if (man_start_com) {
+    if ((man_start_com && s->regs[R_CONFIG] & MAN_START_EN) ||
+            (fifo8_is_empty(&s->tx_fifo) && s->regs[R_CONFIG] & MAN_START_EN)) {
         xilinx_spips_flush_txfifo(s);
     }
     xilinx_spips_update_ixr(s);
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 08/15] xilinx_spips: Implement automatic CS
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (6 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-21  6:35 ` [Qemu-devel] [PATCH arm-devs v4 09/15] xilinx_spips: lqspi: Dont touch config register peter.crosthwaite
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:34 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

Implement the automatic CS control feature. If the MANUAL_CS bit is
cleared then the chip select stay de-asserted as long as the tx FIFO
is empty.

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 v3:
remove usage on DB_PRINT_L (PMM review)
changed from v1:
Refresh CS on entry and exit from flush routine as needed.

 hw/ssi/xilinx_spips.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 0c04ec9..631d010 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -190,6 +190,12 @@ static inline int num_effective_busses(XilinxSPIPS *s)
             s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM) ? s->num_busses : 1;
 }
 
+static inline bool xilinx_spips_cs_is_set(XilinxSPIPS *s, int i, int field)
+{
+    return ~field & (1 << i) && (s->regs[R_CONFIG] & MANUAL_CS
+                    || !fifo8_is_empty(&s->tx_fifo));
+}
+
 static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
 {
     int i, j;
@@ -202,14 +208,15 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
             int cs_to_set = (j * s->num_cs + i + upage) %
                                 (s->num_cs * s->num_busses);
 
-            if (~field & (1 << i) && !found) {
+            if (xilinx_spips_cs_is_set(s, i, field) && !found) {
                 DB_PRINT("selecting slave %d\n", i);
                 qemu_set_irq(s->cs_lines[cs_to_set], 0);
             } else {
+                DB_PRINT("deselecting slave %d\n", i);
                 qemu_set_irq(s->cs_lines[cs_to_set], 1);
             }
         }
-        if (~field & (1 << i)) {
+        if (xilinx_spips_cs_is_set(s, i, field)) {
             found = true;
         }
     }
@@ -451,12 +458,13 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
     }
     s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
 no_reg_update:
+    xilinx_spips_update_cs_lines(s);
     if ((man_start_com && s->regs[R_CONFIG] & MAN_START_EN) ||
             (fifo8_is_empty(&s->tx_fifo) && s->regs[R_CONFIG] & MAN_START_EN)) {
         xilinx_spips_flush_txfifo(s);
     }
-    xilinx_spips_update_ixr(s);
     xilinx_spips_update_cs_lines(s);
+    xilinx_spips_update_ixr(s);
 }
 
 static const MemoryRegionOps spips_ops = {
@@ -510,7 +518,7 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
         fifo8_reset(&s->rx_fifo);
 
         s->regs[R_CONFIG] &= ~CS;
-        s->regs[R_CONFIG] |= (~(1 << slave) << CS_SHIFT) & CS;
+        s->regs[R_CONFIG] |= ((~(1 << slave) << CS_SHIFT) & CS) | MANUAL_CS;
         xilinx_spips_update_cs_lines(s);
 
         /* instruction */
@@ -534,6 +542,7 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
             DB_PRINT("pushing dummy byte\n");
             fifo8_push(&s->tx_fifo, 0);
         }
+        xilinx_spips_update_cs_lines(s);
         xilinx_spips_flush_txfifo(s);
         fifo8_reset(&s->rx_fifo);
 
@@ -545,6 +554,7 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
             rx_data_bytes(s, &q->lqspi_buf[cache_entry], 4);
             cache_entry++;
         }
+        xilinx_spips_update_cs_lines(s);
 
         s->regs[R_CONFIG] |= CS;
         xilinx_spips_update_cs_lines(s);
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 09/15] xilinx_spips: lqspi: Dont touch config register
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (7 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-21  6:35 ` [Qemu-devel] [PATCH arm-devs v4 10/15] xilinx_spips: Fix CTRL register RW bits peter.crosthwaite
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:35 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

The LQSPI mode is supposed to work via the automatic CS mode feature
rather than manipulate CS lines itself. Now that auto CS is implemented
remove LQSPIs CS mode override logic. There is still a need to
manipulate the U_PAGE bit in LQSPI config register to implement
dual-stack mode however.

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>
---
This patch in new as of v2

 hw/ssi/xilinx_spips.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 631d010..ea8a593 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -511,16 +511,16 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
         int flash_addr = (addr / num_effective_busses(s));
         int slave = flash_addr >> LQSPI_ADDRESS_BITS;
         int cache_entry = 0;
+        uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
+
+        s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
+        s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
 
         DB_PRINT("config reg status: %08x\n", s->regs[R_LQSPI_CFG]);
 
         fifo8_reset(&s->tx_fifo);
         fifo8_reset(&s->rx_fifo);
 
-        s->regs[R_CONFIG] &= ~CS;
-        s->regs[R_CONFIG] |= ((~(1 << slave) << CS_SHIFT) & CS) | MANUAL_CS;
-        xilinx_spips_update_cs_lines(s);
-
         /* instruction */
         DB_PRINT("pushing read instruction: %02x\n",
                  (uint8_t)(s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE));
@@ -554,9 +554,9 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
             rx_data_bytes(s, &q->lqspi_buf[cache_entry], 4);
             cache_entry++;
         }
-        xilinx_spips_update_cs_lines(s);
 
-        s->regs[R_CONFIG] |= CS;
+        s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
+        s->regs[R_LQSPI_STS] |= u_page_save;
         xilinx_spips_update_cs_lines(s);
 
         q->lqspi_cached_addr = addr;
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 10/15] xilinx_spips: Fix CTRL register RW bits
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (8 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-21  6:36 ` [Qemu-devel] [PATCH arm-devs v4 11/15] xilinx_spips: Fix striping behaviour peter.crosthwaite
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:35 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

The CTRL register was RAZ/WI on some of the RW bits. Even though the
function behind these bits is invalid in QEMU, they should still be
guest accessible. Fix.

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
Macroified magic number (PMM review)

 hw/ssi/xilinx_spips.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index ea8a593..3e9e76c 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -56,6 +56,7 @@
 #define CLK_PH              (1 << 2)
 #define CLK_POL             (1 << 1)
 #define MODE_SEL            (1 << 0)
+#define R_CONFIG_RSVD       (0x7bf40000)
 
 /* interrupt mechanism */
 #define R_INTR_STATUS       (0x04 / 4)
@@ -355,7 +356,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
     addr >>= 2;
     switch (addr) {
     case R_CONFIG:
-        mask = 0x0002FFFF;
+        mask = ~(R_CONFIG_RSVD | MAN_START_COM);
         break;
     case R_INTR_STATUS:
         ret = s->regs[addr] & IXR_ALL;
@@ -415,7 +416,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
     addr >>= 2;
     switch (addr) {
     case R_CONFIG:
-        mask = 0x0002FFFF;
+        mask = ~(R_CONFIG_RSVD | MAN_START_COM);
         if (value & MAN_START_COM) {
             man_start_com = 1;
         }
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 11/15] xilinx_spips: Fix striping behaviour
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (9 preceding siblings ...)
  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
  2013-05-21  6:37 ` [Qemu-devel] [PATCH arm-devs v4 12/15] xilinx_spips: Debug msgs for Snoop state peter.crosthwaite
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:36 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 12/15] xilinx_spips: Debug msgs for Snoop state
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (10 preceding siblings ...)
  2013-05-21  6:36 ` [Qemu-devel] [PATCH arm-devs v4 11/15] xilinx_spips: Fix striping behaviour peter.crosthwaite
@ 2013-05-21  6:37 ` peter.crosthwaite
  2013-05-21  6:38 ` [Qemu-devel] [PATCH arm-devs v4 13/15] xilinx_spips: Multiple debug verbosity levels peter.crosthwaite
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:37 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

This is worth keeping track of when debugging the device model.

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>
---

 hw/ssi/xilinx_spips.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 7222e15..8fbbd24 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -223,6 +223,7 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
     }
     if (!found) {
         s->snoop_state = SNOOP_CHECKING;
+        DB_PRINT("moving to snoop check state\n");
     }
 }
 
@@ -346,6 +347,7 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
            fifo8_push(&s->rx_fifo, (uint8_t)tx_rx[0]);
         }
 
+        DB_PRINT("initial snoop state: %x\n", (unsigned)s->snoop_state);
         switch (s->snoop_state) {
         case (SNOOP_CHECKING):
             switch (tx) { /* new instruction code */
@@ -374,6 +376,7 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
         default:
             s->snoop_state--;
         }
+        DB_PRINT("final snoop state: %x\n", (unsigned)s->snoop_state);
     }
 }
 
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 13/15] xilinx_spips: Multiple debug verbosity levels
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (11 preceding siblings ...)
  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 ` 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
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:38 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

The debug printfs on every SPI operation is extremely verbose. Add
a second level of debug for this.

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>
---

 hw/ssi/xilinx_spips.c | 70 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 42 insertions(+), 28 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 8fbbd24..665f471 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -30,15 +30,17 @@
 #include "hw/ssi.h"
 #include "qemu/bitops.h"
 
-#ifdef XILINX_SPIPS_ERR_DEBUG
-#define DB_PRINT(...) do { \
-    fprintf(stderr,  ": %s: ", __func__); \
-    fprintf(stderr, ## __VA_ARGS__); \
-    } while (0);
-#else
-    #define DB_PRINT(...)
+#ifndef XILINX_SPIPS_ERR_DEBUG
+#define XILINX_SPIPS_ERR_DEBUG 0
 #endif
 
+#define DB_PRINT_L(level, ...) do { \
+    if (XILINX_SPIPS_ERR_DEBUG > (level)) { \
+        fprintf(stderr,  ": %s: ", __func__); \
+        fprintf(stderr, ## __VA_ARGS__); \
+    } \
+} while (0);
+
 /* config register */
 #define R_CONFIG            (0x00 / 4)
 #define IFMODE              (1 << 31)
@@ -210,10 +212,10 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
                                 (s->num_cs * s->num_busses);
 
             if (xilinx_spips_cs_is_set(s, i, field) && !found) {
-                DB_PRINT("selecting slave %d\n", i);
+                DB_PRINT_L(0, "selecting slave %d\n", i);
                 qemu_set_irq(s->cs_lines[cs_to_set], 0);
             } else {
-                DB_PRINT("deselecting slave %d\n", i);
+                DB_PRINT_L(0, "deselecting slave %d\n", i);
                 qemu_set_irq(s->cs_lines[cs_to_set], 1);
             }
         }
@@ -223,7 +225,7 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
     }
     if (!found) {
         s->snoop_state = SNOOP_CHECKING;
-        DB_PRINT("moving to snoop check state\n");
+        DB_PRINT_L(1, "moving to snoop check state\n");
     }
 }
 
@@ -306,6 +308,8 @@ static inline void stripe8(uint8_t *x, int num, bool dir)
 
 static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 {
+    int debug_level = 0;
+
     for (;;) {
         int i;
         uint8_t tx = 0;
@@ -330,14 +334,14 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
         }
 
         for (i = 0; i < num_effective_busses(s); ++i) {
-            DB_PRINT("tx = %02x\n", tx_rx[i]);
+            DB_PRINT_L(debug_level, "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]);
+            DB_PRINT_L(debug_level, "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");
+            DB_PRINT_L(0, "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) {
@@ -347,7 +351,8 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
            fifo8_push(&s->rx_fifo, (uint8_t)tx_rx[0]);
         }
 
-        DB_PRINT("initial snoop state: %x\n", (unsigned)s->snoop_state);
+        DB_PRINT_L(debug_level, "initial snoop state: %x\n",
+                   (unsigned)s->snoop_state);
         switch (s->snoop_state) {
         case (SNOOP_CHECKING):
             switch (tx) { /* new instruction code */
@@ -372,11 +377,17 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
             break;
         case (SNOOP_STRIPING):
         case (SNOOP_NONE):
+            /* Once we hit the boring stuff - squelch debug noise */
+            if (!debug_level) {
+                DB_PRINT_L(0, "squelching debug info ....\n");
+                debug_level = 1;
+            }
             break;
         default:
             s->snoop_state--;
         }
-        DB_PRINT("final snoop state: %x\n", (unsigned)s->snoop_state);
+        DB_PRINT_L(debug_level, "final snoop state: %x\n",
+                   (unsigned)s->snoop_state);
     }
 }
 
@@ -406,7 +417,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
     case R_INTR_STATUS:
         ret = s->regs[addr] & IXR_ALL;
         s->regs[addr] = 0;
-        DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
+        DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
         return ret;
     case R_INTR_MASK:
         mask = IXR_ALL;
@@ -427,11 +438,12 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
         break;
     case R_RX_DATA:
         rx_data_bytes(s, &ret, s->num_txrx_bytes);
-        DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
+        DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
         xilinx_spips_update_ixr(s);
         return ret;
     }
-    DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr * 4, s->regs[addr] & mask);
+    DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4,
+               s->regs[addr] & mask);
     return s->regs[addr] & mask;
 
 }
@@ -457,7 +469,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
     int man_start_com = 0;
     XilinxSPIPS *s = opaque;
 
-    DB_PRINT("addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
+    DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
     addr >>= 2;
     switch (addr) {
     case R_CONFIG:
@@ -551,7 +563,8 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
     if (addr >= q->lqspi_cached_addr &&
             addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
         ret = q->lqspi_buf[(addr - q->lqspi_cached_addr) >> 2];
-        DB_PRINT("addr: %08x, data: %08x\n", (unsigned)addr, (unsigned)ret);
+        DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
+                   (unsigned)ret);
         return ret;
     } else {
         int flash_addr = (addr / num_effective_busses(s));
@@ -562,17 +575,18 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
         s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
         s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
 
-        DB_PRINT("config reg status: %08x\n", s->regs[R_LQSPI_CFG]);
+        DB_PRINT_L(0, "config reg status: %08x\n", s->regs[R_LQSPI_CFG]);
 
         fifo8_reset(&s->tx_fifo);
         fifo8_reset(&s->rx_fifo);
 
         /* instruction */
-        DB_PRINT("pushing read instruction: %02x\n",
-                 (uint8_t)(s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE));
+        DB_PRINT_L(0, "pushing read instruction: %02x\n",
+                   (unsigned)(uint8_t)(s->regs[R_LQSPI_CFG] &
+                                       LQSPI_CFG_INST_CODE));
         fifo8_push(&s->tx_fifo, s->regs[R_LQSPI_CFG] & LQSPI_CFG_INST_CODE);
         /* read address */
-        DB_PRINT("pushing read address %06x\n", flash_addr);
+        DB_PRINT_L(0, "pushing read address %06x\n", flash_addr);
         fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 16));
         fifo8_push(&s->tx_fifo, (uint8_t)(flash_addr >> 8));
         fifo8_push(&s->tx_fifo, (uint8_t)flash_addr);
@@ -585,14 +599,14 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
         /* dummy bytes */
         for (i = 0; i < (extract32(s->regs[R_LQSPI_CFG], LQSPI_CFG_DUMMY_SHIFT,
                                    LQSPI_CFG_DUMMY_WIDTH)); ++i) {
-            DB_PRINT("pushing dummy byte\n");
+            DB_PRINT_L(0, "pushing dummy byte\n");
             fifo8_push(&s->tx_fifo, 0);
         }
         xilinx_spips_update_cs_lines(s);
         xilinx_spips_flush_txfifo(s);
         fifo8_reset(&s->rx_fifo);
 
-        DB_PRINT("starting QSPI data read\n");
+        DB_PRINT_L(0, "starting QSPI data read\n");
 
         for (i = 0; i < LQSPI_CACHE_SIZE / 4; ++i) {
             tx_data_bytes(s, 0, 4);
@@ -626,7 +640,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
     XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
     int i;
 
-    DB_PRINT("realized spips\n");
+    DB_PRINT_L(0, "realized spips\n");
 
     s->spi = g_new(SSIBus *, s->num_busses);
     for (i = 0; i < s->num_busses; ++i) {
@@ -658,7 +672,7 @@ static void xilinx_qspips_realize(DeviceState *dev, Error **errp)
     XilinxQSPIPS *q = XILINX_QSPIPS(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
-    DB_PRINT("realized qspips\n");
+    DB_PRINT_L(0, "realized qspips\n");
 
     s->num_busses = 2;
     s->num_cs = 2;
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 14/15] xilinx_spips: lqspi: Push more data to tx-fifo
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (12 preceding siblings ...)
  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 ` 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
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:38 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

Do 16 words per fifo flush. Increases performance and decreases
debug verbosity. This data depth has no real hardware analogue,
so just go with something that has reasonable performance.

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>
---

 hw/ssi/xilinx_spips.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 665f471..e975a87 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -608,11 +608,14 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 
         DB_PRINT_L(0, "starting QSPI data read\n");
 
-        for (i = 0; i < LQSPI_CACHE_SIZE / 4; ++i) {
-            tx_data_bytes(s, 0, 4);
+        while (cache_entry < LQSPI_CACHE_SIZE / 4) {
+            for (i = 0; i < 16; ++i) {
+                tx_data_bytes(s, 0, 4);
+            }
             xilinx_spips_flush_txfifo(s);
-            rx_data_bytes(s, &q->lqspi_buf[cache_entry], 4);
-            cache_entry++;
+            for (i = 0; i < 16; ++i) {
+                rx_data_bytes(s, &q->lqspi_buf[cache_entry++], 4);
+            }
         }
 
         s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH arm-devs v4 15/15] xilinx_spips: lqspi: Fix byte/misaligned access
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (13 preceding siblings ...)
  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 ` peter.crosthwaite
  2013-05-24 12:57 ` [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 Peter Maydell
  15 siblings, 0 replies; 17+ messages in thread
From: peter.crosthwaite @ 2013-05-21  6:39 UTC (permalink / raw)
  To: peter.maydell, qemu-devel; +Cc: edgar.iglesias

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

The LQSPI bus attachment supports byte/halfword and misaligned
accesses. Fixed. Refactored the LQSPI cache to be byte-wise
instead of word wise accordingly.

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>
---

 hw/ssi/xilinx_spips.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index e975a87..05a3ada 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -161,7 +161,7 @@ typedef struct {
 typedef struct {
     XilinxSPIPS parent_obj;
 
-    uint32_t lqspi_buf[LQSPI_CACHE_SIZE];
+    uint8_t lqspi_buf[LQSPI_CACHE_SIZE];
     hwaddr lqspi_cached_addr;
 } XilinxQSPIPS;
 
@@ -391,14 +391,12 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
     }
 }
 
-static inline void rx_data_bytes(XilinxSPIPS *s, uint32_t *value, int max)
+static inline void rx_data_bytes(XilinxSPIPS *s, uint8_t *value, int max)
 {
     int i;
 
-    *value = 0;
     for (i = 0; i < max && !fifo8_is_empty(&s->rx_fifo); ++i) {
-        uint32_t next = fifo8_pop(&s->rx_fifo) & 0xFF;
-        *value |= next << 8 * (s->regs[R_CONFIG] & ENDIAN ? 3-i : i);
+        value[i] = fifo8_pop(&s->rx_fifo);
     }
 }
 
@@ -408,6 +406,7 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
     XilinxSPIPS *s = opaque;
     uint32_t mask = ~0;
     uint32_t ret;
+    uint8_t rx_buf[4];
 
     addr >>= 2;
     switch (addr) {
@@ -437,7 +436,10 @@ static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
         mask = 0;
         break;
     case R_RX_DATA:
-        rx_data_bytes(s, &ret, s->num_txrx_bytes);
+        memset(rx_buf, 0, sizeof(rx_buf));
+        rx_data_bytes(s, rx_buf, s->num_txrx_bytes);
+        ret = s->regs[R_CONFIG] & ENDIAN ? cpu_to_be32(*(uint32_t *)rx_buf)
+                        : cpu_to_le32(*(uint32_t *)rx_buf);
         DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr * 4, ret);
         xilinx_spips_update_ixr(s);
         return ret;
@@ -562,7 +564,8 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 
     if (addr >= q->lqspi_cached_addr &&
             addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
-        ret = q->lqspi_buf[(addr - q->lqspi_cached_addr) >> 2];
+        uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
+        ret = cpu_to_le32(*(uint32_t *)retp);
         DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
                    (unsigned)ret);
         return ret;
@@ -608,13 +611,13 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
 
         DB_PRINT_L(0, "starting QSPI data read\n");
 
-        while (cache_entry < LQSPI_CACHE_SIZE / 4) {
-            for (i = 0; i < 16; ++i) {
-                tx_data_bytes(s, 0, 4);
+        while (cache_entry < LQSPI_CACHE_SIZE) {
+            for (i = 0; i < 64; ++i) {
+                tx_data_bytes(s, 0, 1);
             }
             xilinx_spips_flush_txfifo(s);
-            for (i = 0; i < 16; ++i) {
-                rx_data_bytes(s, &q->lqspi_buf[cache_entry++], 4);
+            for (i = 0; i < 64; ++i) {
+                rx_data_bytes(s, &q->lqspi_buf[cache_entry++], 1);
             }
         }
 
@@ -622,7 +625,7 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
         s->regs[R_LQSPI_STS] |= u_page_save;
         xilinx_spips_update_cs_lines(s);
 
-        q->lqspi_cached_addr = addr;
+        q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
         return lqspi_read(opaque, addr, size);
     }
 }
@@ -631,7 +634,7 @@ static const MemoryRegionOps lqspi_ops = {
     .read = lqspi_read,
     .endianness = DEVICE_NATIVE_ENDIAN,
     .valid = {
-        .min_access_size = 4,
+        .min_access_size = 1,
         .max_access_size = 4
     }
 };
-- 
1.8.3.rc1.44.gb387c77.dirty

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2
  2013-05-21  6:28 [Qemu-devel] [PATCH arm-devs v4 00/15] Xilinx SPIPS fixes round 2 peter.crosthwaite
                   ` (14 preceding siblings ...)
  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 ` Peter Maydell
  15 siblings, 0 replies; 17+ messages in thread
From: Peter Maydell @ 2013-05-24 12:57 UTC (permalink / raw)
  To: peter.crosthwaite; +Cc: edgar.iglesias, qemu-devel

On 21 May 2013 07:28,  <peter.crosthwaite@xilinx.com> wrote:
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>
> Updates to the Zynq SPI controller. Some QOMifying cleanup, followed by
> a number of bugs/incompletnesses found by some (very) rigourous test
> vectors.

Thanks; applied all to arm-devs.next.

-- PMM

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2013-05-24 12:58 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [Qemu-devel] [PATCH arm-devs v4 11/15] xilinx_spips: Fix striping behaviour peter.crosthwaite
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

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.