From: Marcin Krzeminski <marcin.krzemin...@nokia.com> Signed-off-by: Pawel Lenkow <pawel.len...@nokia.com> --- hw/block/m25p80.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 25ec666..fadd6ec 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -107,6 +107,7 @@ typedef struct FlashPartInfo { #define JEDEC_NUMONYX 0x20 #define JEDEC_WINBOND 0xEF #define JEDEC_SPANSION 0x01 +#define JEDEC_MACRONIX 0xC2 static const FlashPartInfo known_devices[] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ @@ -157,6 +158,7 @@ static const FlashPartInfo known_devices[] = { { INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) }, { INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) }, { INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) }, + { INFO("mx66u51235f", 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) }, /* Micron */ { INFO("n25q032a11", 0x20bb16, 0, 64 << 10, 64, ER_4K) }, @@ -175,7 +177,7 @@ static const FlashPartInfo known_devices[] = { { INFO("s25sl064p", 0x010216, 0x4d00, 64 << 10, 128, ER_4K) }, { INFO("s25fl256s0", 0x010219, 0x4d00, 256 << 10, 128, 0) }, { INFO("s25fl256s1", 0x010219, 0x4d01, 64 << 10, 512, 0) }, - { INFO("s25fl512s", 0x010220, 0x4d00, 256 << 10, 256, 0) }, + { INFO6("s25fl512s", 0x010220, 0x4d0080, 256 << 10, 256, 0) }, { INFO("s70fl01gs", 0x010221, 0x4d00, 256 << 10, 256, 0) }, { INFO("s25sl12800", 0x012018, 0x0300, 256 << 10, 64, 0) }, { INFO("s25sl12801", 0x012018, 0x0301, 64 << 10, 256, 0) }, @@ -189,6 +191,9 @@ static const FlashPartInfo known_devices[] = { { INFO("s25fl016k", 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) }, { INFO("s25fl064k", 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) }, + /* Spansion -- boot sectors support */ + { INFO6("s25fs512s", 0x010220, 0x4d0081, 256 << 10, 256, 0) }, + /* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */ { INFO("sst25vf040b", 0xbf258d, 0, 64 << 10, 8, ER_4K) }, { INFO("sst25vf080b", 0xbf258e, 0, 64 << 10, 16, ER_4K) }, @@ -283,6 +288,12 @@ typedef enum { RESET_ENABLE = 0x66, RESET_MEMORY = 0x99, + /* + * Micron: 0x35 - enable QPI + * Spansion: 0x35 - read control register + */ + RDCR_QPIEN = 0x35, + } FlashCMD; typedef enum { @@ -509,6 +520,16 @@ static void complete_collecting_data(Flash *s) flash_erase(s, s->cur_addr, s->cmd_in_progress); break; case WRSR: + switch (s->pi->id[0]) { + case JEDEC_SPANSION: + s->quad_enable = !!(s->data[1] & 0x02); + break; + case JEDEC_MACRONIX: + s->quad_enable = !!(s->data[0] & 0x40); + break; + default: + break; + } if (s->write_enable) { s->write_enable = false; } @@ -610,7 +631,19 @@ static void decode_new_cmd(Flash *s, uint32_t value) break; case WRSR: if (s->write_enable) { - s->needed_bytes = 1; + switch (s->pi->id[0]) { + case JEDEC_SPANSION: + /* FIXME: + * needed_bytes fixed to 2 because Spansion + * supports access to 2nd register + * in one WRSR command and Linux is using it. + * Real needed_bytes should depend on CS line. + */ + s->needed_bytes = 2; + break; + default: + s->needed_bytes = 1; + } s->pos = 0; s->len = 0; s->state = STATE_COLLECTING_DATA; @@ -626,6 +659,9 @@ static void decode_new_cmd(Flash *s, uint32_t value) case RDSR: s->data[0] = (!!s->write_enable) << 1; + if (s->pi->id[0] == JEDEC_MACRONIX) { + s->data[0] |= (!!s->quad_enable) << 6; + } s->pos = 0; s->len = 1; s->state = STATE_READING_DATA; @@ -680,6 +716,18 @@ static void decode_new_cmd(Flash *s, uint32_t value) reset_memory(s); } break; + case RDCR_QPIEN: + switch (s->pi->id[0]) { + case JEDEC_SPANSION: + s->data[0] = (!!s->quad_enable) << 1; + s->pos = 0; + s->len = 1; + s->state = STATE_READING_DATA; + break; + default: + break; + } + break; default: qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value); break; -- 2.5.0