qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/9] hw/block: m25p80: Fix the number of dummy bytes needed for W


From: Bin Meng
Subject: [PATCH 1/9] hw/block: m25p80: Fix the number of dummy bytes needed for Windbond flashes
Date: Thu, 14 Jan 2021 23:08:54 +0800

From: Bin Meng <bin.meng@windriver.com>

The m25p80 model uses s->needed_bytes to indicate how many follow-up
bytes are expected to be received after it receives a command. For
example, depending on the address mode, either 3-byte address or
4-byte address is needed.

For fast read family commands, some dummy cycles are required after
sending the address bytes, and the dummy cycles need to be counted
in s->needed_bytes. This is where the mess began.

As the variable name (needed_bytes) indicates, the unit is in byte.
It is not in bit, or cycle. However for some reason the model has
been using the number of dummy cycles for s->needed_bytes. The right
approach is to convert the number of dummy cycles to bytes based on
the SPI protocol, for example, 6 dummy cycles for the Fast Read Quad
I/O (EBh) should be converted to 3 bytes per the formula (6 * 4 / 8).

Things get complicated when interacting with different SPI or QSPI
flash controllers. There are major two cases:

- Dummy bytes prepared by drivers, and wrote to the controller fifo.
  For such case, driver will calculate the correct number of dummy
  bytes and write them into the tx fifo. Fixing the m25p80 model will
  fix flashes working with such controllers.
- Dummy bytes not prepared by drivers. Drivers just tell the hardware
  the dummy cycle configuration via some registers, and hardware will
  automatically generate dummy cycles for us. Fixing the m25p80 model
  is not enough, and we will need to fix the SPI/QSPI models for such
  controllers.

Let's fix the mess from the flash side first. We start from a easy one,
the Winbond flashes.

Per the Windbond W25Q256JV datasheet [1] instrunction set table
(chapter 8.1.2, 8.1.3, 8.1.4, 8.1.5), fix the wrong number of
dummy bytes needed for fast read commands.

[1] https://www.winbond.com/resource-files/w25q256jv%20spi%20revb%2009202016.pdf

Fixes: fe8477052831 ("m25p80: Fix QIOR/DIOR handling for Winbond")
Fixes: 3830c7a460b8 ("m25p80: Fix WINBOND fast read command handling")
Fixes: cf6f1efe0b57 ("m25p80: Fast read commands family changes")
Signed-off-by: Bin Meng <bin.meng@windriver.com>
---

 hw/block/m25p80.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index b744a58d1c..c947716f99 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -875,9 +875,22 @@ static void decode_fast_read_cmd(Flash *s)
 {
     s->needed_bytes = get_addr_length(s);
     switch (get_man(s)) {
-    /* Dummy cycles - modeled with bytes writes instead of bits */
+    /* Dummy cycles - modeled with bytes writes */
     case MAN_WINBOND:
-        s->needed_bytes += 8;
+        switch (s->cmd_in_progress) {
+        case FAST_READ:
+        case FAST_READ4:
+            s->needed_bytes += 1;
+            break;
+        case DOR:
+        case DOR4:
+            s->needed_bytes += 2;
+            break;
+        case QOR:
+        case QOR4:
+            s->needed_bytes += 4;
+            break;
+        }
         break;
     case MAN_NUMONYX:
         s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
@@ -906,7 +919,7 @@ static void decode_fast_read_cmd(Flash *s)
 static void decode_dio_read_cmd(Flash *s)
 {
     s->needed_bytes = get_addr_length(s);
-    /* Dummy cycles modeled with bytes writes instead of bits */
+    /* Dummy cycles modeled with bytes writes */
     switch (get_man(s)) {
     case MAN_WINBOND:
         s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
@@ -945,11 +958,10 @@ static void decode_dio_read_cmd(Flash *s)
 static void decode_qio_read_cmd(Flash *s)
 {
     s->needed_bytes = get_addr_length(s);
-    /* Dummy cycles modeled with bytes writes instead of bits */
+    /* Dummy cycles modeled with bytes writes */
     switch (get_man(s)) {
     case MAN_WINBOND:
-        s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
-        s->needed_bytes += 4;
+        s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN + 2;
         break;
     case MAN_SPANSION:
         s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]