All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v1 0/3] Introduce ssi_txfifo_transfer
@ 2021-01-19 13:01 Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 1/3] hw: ssi: " Francisco Iglesias
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Francisco Iglesias @ 2021-01-19 13:01 UTC (permalink / raw)
  To: qemu-devel, frasse.iglesias
  Cc: kwolf, peter.maydell, alistair, bin.meng, mreitz, alistair23

Dear all,

This small RFC patch series attempts to make it possible to support the
SPI commands requiring dummy clock cycles in the SPI controllers that
currently do not support them.

There are two ways SPI controllers transfer dummy clock cycles. In one way
the dummy clock cycles to be used with a command are configured into a
register and the second way the dummy clock cycles are generated from
dummy bytes pushed into a txfifo. Since these two ways work differently
this patch series introduces ssi_txfifo_transfer to be used by the
controllers that makes use of a txfifo. Furthermore, since the QEMU SPI
controllers models transfering through a txfifo require that the SPI flash
(m25p80) operates with dummy byte accuracy (instead of dummy clock cycle),
m25p80 is made to support toggling accuracy between dummy clock cycle into
dummy byte in this patch series. This is done automatically inside
ssi_txfifo_transfer.

Lastly, one SPI controller transfering through a txfifo is modified to use
the new function and has been tested to work with the FAST_READ command
(using 8 dummy clock cycles). For testing the first way of
transferring dummy clock cycles (when they are configured into a register)
the Xilinx ZynqMP GQSPI has been used and all works equally well as previously
with the controller.

Best regards,
Francisco Iglesias


Francisco Iglesias (3):
  hw: ssi: Introduce ssi_txfifo_transfer
  hw: block: m25p80: Support dummy byte accuracy
  hw: ssi: xilinx_spi: Change to use ssi_txfifo_transfer

 hw/block/m25p80.c    | 112 +++++++++++++++++++++++++++++++++++--------
 hw/ssi/ssi.c         |  22 +++++++++
 hw/ssi/xilinx_spi.c  |   2 +-
 include/hw/ssi/ssi.h |   3 ++
 4 files changed, 118 insertions(+), 21 deletions(-)

-- 
2.20.1



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

* [RFC PATCH v1 1/3] hw: ssi: Introduce ssi_txfifo_transfer
  2021-01-19 13:01 [RFC PATCH v1 0/3] Introduce ssi_txfifo_transfer Francisco Iglesias
