All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bin Meng <bin.meng@processmission.com>
To: QEMU <qemu-devel@nongnu.org>
Cc: "Cédric Le Goater" <clg@redhat.com>,
	"Alistair Francis" <alistair@alistair23.me>,
	"Hanna Reitz" <hreitz@redhat.com>,
	"Kevin Wolf" <kwolf@redhat.com>,
	qemu-block@nongnu.org
Subject: [PATCH v2 02/10] hw/block: m25p80: Fix dummy byte handling for Numonyx/Micron flash
Date: Tue,  7 Jul 2026 16:34:21 +0800	[thread overview]
Message-ID: <20260707083431.219671-3-bin.meng@processmission.com> (raw)
In-Reply-To: <20260707083431.219671-1-bin.meng@processmission.com>

Numonyx/Micron flashes [1] 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://docs.rs-online.com/cad7/0900766b8121bd3c.pdf

Fixes: 23af26856606 ("hw/block/m25p80: Fix Numonyx fast read dummy cycle count")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Tested-by: Cédric Le Goater <clg@redhat.com>

---

Changes in v2:
- change numonyx_extract_cfg_num_dummies() to numonyx_extract_cfg_dummy_bytes()
  to avoid confusion
- use assert() when the dummy bit count is not byte-aligned

 hw/block/m25p80.c | 55 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 13 deletions(-)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 59ecb32c0a..83d1ce1f95 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -971,28 +971,57 @@ static uint8_t numonyx_mode(Flash *s)
     }
 }
 
-static uint8_t numonyx_extract_cfg_num_dummies(Flash *s)
+static uint8_t numonyx_extract_cfg_dummy_bytes(Flash *s)
 {
-    uint8_t num_dummies;
+    uint8_t dummy_bits;
     uint8_t mode;
-    assert(get_man(s) == MAN_NUMONYX);
 
     mode = numonyx_mode(s);
-    num_dummies = extract32(s->volatile_cfg, 4, 4);
+    dummy_bits = extract32(s->volatile_cfg, 4, 4);
 
-    if (num_dummies == 0x0 || num_dummies == 0xf) {
+    /*
+     * The default nubmer of dummy cycles is only related to the SPI
+     * protocol mode. For QSPI it is 10, otherwise it is 8.
+     */
+    if (dummy_bits == 0x0 || dummy_bits == 0xf) {
+        dummy_bits = (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) {
+        dummy_bits *= 4;
+    } else if (mode == MODE_DIO) {
+        dummy_bits *= 2;
+    } else {
         switch (s->cmd_in_progress) {
         case QIOR:
         case QIOR4:
-            num_dummies = 10;
+            dummy_bits *= 4;
             break;
-        default:
-            num_dummies = (mode == MODE_QIO) ? 10 : 8;
+        case DIOR:
+        case DIOR4:
+            dummy_bits *= 2;
             break;
-        }
+         }
     }
 
-    return num_dummies;
+    /*
+     * Assert that the dummy bit count is byte-aligned
+     * as SSI core can only consume whole dummy bytes.
+     */
+    assert(dummy_bits % 8 == 0);
+
+    /* return the number of dummy bytes */
+    return dummy_bits / 8;
 }
 
 static void decode_fast_read_cmd(Flash *s)
@@ -1007,7 +1036,7 @@ static void decode_fast_read_cmd(Flash *s)
         s->needed_bytes += 1;
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+        s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
         break;
     case MAN_MACRONIX:
         if (extract32(s->volatile_cfg, 6, 2) == 1) {
@@ -1059,7 +1088,7 @@ static void decode_dio_read_cmd(Flash *s)
                                     );
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+        s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
         break;
     case MAN_MACRONIX:
         switch (extract32(s->volatile_cfg, 6, 2)) {
@@ -1109,7 +1138,7 @@ static void decode_qio_read_cmd(Flash *s)
                                     );
         break;
     case MAN_NUMONYX:
-        s->needed_bytes += numonyx_extract_cfg_num_dummies(s);
+        s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
         break;
     case MAN_MACRONIX:
         switch (extract32(s->volatile_cfg, 6, 2)) {
-- 
2.53.0



  parent reply	other threads:[~2026-07-07  8:36 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  8:34 [PATCH v2 00/10] hw/{block, ssi}: Fix spi-nor flash dummy byte handling Bin Meng via
2026-07-07  8:34 ` Bin Meng via qemu development
2026-07-07  8:34 ` [PATCH v2 01/10] hw/block: m25p80: Fix dummy byte handling for Winbond flash Bin Meng
2026-07-07  8:34 ` Bin Meng [this message]
2026-07-07  8:34 ` [PATCH v2 03/10] hw/block: m25p80: Fix dummy byte handling for Macronix flash Bin Meng
2026-07-07  8:34 ` [PATCH v2 04/10] hw/block: m25p80: Fix dummy byte handling for Spansion flash Bin Meng
2026-07-07 12:34   ` Philippe Mathieu-Daudé
2026-07-07 12:51     ` Cédric Le Goater
2026-07-07 14:00       ` Philippe Mathieu-Daudé
2026-07-07 14:05       ` Cédric Le Goater
2026-07-07 14:26         ` Cédric Le Goater
2026-07-07 14:49           ` Bin Meng
2026-07-07 15:05           ` Philippe Mathieu-Daudé
2026-07-07  8:34 ` [PATCH v2 05/10] hw/ssi: npcm7xx_fiu: Correct the dummy cycle emulation logic Bin Meng
2026-07-07  8:34 ` [PATCH v2 06/10] hw/ssi: xilinx_spips: Fix dummy phase handling Bin Meng
2026-07-07  8:34 ` [PATCH v2 07/10] hw/ssi: aspeed_smc: Fix direct-read dummy bytes Bin Meng
2026-07-07  8:34 ` [PATCH v2 08/10] Revert "aspeed/smc: Fix number of dummy cycles for FAST_READ_4 command" Bin Meng
2026-07-07  8:34 ` [PATCH v2 09/10] Revert "aspeed/smc: snoop SPI transfers to fake dummy cycles" Bin Meng
2026-07-07  8:34 ` [PATCH v2 10/10] docs/devel: Document SSI dummy-cycle ownership Bin Meng
2026-07-07 13:10   ` Philippe Mathieu-Daudé
2026-07-07  9:11 ` [PATCH v2 00/10] hw/{block,ssi}: Fix spi-nor flash dummy byte handling Cédric Le Goater

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260707083431.219671-3-bin.meng@processmission.com \
    --to=bin.meng@processmission.com \
    --cc=alistair@alistair23.me \
    --cc=clg@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.