Patchwork [for-1.5,v2,06/15] xilinx_spips: Trash LQ page cache on mode change

login
register
mail settings
Submitter Peter Crosthwaite
Date April 19, 2013, 2:06 a.m.
Message ID <0890ab958dbecc05faeae7bcdb4a5051f0625875.1366335998.git.peter.crosthwaite@xilinx.com>
Download mbox | patch
Permalink /patch/237807/
State New
Headers show

Comments

Peter Crosthwaite - April 19, 2013, 2:06 a.m.
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>
---
changed from v1:
Re-implemented using separate SPI/QSPI write handlers.

 hw/ssi/xilinx_spips.c |   26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)
Peter Maydell - April 19, 2013, 10:23 a.m.
On 19 April 2013 03:06,  <peter.crosthwaite@xilinx.com> wrote:
> 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>
> ---
> changed from v1:
> Re-implemented using separate SPI/QSPI write handlers.
>
>  hw/ssi/xilinx_spips.c |   26 +++++++++++++++++++++++++-
>  1 files changed, 25 insertions(+), 1 deletions(-)
>
> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
> index e351cb2..6d38111 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;
> @@ -446,6 +448,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
>      case R_TXD3:
>          tx_data_bytes(s, (uint32_t)value, 3);
>          goto no_reg_update;
> +        break;

Why insert code after a goto?

>      }
>      s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
>  no_reg_update:

-- PMM
Peter Crosthwaite - April 22, 2013, 4:48 a.m.
On Fri, Apr 19, 2013 at 8:23 PM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 19 April 2013 03:06,  <peter.crosthwaite@xilinx.com> wrote:
>> 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>
>> ---
>> changed from v1:
>> Re-implemented using separate SPI/QSPI write handlers.
>>
>>  hw/ssi/xilinx_spips.c |   26 +++++++++++++++++++++++++-
>>  1 files changed, 25 insertions(+), 1 deletions(-)
>>
>> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
>> index e351cb2..6d38111 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;
>> @@ -446,6 +448,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
>>      case R_TXD3:
>>          tx_data_bytes(s, (uint32_t)value, 3);
>>          goto no_reg_update;
>> +        break;
>
> Why insert code after a goto?
>

Removed.

Thanks,
Peter

>>      }
>>      s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
>>  no_reg_update:
>
> -- PMM
>

Patch

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index e351cb2..6d38111 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;
@@ -446,6 +448,7 @@  static void xilinx_spips_write(void *opaque, hwaddr addr,
     case R_TXD3:
         tx_data_bytes(s, (uint32_t)value, 3);
         goto no_reg_update;
+        break;
     }
     s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
 no_reg_update:
@@ -462,6 +465,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 +587,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 +651,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 +666,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;
 }