From 4957f668c4369f6b80e77b04e604747ca6014c9a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 7 Jul 2026 16:34:23 +0800 Subject: [PATCH] hw/block: m25p80: Fix dummy byte handling for Spansion flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spansion flashes expose the number of dummy clock cycles through CR2V register [1]. The value is a cycle count, not a byte count, so the m25p80 model has to convert it to the number of whole SSI transfer bytes consumed while collecting read command data. Add a helper that multiplies the CR2V dummy cycle count by the phase width and rounds up non-byte-aligned counts, matching the byte-oriented SSI model. The default eight-cycle configuration keeps the same byte counts as before. [1] https://www.infineon.com/assets/row/public/documents/10/49/infineon-s25fs128s-s25fs256s-1-datasheet-en.pdf Fixes: cf6f1efe0b57 ("m25p80: Fast read commands family changes") Signed-off-by: Bin Meng Tested-by: Cédric Le Goater Message-ID: <20260707083431.219671-5-bin.meng@processmission.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/block/m25p80.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index d7a9d79373..545e0b5728 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -1057,6 +1057,23 @@ static uint8_t macronix_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width) return dummy_bits / 8; } +static uint8_t spansion_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width) +{ + uint8_t dummy_bits; + + dummy_bits = extract32(s->spansion_cr2v, SPANSION_DUMMY_CLK_POS, + SPANSION_DUMMY_CLK_LEN); + dummy_bits *= bus_width; + + /* + * Assert that the dummy bit count is byte-aligned + * as SSI core can only consume whole dummy bytes. + */ + assert(dummy_bits % 8 == 0); + + return dummy_bits / 8; +} + static void decode_fast_read_cmd(Flash *s) { s->needed_bytes = get_addr_length(s); @@ -1075,10 +1092,7 @@ static void decode_fast_read_cmd(Flash *s) s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 1); break; case MAN_SPANSION: - s->needed_bytes += extract32(s->spansion_cr2v, - SPANSION_DUMMY_CLK_POS, - SPANSION_DUMMY_CLK_LEN - ); + s->needed_bytes += spansion_extract_cfg_dummy_bytes(s, 1); break; case MAN_ISSI: /* @@ -1111,10 +1125,7 @@ static void decode_dio_read_cmd(Flash *s) break; case MAN_SPANSION: s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; - s->needed_bytes += extract32(s->spansion_cr2v, - SPANSION_DUMMY_CLK_POS, - SPANSION_DUMMY_CLK_LEN - ); + s->needed_bytes += spansion_extract_cfg_dummy_bytes(s, 2); break; case MAN_NUMONYX: s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s); @@ -1151,10 +1162,7 @@ static void decode_qio_read_cmd(Flash *s) break; case MAN_SPANSION: s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; - s->needed_bytes += extract32(s->spansion_cr2v, - SPANSION_DUMMY_CLK_POS, - SPANSION_DUMMY_CLK_LEN - ); + s->needed_bytes += spansion_extract_cfg_dummy_bytes(s, 4); break; case MAN_NUMONYX: s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);