@ 2021-01-19 13:01 ` Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 2/3] hw: block: m25p80: Support dummy byte accuracy Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 3/3] hw: ssi: xilinx_spi: Change to use ssi_txfifo_transfer Francisco Iglesias
  2 siblings, 0 replies; 4+ messages in thread
From: Francisco Iglesias @ 2021-01-19 13:01 UTC (permalink / raw)
  To: qemu-devel, frasse.iglesias
  Cc: kwolf, peter.maydell, alistair, bin.meng, mreitz, alistair23

This patch introduces ssi_txfifo_transfer aimed to be used by SPI
controllers transfering through a txfifo. When interacting with a SPI
flash (m25p80), ssi_txfifo_transfer will toggle the accuracy from dummy
clock cycles to dummy bytes and by doing this above mentioned SPI
controllers will obtain support for the commands requiring those.

Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
---
 hw/ssi/ssi.c         | 22 ++++++++++++++++++++++
 include/hw/ssi/ssi.h |  3 +++
 2 files changed, 25 insertions(+)

diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c
index e5d7ce9523..b87628ea0c 100644
--- a/hw/ssi/ssi.c
+++ b/hw/ssi/ssi.c
@@ -127,6 +127,28 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
     return r;
 }
 
+uint32_t ssi_txfifo_transfer(SSIBus *bus, uint32_t val)
+{
+    BusState *b = BUS(bus);
+    BusChild *kid;
+    SSIPeripheralClass *ssc;
+    uint32_t r = 0;
+
+    QTAILQ_FOREACH(kid, &b->children, sibling) {
+        SSIPeripheral *peripheral = SSI_PERIPHERAL(kid->child);
+        ssc = SSI_PERIPHERAL_GET_CLASS(peripheral);
+        if (ssc->set_dummy_byte_accuracy) {
+            ssc->set_dummy_byte_accuracy(peripheral, true);
+        }
+        r |= ssc->transfer_raw(peripheral, val);
+        if (ssc->set_dummy_byte_accuracy) {
+            ssc->set_dummy_byte_accuracy(peripheral, false);
+        }
+    }
+
+    return r;
+}
+
 const VMStateDescription vmstate_ssi_peripheral = {
     .name = "SSISlave",
     .version_id = 1,
diff --git a/include/hw/ssi/ssi.h b/include/hw/ssi/ssi.h
index f411858ab0..39bf00ec96 100644
--- a/include/hw/ssi/ssi.h
+++ b/include/hw/ssi/ssi.h
@@ -54,6 +54,8 @@ struct SSIPeripheralClass {
      * always be called for the device for every txrx access to the parent bus
      */
     uint32_t (*transfer_raw)(SSIPeripheral *dev, uint32_t val);
+
+    void (*set_dummy_byte_accuracy)(SSIPeripheral *dev, bool val);
 };
 
 struct SSIPeripheral {
@@ -105,5 +107,6 @@ bool ssi_realize_and_unref(DeviceState *dev, SSIBus *bus, Error **errp);
 SSIBus *ssi_create_bus(DeviceState *parent, const char *name);
 
 uint32_t ssi_transfer(SSIBus *bus, uint32_t val);
+uint32_t ssi_txfifo_transfer(SSIBus *bus, uint32_t val);
 
 #endif
-- 
2.20.1



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

* [RFC PATCH v1 2/3] hw: block: m25p80: Support dummy byte accuracy
  2021-01-19 13:01 [RFC PATCH v1 0/3] Introduce ssi_txfifo_transfer Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 1/3] hw: ssi: " Francisco Iglesias
@ 2021-01-19 13:01 ` Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 3/3] hw: ssi: xilinx_spi: Change to use ssi_txfifo_transfer Francisco Iglesias
  2 siblings, 0 replies; 4+ messages in thread
From: Francisco Iglesias @ 2021-01-19 13:01 UTC (permalink / raw)
  To: qemu-devel, frasse.iglesias
  Cc: kwolf, peter.maydell, alistair, bin.meng, mreitz, alistair23

This patch adds support to toggle the accuracy in m25p80 between dummy
clock cycle to dummy byte. By being able to do this the SPI controllers
transfering through a txfifo will be able to support commands with dummy
clock cycles.

Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
---
 hw/block/m25p80.c | 112 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 92 insertions(+), 20 deletions(-)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 1b3f2405a1..c9342e1842 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -462,6 +462,7 @@ struct Flash {
 
     const FlashPartInfo *pi;
 
+    bool dummy_byte_accuracy;
 };
 
 struct M25P80Class {
@@ -862,26 +863,59 @@ static uint8_t numonyx_extract_cfg_num_dummies(Flash *s)
     return num_dummies;
 }
 
