mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
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: cf6f1efe0b ("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>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
42b6165cd7
commit
5bcedae7a7
@@ -1024,6 +1024,39 @@ static uint8_t numonyx_extract_cfg_dummy_bytes(Flash *s)
|
||||
return dummy_bits / 8;
|
||||
}
|
||||
|
||||
static uint8_t macronix_extract_cfg_dummy_bytes(Flash *s, uint8_t bus_width)
|
||||
{
|
||||
static const uint8_t dummy_cycles_fast[4] = { 8, 6, 8, 10 };
|
||||
static const uint8_t dummy_cycles_dio[4] = { 4, 6, 8, 10 };
|
||||
static const uint8_t dummy_cycles_qio[4] = { 6, 4, 8, 10 };
|
||||
const uint8_t *dummy_cycles = dummy_cycles_fast;
|
||||
uint8_t dummy_bits;
|
||||
|
||||
switch (s->cmd_in_progress) {
|
||||
case DIOR:
|
||||
case DIOR4:
|
||||
dummy_cycles = dummy_cycles_dio;
|
||||
break;
|
||||
case QIOR:
|
||||
case QIOR4:
|
||||
dummy_cycles = dummy_cycles_qio;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dummy_bits = dummy_cycles[extract32(s->volatile_cfg, 6, 2)];
|
||||
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);
|
||||
@@ -1039,11 +1072,7 @@ static void decode_fast_read_cmd(Flash *s)
|
||||
s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
|
||||
break;
|
||||
case MAN_MACRONIX:
|
||||
if (extract32(s->volatile_cfg, 6, 2) == 1) {
|
||||
s->needed_bytes += 6;
|
||||
} else {
|
||||
s->needed_bytes += 8;
|
||||
}
|
||||
s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 1);
|
||||
break;
|
||||
case MAN_SPANSION:
|
||||
s->needed_bytes += extract32(s->spansion_cr2v,
|
||||
@@ -1091,17 +1120,7 @@ static void decode_dio_read_cmd(Flash *s)
|
||||
s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
|
||||
break;
|
||||
case MAN_MACRONIX:
|
||||
switch (extract32(s->volatile_cfg, 6, 2)) {
|
||||
case 1:
|
||||
s->needed_bytes += 6;
|
||||
break;
|
||||
case 2:
|
||||
s->needed_bytes += 8;
|
||||
break;
|
||||
default:
|
||||
s->needed_bytes += 4;
|
||||
break;
|
||||
}
|
||||
s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 2);
|
||||
break;
|
||||
case MAN_ISSI:
|
||||
/*
|
||||
@@ -1141,17 +1160,7 @@ static void decode_qio_read_cmd(Flash *s)
|
||||
s->needed_bytes += numonyx_extract_cfg_dummy_bytes(s);
|
||||
break;
|
||||
case MAN_MACRONIX:
|
||||
switch (extract32(s->volatile_cfg, 6, 2)) {
|
||||
case 1:
|
||||
s->needed_bytes += 4;
|
||||
break;
|
||||
case 2:
|
||||
s->needed_bytes += 8;
|
||||
break;
|
||||
default:
|
||||
s->needed_bytes += 6;
|
||||
break;
|
||||
}
|
||||
s->needed_bytes += macronix_extract_cfg_dummy_bytes(s, 4);
|
||||
break;
|
||||
case MAN_ISSI:
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user