@samitouri / QOSamiQemu / commits / 5bcedae7a7

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

Macronix flashes expose DC[1:0] bits in the volatile configuration register [1]. These bits select the number of dummy clock cycles used by the fast-read command families. Convert the Macronix dummy-cycle settings through per-command-family tables and round up the non-byte-aligned cases that the byte-oriented SSI model cannot represent exactly. [1] https://www.macronix.com/Lists/Datasheet/Attachments/8657/MX66L51235F,%203V,%20512Mb,%20v1.1.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-4-bin.meng@processmission.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

Bin Meng committed Jul 7, 2026 at 16:34 UTC 5bcedae7a7dc42d19d96335e7d444cf0c24799ba
1 file changed +36 -27
hw/block/m25p80.c
+36 -27
@@ -1024,6 +1024,39 @@ static uint8_t numonyx_extract_cfg_dummy_bytes(Flash *s)
1024 return dummy_bits / 8;
1025 }
1026
1027 +static uint8_t macronix_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width)
1028 +{
1029 + static const uint8_t dummy_cycles_fast[4] = { 8, 6, 8, 10 };
1030 + static const uint8_t dummy_cycles_dio[4] = { 4, 6, 8, 10 };
1031 + static const uint8_t dummy_cycles_qio[4] = { 6, 4, 8, 10 };
1032 + const uint8_t *dummy_cycles = dummy_cycles_fast;
1033 + uint8_t dummy_bits;
1034 +
1035 + switch (s->cmd_in_progress) {
1036 + case DIOR:
1037 + case DIOR4:
1038 + dummy_cycles = dummy_cycles_dio;
1039 + break;
1040 + case QIOR:
1041 + case QIOR4:
1042 + dummy_cycles = dummy_cycles_qio;
1043 + break;
1044 + default:
1045 + break;
1046 + }
1047 +
1048 + dummy_bits = dummy_cycles[extract32(s->volatile_cfg, 6, 2)];
1049 + dummy_bits *= bus_width;
1050 +
1051 + /*
1052 + * Assert that the dummy bit count is byte-aligned
1053 + * as SSI core can only consume whole dummy bytes.
1054 + */
1055 + assert(dummy_bits % 8 == 0);
1056 +
1057 + return dummy_bits / 8;
1058 +}
1059 +
1060 static void decode_fast_read_cmd(Flash *s)
1061 {
1062 s->needed_bytes = get_addr_length(s);
@@ -1039,11 +1072,7 @@ static void decode_fast_read_cmd(Flash *s)
1072 s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
1073 break;
1074 case MAN_MACRONIX:
1042 - if (extract32(s->volatile_cfg, 6, 2) == 1) {
1043 - s->needed_bytes += 6;
1044 - } else {
1045 - s->needed_bytes += 8;
1046 - }
1075 + s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 1);
1076 break;
1077 case MAN_SPANSION:
1078 s->needed_bytes += extract32(s->spansion_cr2v,
@@ -1091,17 +1120,7 @@ static void decode_dio_read_cmd(Flash *s)
1120 s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
1121 break;
1122 case MAN_MACRONIX:
1094 - switch (extract32(s->volatile_cfg, 6, 2)) {
1095 - case 1:
1096 - s->needed_bytes += 6;
1097 - break;
1098 - case 2:
1099 - s->needed_bytes += 8;
1100 - break;
1101 - default:
1102 - s->needed_bytes += 4;
1103 - break;
1104 - }
1123 + s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 2);
1124 break;
1125 case MAN_ISSI:
1126 /*
@@ -1141,17 +1160,7 @@ static void decode_qio_read_cmd(Flash *s)
1160 s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
1161 break;
1162 case MAN_MACRONIX:
1144 - switch (extract32(s->volatile_cfg, 6, 2)) {
1145 - case 1:
1146 - s->needed_bytes += 4;
1147 - break;
1148 - case 2:
1149 - s->needed_bytes += 8;
1150 - break;
1151 - default:
1152 - s->needed_bytes += 6;
1153 - break;
1154 - }
1163 + s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 4);
1164 break;
1165 case MAN_ISSI:
1166 /*