@samitouri / QOSamiQemu / commits / 4957f668c4

hw/block: m25p80: Fix dummy byte handling for Spansion flash

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 <bin.meng@processmission.com> Tested-by: Cédric Le Goater <clg@redhat.com> Message-ID: <20260707083431.219671-5-bin.meng@processmission.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

Bin Meng committed Jul 7, 2026 at 16:34 UTC 4957f668c4369f6b80e77b04e604747ca6014c9a
1 file changed +20 -12
hw/block/m25p80.c
+20 -12
@@ -1057,6 +1057,23 @@ static uint8_t macronix_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width)
1057 return dummy_bits / 8;
1058 }
1059
1060 +static uint8_t spansion_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width)
1061 +{
1062 + uint8_t dummy_bits;
1063 +
1064 + dummy_bits = extract32(s->spansion_cr2v, SPANSION_DUMMY_CLK_POS,
1065 + SPANSION_DUMMY_CLK_LEN);
1066 + dummy_bits *= bus_width;
1067 +
1068 + /*
1069 + * Assert that the dummy bit count is byte-aligned
1070 + * as SSI core can only consume whole dummy bytes.
1071 + */
1072 + assert(dummy_bits % 8 == 0);
1073 +
1074 + return dummy_bits / 8;
1075 +}
1076 +
1077 static void decode_fast_read_cmd(Flash *s)
1078 {
1079 s->needed_bytes = get_addr_length(s);
@@ -1075,10 +1092,7 @@ static void decode_fast_read_cmd(Flash *s)
1092 s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 1);
1093 break;
1094 case MAN_SPANSION:
1078 - s->needed_bytes += extract32(s->spansion_cr2v,
1079 - SPANSION_DUMMY_CLK_POS,
1080 - SPANSION_DUMMY_CLK_LEN
1081 - );
1095 + s->needed_bytes += spansion_extract_cfg_dummy_bytes(s, 1);
1096 break;
1097 case MAN_ISSI:
1098 /*
@@ -1111,10 +1125,7 @@ static void decode_dio_read_cmd(Flash *s)
1125 break;
1126 case MAN_SPANSION:
1127 s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
1114 - s->needed_bytes += extract32(s->spansion_cr2v,
1115 - SPANSION_DUMMY_CLK_POS,
1116 - SPANSION_DUMMY_CLK_LEN
1117 - );
1128 + s->needed_bytes += spansion_extract_cfg_dummy_bytes(s, 2);
1129 break;
1130 case MAN_NUMONYX:
1131 s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
@@ -1151,10 +1162,7 @@ static void decode_qio_read_cmd(Flash *s)
1162 break;
1163 case MAN_SPANSION:
1164 s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
1154 - s->needed_bytes += extract32(s->spansion_cr2v,
1155 - SPANSION_DUMMY_CLK_POS,
1156 - SPANSION_DUMMY_CLK_LEN
1157 - );
1165 + s->needed_bytes += spansion_extract_cfg_dummy_bytes(s, 4);
1166 break;
1167 case MAN_NUMONYX:
1168 s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);