Numonyx/Micron flashes do not use one fixed dummy-phase width for all
fast-read commands. The volatile configuration register stores a number
of dummy clock cycles, and QEMU must convert that value to the number of
SSI bytes consumed by the flash model.

Keep the existing default: 10 dummy clocks in Quad I/O mode and 8 dummy
clocks otherwise. In Quad I/O and Dual I/O protocol modes, all command
phases are transferred on 4 or 2 lines, so the dummy clock count still
needs to be scaled by that bus width.

Standard SPI, also called extended SPI in the Micron datasheet, is more
subtle. Quad Output Fast Read (6Bh) and Dual Output Fast Read (3Bh) keep
the opcode and address phases on DQ0; their dummy phase is just a clock
gap before data is returned on four or two output lines. Do not scale the
dummy count for those output-only commands. Only Quad I/O Fast Read
(EBh) and Dual I/O Fast Read (BBh) transfer the address and dummy phases
on the 4-bit or 2-bit bus, so keep scaling those commands.

[1] https://media-www.micron.com/-/media/client/global/documents/products/
    data-sheet/nor-flash/serial-nor/n25q/n25q_512mb_1ce_3v_65nm.pdf

Fixes: 23af26856606 ("hw/block/m25p80: Fix Numonyx fast read dummy cycle count")
Signed-off-by: Bin Meng <[email protected]>
---

 hw/block/m25p80.c | 44 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 39 insertions(+), 5 deletions(-)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 59ecb32c0a..ba109cc055 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -980,19 +980,53 @@ static uint8_t numonyx_extract_cfg_num_dummies(Flash *s)
     mode = numonyx_mode(s);
     num_dummies = extract32(s->volatile_cfg, 4, 4);
 
+    /*
+     * The default nubmer of dummy cycles is only related to the SPI
+     * protocol mode. For QSPI it is 10, otherwise it is 8.
+     */
     if (num_dummies == 0x0 || num_dummies == 0xf) {
+        num_dummies = (mode == MODE_QIO) ? 10 : 8;
+    }
+
+    /*
+     * Convert the number of dummy cycles to bytes.
+     *
+     * In the Dual I/O and Quad I/O protocols, all command phases use 2 or 4
+     * lines. In standard/extended SPI mode the phase width depends on the
+     * command sequence: output-only fast reads keep the dummy clocks on the
+     * single address line, while input/output fast reads use the same 2-line
+     * or 4-line phase as the address.
+     */
+
+    if (mode == MODE_QIO) {
+        num_dummies *= 4;
+    } else if (mode == MODE_DIO) {
+        num_dummies *= 2;
+    } else {
         switch (s->cmd_in_progress) {
         case QIOR:
         case QIOR4:
-            num_dummies = 10;
+            num_dummies *= 4;
             break;
-        default:
-            num_dummies = (mode == MODE_QIO) ? 10 : 8;
+        case DIOR:
+        case DIOR4:
+            num_dummies *= 2;
             break;
-        }
+         }
+    }
+
+    /*
+     * If the total number of dummy bits is not multiple of 8, log an
+     * unimplemented message to notify user, and round it up.
+     */
+    if (num_dummies % 8) {
+        qemu_log_mask(LOG_UNIMP,
+                      "M25P80: the number of dummy bits is not multiple of 8");
+        num_dummies = ROUND_UP(num_dummies, 8);
     }
 
-    return num_dummies;
+    /* return the number of dummy bytes */
+    return num_dummies / 8;
 }
 
 static void decode_fast_read_cmd(Flash *s)
-- 
2.34.1


Reply via email to