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) {