[PATCH v1 03/16] hw/block:m25p80: Support write status register 2 command (0x31) for w25q01jvq

Jamin Lin via posted 16 patches 4 days, 17 hours ago
There is a newer version of this series
[PATCH v1 03/16] hw/block:m25p80: Support write status register 2 command (0x31) for w25q01jvq
Posted by Jamin Lin via 4 days, 17 hours ago
According to the w25q01jv datasheet at page 16, it is required to set QE bit
in "Status Register 2" to enable quad mode.

Currently, m25p80 support users utilize "Write Status Register 1(0x01)" command
to set QE bit in "Status Register 2" and utilize "Read Status Register 2(0x35)"
command to get the QE bit status.

However, some firmware directly utilize "Status Register 2(0x31)" command to
set QE bit. To fully support quad mode for w25q01jvq, adds WRSR2 command.

Update collecting data needed 1 byte for WRSR2 command in decode_new_cmd
function and verify QE bit at the first byte of collecting data bit 2 in
complete_collecting_data.

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 hw/block/m25p80.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 3f55b8f385..411d810d3b 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -430,6 +430,11 @@ typedef enum {
     RDCR_EQIO = 0x35,
     RSTQIO = 0xf5,
 
+    /*
+     * Winbond: 0x31 - write status register 2
+     */
+    WRSR2 = 0x31,
+
     RNVCR = 0xB5,
     WNVCR = 0xB1,
 
@@ -821,6 +826,15 @@ static void complete_collecting_data(Flash *s)
             s->write_enable = false;
         }
         break;
+    case WRSR2:
+        switch (get_man(s)) {
+        case MAN_WINBOND:
+            s->quad_enable = !!(s->data[0] & 0x02);
+            break;
+        default:
+            break;
+        }
+        break;
     case BRWR:
     case EXTEND_ADDR_WRITE:
         s->ear = s->data[0];
@@ -1280,7 +1294,31 @@ static void decode_new_cmd(Flash *s, uint32_t value)
         }
         s->pos = 0;
         break;
+    case WRSR2:
+        /*
+         * If WP# is low and status_register_write_disabled is high,
+         * status register writes are disabled.
+         * This is also called "hardware protected mode" (HPM). All other
+         * combinations of the two states are called "software protected mode"
+         * (SPM), and status register writes are permitted.
+         */
+        if ((s->wp_level == 0 && s->status_register_write_disabled)
+            || !s->write_enable) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "M25P80: Status register 2 write is disabled!\n");
+            break;
+        }
 
+        switch (get_man(s)) {
+        case MAN_WINBOND:
+            s->needed_bytes = 1;
+            s->state = STATE_COLLECTING_DATA;
+            s->pos = 0;
+            break;
+        default:
+            break;
+        }
+        break;
     case WRDI:
         s->write_enable = false;
         if (get_man(s) == MAN_SST) {
-- 
2.34.1
Re: [SPAM] [PATCH v1 03/16] hw/block:m25p80: Support write status register 2 command (0x31) for w25q01jvq
Posted by Cédric Le Goater 1 day, 14 hours ago
On 10/18/24 07:30, Jamin Lin wrote:
> According to the w25q01jv datasheet at page 16, it is required to set QE bit
> in "Status Register 2" to enable quad mode.
> 
> Currently, m25p80 support users utilize "Write Status Register 1(0x01)" command
> to set QE bit in "Status Register 2" and utilize "Read Status Register 2(0x35)"
> command to get the QE bit status.
> 
> However, some firmware directly utilize "Status Register 2(0x31)" command to
> set QE bit. To fully support quad mode for w25q01jvq, adds WRSR2 command.
> 
> Update collecting data needed 1 byte for WRSR2 command in decode_new_cmd
> function and verify QE bit at the first byte of collecting data bit 2 in
> complete_collecting_data.
> 
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>


Reviewed-by: Cédric Le Goater <clg@redhat.com>

Thanks,

C.


> ---
>   hw/block/m25p80.c | 38 ++++++++++++++++++++++++++++++++++++++
>   1 file changed, 38 insertions(+)
> 
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 3f55b8f385..411d810d3b 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -430,6 +430,11 @@ typedef enum {
>       RDCR_EQIO = 0x35,
>       RSTQIO = 0xf5,
>   
> +    /*
> +     * Winbond: 0x31 - write status register 2
> +     */
> +    WRSR2 = 0x31,
> +
>       RNVCR = 0xB5,
>       WNVCR = 0xB1,
>   
> @@ -821,6 +826,15 @@ static void complete_collecting_data(Flash *s)
>               s->write_enable = false;
>           }
>           break;
> +    case WRSR2:
> +        switch (get_man(s)) {
> +        case MAN_WINBOND:
> +            s->quad_enable = !!(s->data[0] & 0x02);
> +            break;
> +        default:
> +            break;
> +        }
> +        break;
>       case BRWR:
>       case EXTEND_ADDR_WRITE:
>           s->ear = s->data[0];
> @@ -1280,7 +1294,31 @@ static void decode_new_cmd(Flash *s, uint32_t value)
>           }
>           s->pos = 0;
>           break;
> +    case WRSR2:
> +        /*
> +         * If WP# is low and status_register_write_disabled is high,
> +         * status register writes are disabled.
> +         * This is also called "hardware protected mode" (HPM). All other
> +         * combinations of the two states are called "software protected mode"
> +         * (SPM), and status register writes are permitted.
> +         */
> +        if ((s->wp_level == 0 && s->status_register_write_disabled)
> +            || !s->write_enable) {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "M25P80: Status register 2 write is disabled!\n");
> +            break;
> +        }
>   
> +        switch (get_man(s)) {
> +        case MAN_WINBOND:
> +            s->needed_bytes = 1;
> +            s->state = STATE_COLLECTING_DATA;
> +            s->pos = 0;
> +            break;
> +        default:
> +            break;
> +        }
> +        break;
>       case WRDI:
>           s->write_enable = false;
>           if (get_man(s) == MAN_SST) {