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
/*