Newer Linux kernels support multi-die Winbond flashes such as
W25Q01JV. When polling the flash ready status, the kernel sends the
Software Die Select (0xC2) command followed by a one byte die ID for
each die, and then reads the status register of the selected die.

The m25p80 model does not implement this command, so running with
"-d guest_errors" keeps flooding the log with "M25P80: Unknown cmd c2"
messages whenever the flash is written or erased.

Implement the command for Winbond devices by collecting the one byte
die ID. The model stores the flash array as a single contiguous
storage and only has one set of status registers, so the selected die
does not affect the current design. The die ID in data[0] is not used.

This commit only fixes the "Unknown cmd c2" log flood.

Signed-off-by: Jamin Lin <[email protected]>
---
 hw/block/m25p80.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index baf798c6b5..528df57e5a 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -451,6 +451,11 @@ typedef enum {
     WEVCR = 0x61,
 
     DIE_ERASE = 0xC4,
+
+    /*
+     * Winbond: 0xC2 - software die select (multi-die devices)
+     */
+    DIE_SELECT = 0xC2,
 } FlashCMD;
 
 typedef enum {
@@ -1479,6 +1484,20 @@ static void decode_new_cmd(Flash *s, uint32_t value)
             s->state = STATE_COLLECTING_DATA;
         }
         break;
+    case DIE_SELECT:
+        /*
+         * The flash array is modelled as a single contiguous storage,
+         * so the die ID is collected and ignored.
+         */
+        if (get_man(s) == MAN_WINBOND) {
+            s->needed_bytes = 1;
+            s->pos = 0;
+            s->len = 0;
+            s->state = STATE_COLLECTING_DATA;
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value);
+        }
+        break;
     case RNVCR:
         s->data[0] = s->nonvolatile_cfg & 0xFF;
         s->data[1] = (s->nonvolatile_cfg >> 8) & 0xFF;
-- 
2.53.0

Reply via email to