Patchwork [for-1.5,v2,08/15] xilinx_spips: Implement automatic CS

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

Comments

Peter Crosthwaite - April 19, 2013, 2:08 a.m.
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>
---
changed from v1:
Refresh CS on entry and exit from flush routine as needed.

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

Patch

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 2eb6a2f..7699562 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_L(0, "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;
         }
     }
@@ -452,12 +459,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 = {
@@ -511,7 +519,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 */
@@ -535,6 +543,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);
 
@@ -546,6 +555,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);