+static uint8_t to_dummy_bytes(Flash *s, uint8_t dummy_clk_cycles)
+{
+    uint8_t lines = 1;
+
+    switch (s->cmd_in_progress) {
+    case DOR:
+    case DOR4:
+    case DIOR:
+    case DIOR4:
+        lines = 2;
+        break;
+    case QOR:
+    case QOR4:
+    case QIOR:
+    case QIOR4:
+        lines = 4;
+        break;
+    default:
+        break;
+    }
+
+    if ((dummy_clk_cycles * lines) % 8) {
+        qemu_log_mask(LOG_UNIMP, "M25P80: Non multiple of 8 number of dummy"
+                     " clock cycles while operating with dummy byte"
+                     " accuracy\n");
+    }
+
+    return (dummy_clk_cycles * lines) / 8;
+}
+
 static void decode_fast_read_cmd(Flash *s)
 {
+    uint8_t dummy_clk_cycles = 0;
+    uint8_t extra_bytes;
+
     s->needed_bytes = get_addr_length(s);
     switch (get_man(s)) {
     /* Dummy cycles - modeled with bytes writes instead of bits */
     case MAN_WINBOND:
-        s->needed_bytes += 8;
+        dummy_clk_cycles = 8;
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+        dummy_clk_cycles = numonyx_extract_cfg_num_dummies(s);
         break;
     case MAN_MACRONIX:
         if (extract32(s->volatile_cfg, 6, 2) == 1) {
-            s->needed_bytes += 6;
+            dummy_clk_cycles = 6;
         } else {
-            s->needed_bytes += 8;
+            dummy_clk_cycles = 8;
         }
         break;
     case MAN_SPANSION:
-        s->needed_bytes += extract32(s->spansion_cr2v,
+        dummy_clk_cycles = extract32(s->spansion_cr2v,
                                     SPANSION_DUMMY_CLK_POS,
                                     SPANSION_DUMMY_CLK_LEN
                                     );
@@ -889,6 +923,14 @@ static void decode_fast_read_cmd(Flash *s)
     default:
         break;
     }
+
+    if (s->dummy_byte_accuracy) {
+        extra_bytes = to_dummy_bytes(s, dummy_clk_cycles);
+    } else {
+        extra_bytes = dummy_clk_cycles;
+    }
+
+    s->needed_bytes += extra_bytes;
     s->pos = 0;
     s->len = 0;
     s->state = STATE_COLLECTING_DATA;
@@ -896,38 +938,49 @@ static void decode_fast_read_cmd(Flash *s)
 
 static void decode_dio_read_cmd(Flash *s)
 {
+    uint8_t dummy_clk_cycles = 0;
+    uint8_t extra_bytes;
+
     s->needed_bytes = get_addr_length(s);
     /* Dummy cycles modeled with bytes writes instead of bits */
     switch (get_man(s)) {
     case MAN_WINBOND:
-        s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
+        dummy_clk_cycles = WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
         break;
     case MAN_SPANSION:
-        s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
-        s->needed_bytes += extract32(s->spansion_cr2v,
+        dummy_clk_cycles = SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
+        dummy_clk_cycles = extract32(s->spansion_cr2v,
                                     SPANSION_DUMMY_CLK_POS,
                                     SPANSION_DUMMY_CLK_LEN
                                     );
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+        dummy_clk_cycles = numonyx_extract_cfg_num_dummies(s);
         break;
     case MAN_MACRONIX:
         switch (extract32(s->volatile_cfg, 6, 2)) {
         case 1:
-            s->needed_bytes += 6;
+            dummy_clk_cycles = 6;
             break;
         case 2:
-            s->needed_bytes += 8;
+            dummy_clk_cycles = 8;
             break;
         default:
-            s->needed_bytes += 4;
+            dummy_clk_cycles = 4;
             break;
         }
         break;
     default:
         break;
     }
+
+    if (s->dummy_byte_accuracy) {
+        extra_bytes = to_dummy_bytes(s, dummy_clk_cycles);
+    } else {
+        extra_bytes = dummy_clk_cycles;
+    }
+
+    s->needed_bytes += extra_bytes;
     s->pos = 0;
     s->len = 0;
     s->state = STATE_COLLECTING_DATA;
@@ -935,39 +988,50 @@ static void decode_dio_read_cmd(Flash *s)
 
 static void decode_qio_read_cmd(Flash *s)
 {
+    uint8_t dummy_clk_cycles = 0;
+    uint8_t extra_bytes;
+
     s->needed_bytes = get_addr_length(s);
     /* Dummy cycles modeled with bytes writes instead of bits */
     switch (get_man(s)) {
     case MAN_WINBOND:
-        s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
-        s->needed_bytes += 4;
+        dummy_clk_cycles = WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
+        dummy_clk_cycles += 4;
         break;
     case MAN_SPANSION:
-        s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
-        s->needed_bytes += extract32(s->spansion_cr2v,
+        dummy_clk_cycles = SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
+        dummy_clk_cycles += extract32(s->spansion_cr2v,
                                     SPANSION_DUMMY_CLK_POS,
                                     SPANSION_DUMMY_CLK_LEN
                                     );
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+        dummy_clk_cycles = numonyx_extract_cfg_num_dummies(s);
         break;
     case MAN_MACRONIX:
         switch (extract32(s->volatile_cfg, 6, 2)) {
         case 1:
-            s->needed_bytes += 4;
+            dummy_clk_cycles = 4;
             break;
         case 2:
-            s->needed_bytes += 8;
+            dummy_clk_cycles = 8;
             break;
         default:
-            s->needed_bytes += 6;
+            dummy_clk_cycles = 6;
             break;
         }
         break;
     default:
         break;
     }
+
+    if (s->dummy_byte_accuracy) {
+        extra_bytes = to_dummy_bytes(s, dummy_clk_cycles);
+    } else {
+        extra_bytes = dummy_clk_cycles;
+    }
+
+    s->needed_bytes += extra_bytes;
     s->pos = 0;
     s->len = 0;
     s->state = STATE_COLLECTING_DATA;
@@ -1291,6 +1355,13 @@ static int m25p80_cs(SSIPeripheral *ss, bool select)
     return 0;
 }
 
+static void m25p80_dummy_byte_accuracy(SSIPeripheral *ss, bool val)
+{
+    Flash *s = M25P80(ss);
+
+    s->dummy_byte_accuracy = val;
+}
+
 static uint32_t m25p80_transfer8(SSIPeripheral *ss, uint32_t tx)
 {
     Flash *s = M25P80(ss);
@@ -1494,6 +1565,7 @@ static void m25p80_class_init(ObjectClass *klass, void *data)
     k->transfer = m25p80_transfer8;
     k->set_cs = m25p80_cs;
     k->cs_polarity = SSI_CS_LOW;
+    k->set_dummy_byte_accuracy = m25p80_dummy_byte_accuracy;
     dc->vmsd = &vmstate_m25p80;
     device_class_set_props(dc, m25p80_properties);
     dc->reset = m25p80_reset;
-- 
2.20.1



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

* [RFC PATCH v1 3/3] hw: ssi: xilinx_spi: Change to use ssi_txfifo_transfer
  2021-01-19 13:01 [RFC PATCH v1 0/3] Introduce ssi_txfifo_transfer Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 1/3] hw: ssi: " Francisco Iglesias
  2021-01-19 13:01 ` [RFC PATCH v1 2/3] hw: block: m25p80: Support dummy byte accuracy Francisco Iglesias
@ 2021-01-19 13:01 ` Francisco Iglesias
  2 siblings, 0 replies; 4+ messages in thread
From: Francisco Iglesias @ 2021-01-19 13:01 UTC (permalink / raw)
  To: qemu-devel, frasse.iglesias
  Cc: kwolf, peter.maydell, alistair, bin.meng, mreitz, alistair23

This patch changes the SPI controller to use the ssi_txfifo_transfer for
being able to support SPI flash commands requiring dummy clock cycles.

Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
---
 hw/ssi/xilinx_spi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
index 49ff275593..ae34cdc436 100644
--- a/hw/ssi/xilinx_spi.c
+++ b/hw/ssi/xilinx_spi.c
@@ -179,7 +179,7 @@ static void spi_flush_txfifo(XilinxSPI *s)
     while (!fifo8_is_empty(&s->tx_fifo)) {
         tx = (uint32_t)fifo8_pop(&s->tx_fifo);
         DB_PRINT("data tx:%x\n", tx);
-        rx = ssi_transfer(s->spi, tx);
+        rx = ssi_txfifo_transfer(s->spi, tx);
         DB_PRINT("data rx:%x\n", rx);
         if (fifo8_is_full(&s->rx_fifo)) {
             s->regs[R_IPISR] |= IRQ_DRR_OVERRUN;
-- 
2.20.1



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

end of thread, other threads:[~2021-01-19 13:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-19 13:01 [RFC PATCH v1 0/3] Introduce ssi_txfifo_transfer Francisco Iglesias
2021-01-19 13:01 ` [RFC PATCH v1 1/3] hw: ssi: " Francisco Iglesias
2021-01-19 13:01 ` [RFC PATCH v1 2/3] hw: block: m25p80: Support dummy byte accuracy Francisco Iglesias
2021-01-19 13:01 ` [RFC PATCH v1 3/3] hw: ssi: xilinx_spi: Change to use ssi_txfifo_transfer Francisco Iglesias

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.