From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA1AA4F054E; Fri, 4 Sep 2026 18:13:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545592; cv=none; b=e8OMpLYdq4Jj5bY6xFRb/vVNVR0u3Wipotp1PjpwS8ox6PRG+IlZnyyFMobqLUWGmDy315Rc0tm0iwSaxzraPRhyZBzZnJhpGOrEwI8yfGtUDvI1MNcRTcSgoMb7HronevnrxqMt/xv1s0T0yc7jScyNfX/bOFC16s+41fyfBLQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545592; c=relaxed/simple; bh=Uk6XPACReZo+eEumpo6pFYM5JIJufdWuddTF2PyTYtg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nsESvIT1U3uvp6CelCZINpHYH8In2BYpgZhPcTPePlqCMavoOJ+cY6LHIwQzUSDMbZG2CuGEQE4EU3DR/22noPPNisjNbNRnlaYmRKQzYaiDO0mjd/ryLdhXbzqx9JEQ38CrG8Fr04boX1PMAbKsSY9jfnElN8B6+Pczz7yDm9k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=cf42qijb; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="cf42qijb" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 5582B4E41521; Fri, 4 Sep 2026 18:13:09 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 219106057F; Fri, 4 Sep 2026 18:13:09 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 7672B11C78767; Fri, 4 Sep 2026 20:13:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545584; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=TYvl3/rhFkeeIA5nCbOHxwMVTbW8grC81clzEw+bIAE=; b=cf42qijblLDMXYj9+s1Aujxzt6M86dKKVf0cBmoaE2F7OstFL5nOfKCl8OLY0Wy8DaIlpt AdvnkbQgb/d/LBQFg3sf8oB6rTBYH/R2q8eJK23NEHCBahxcycNFLlyNDwrnbiOh7xrMOS Y5WCrA5o65SYfToK/8NkZtGC1IhD64yXz+feKPEi1HMlQcL8/XZYL1F40jsm6hUwpc6XMp j9kktlFCRFbKiZbFTkcu9r7Mq0cqtVbRoQZC5LcV1fM/jl8gbSajVjhLGDaaKdTLLdqkB2 HGnKdfy6+enRnMZzGE5pDzMmtw79RVTDEIRABIGOeraN0+9LPK2zT3hDnRl3zw== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:38 +0200 Subject: [PATCH v5 01/25] mtd: spi-nor: Rename BFPT_DWORD15_QER_SR2_BIT1_BUGGY Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-1-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 The _BUGGY suffix is not super accurate. There is a behavior that indeed seems strange, but it is somewhat documented. The fact is, with this QER field the status register is considered 16-bit wide and if one writes the first 8 bits (SR1) without the next 8 bits (SR2) then the content of SR2 will be assumed to be 0x00 and will be cleared. Rename it BFPT_DWORD15_QER_SR2_BIT1_NO_1B_WR to align with the other namings (_NO_RD) and clarify the meaning of this field. No functional change. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/sfdp.c | 2 +- drivers/mtd/spi-nor/sfdp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 24e4d07b18c9..ab57fa60f718 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -598,7 +598,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, params->quad_enable =3D NULL; break; =20 - case BFPT_DWORD15_QER_SR2_BIT1_BUGGY: + case BFPT_DWORD15_QER_SR2_BIT1_NO_1B_WR: /* * Writing only one byte to the Status Register has the * side-effect of clearing Status Register 2. diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h index f74a0eb339ea..d976c6c9a4ad 100644 --- a/drivers/mtd/spi-nor/sfdp.h +++ b/drivers/mtd/spi-nor/sfdp.h @@ -84,7 +84,7 @@ struct sfdp_bfpt { */ #define BFPT_DWORD15_QER_MASK GENMASK(22, 20) #define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */ -#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20) +#define BFPT_DWORD15_QER_SR2_BIT1_NO_1B_WR (0x1UL << 20) #define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */ #define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20) #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE2624F054E; Fri, 4 Sep 2026 18:13:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545598; cv=none; b=jwobmIjBLDNR+Er1t8BwL6gnKebVoclyegCtLWyUOQzRB0Ard2y8PJArcU1YPzatBXEIs2aooZlnoLSWTftB0EzeFHGEjsP6G6dfAwEnBhq0FsuB0G0uPB0Lwa12+nMT1+lrPgB8CuHcXoS3I92AHx54iJfGbJfePKNfyG1BIAM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545598; c=relaxed/simple; bh=XySjZXjnqbC/qcFT7BRp2wStbhEOco70iAizjFWhDno=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LuR8Bo2nTMe2daS967PHurAfwI3QRgVEuX43frCm7ci2ILVGehJXr231HfBAUqO9RiOagSI9BQWG9yU53mDPBT2wOGdFM5Th17Kr5OZxxGSY37Xys+MZVp55c/31cYifNHF+UTKiSHcKR16JR8VGGfJJRU14cZVkIP0/NCpB1v0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=xTxWOJvW; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="xTxWOJvW" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 70BD74E41521; Fri, 4 Sep 2026 18:13:15 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 43A0D6057F; Fri, 4 Sep 2026 18:13:15 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 766CD11C787BD; Fri, 4 Sep 2026 20:13:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545590; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=I4kegzq08HeRW+Oy3ebXbcHB82GNZUAAxxOPVEO053A=; b=xTxWOJvWuDI7zuWB4ASzLg6Hl6+aKhbIIiuHb6QI7R4BZ77DGfgrFnD7UuZvaDb8JURM3H /7K3+b2lIuIwUe44GnN3kDLgcaRvXdQXJHXrwwiS/g3iMGwEhIaeyQzB1CQCRXignQtkux JdaRgdRhfLxwlMcHRKtzPcSUSea3sl3EGtoW4cnXBu08Fb1NA4GoQl7OgE8+3+RMxwbSrC 2wtkmLKOayC4LWI2XOr9gdONYu7ILPEUwuDr8RPTEigyz0OeJvmHM1g2guzA9+ublOHRcT uxaQ1cB5GVyy+ucpxVT2GE363riUpPnEb+0GfOe9fOfASWmumU6Kb0wc9LKmLQ== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:39 +0200 Subject: [PATCH v5 02/25] mtd: spi-nor: Create a structure containing the flash opcodes Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-2-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Create a structure named opcodes in the flash parameters structures to store all the flash specific opcodes. They are typically discovered dynamically through SFDP parsing. Move the die_erase opcode inside. Later on we will add new fields there, like the supported opcodes for accessing the status registers, which are almost vendor specific. No fonctional change. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/core.c | 6 +++--- drivers/mtd/spi-nor/core.h | 13 +++++++++++-- drivers/mtd/spi-nor/debugfs.c | 2 +- drivers/mtd/spi-nor/micron-st.c | 4 ++-- drivers/mtd/spi-nor/spansion.c | 4 ++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index d9821620f59b..886f3c956309 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1142,7 +1142,7 @@ static int spi_nor_erase_die(struct spi_nor *nor, lof= f_t addr, size_t die_size) =20 if (nor->spimem) { struct spi_mem_op op =3D - SPI_NOR_DIE_ERASE_OP(nor->params->die_erase_opcode, + SPI_NOR_DIE_ERASE_OP(nor->params->opcodes.die_erase, nor->addr_nbytes, addr, multi_die); =20 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); @@ -3023,8 +3023,8 @@ static int spi_nor_late_init_params(struct spi_nor *n= or) return ret; } =20 - if (!nor->params->die_erase_opcode) - nor->params->die_erase_opcode =3D SPINOR_OP_CHIP_ERASE; + if (!nor->params->opcodes.die_erase) + nor->params->opcodes.die_erase =3D SPINOR_OP_CHIP_ERASE; =20 /* Default method kept for backward compatibility. */ if (!params->set_4byte_addr_mode) diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index d59ec9cad986..4b36d99ce8f6 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -342,6 +342,16 @@ struct spi_nor_otp { const struct spi_nor_otp_ops *ops; }; =20 +/** + * struct spi_nor_opcodes - SPI NOR flash specific opcodes. + * List of variable opcodes used by the chip. + * + * @die_erase: opcode for erasing a die, defaults to SPINOR_OP_CHIP_ERASE + */ +struct spi_nor_opcodes { + u8 die_erase; +}; + /** * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings. * Includes legacy flash parameters and settings that can be overwritten @@ -365,7 +375,6 @@ struct spi_nor_otp { * command in octal DTR mode. * @n_banks: number of banks. * @n_dice: number of dice in the flash memory. - * @die_erase_opcode: die erase opcode. Defaults to SPINOR_OP_CHIP_ERASE. * @vreg_offset: volatile register offset for each die. * @hwcaps: describes the read and page program hardware * capabilities. @@ -398,7 +407,6 @@ struct spi_nor_flash_parameter { u8 rdsr_addr_nbytes; u8 n_banks; u8 n_dice; - u8 die_erase_opcode; u32 *vreg_offset; =20 struct spi_nor_hwcaps hwcaps; @@ -406,6 +414,7 @@ struct spi_nor_flash_parameter { struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; enum spi_nor_cmd_ext cmd_ext_type; =20 + struct spi_nor_opcodes opcodes; struct spi_nor_erase_map erase_map; struct spi_nor_otp otp; =20 diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index 437a0e0cb4dd..5a7372e7f802 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -144,7 +144,7 @@ static int spi_nor_params_show(struct seq_file *s, void= *data) } =20 string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf)); - seq_printf(s, " %02x (%s)\n", params->die_erase_opcode, buf); + seq_printf(s, " %02x (%s)\n", params->opcodes.die_erase, buf); =20 seq_puts(s, "\nsector map\n"); seq_puts(s, " region (in hex) | erase mask | overlaid\n"); diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-s= t.c index ca2ce18050df..3c89bd9b575c 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -131,7 +131,7 @@ static int micron_st_nor_four_die_late_init(struct spi_= nor *nor) { struct spi_nor_flash_parameter *params =3D nor->params; =20 - params->die_erase_opcode =3D SPINOR_OP_MT_DIE_ERASE; + params->opcodes.die_erase =3D SPINOR_OP_MT_DIE_ERASE; params->n_dice =3D 4; =20 /* @@ -147,7 +147,7 @@ static int micron_st_nor_two_die_late_init(struct spi_n= or *nor) { struct spi_nor_flash_parameter *params =3D nor->params; =20 - params->die_erase_opcode =3D SPINOR_OP_MT_DIE_ERASE; + params->opcodes.die_erase =3D SPINOR_OP_MT_DIE_ERASE; params->n_dice =3D 2; =20 /* diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c index ec494e14ec82..d29a901900f8 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -677,7 +677,7 @@ static int s25hx_t_late_init(struct spi_nor *nor) cypress_nor_ecc_init(nor); =20 if (params->n_dice > 1) - params->die_erase_opcode =3D SPINOR_OP_CYPRESS_DIE_ERASE; + params->opcodes.die_erase =3D SPINOR_OP_CYPRESS_DIE_ERASE; =20 return 0; } @@ -765,7 +765,7 @@ static int s28hx_t_late_init(struct spi_nor *nor) cypress_nor_ecc_init(nor); =20 if (params->n_dice > 1) - params->die_erase_opcode =3D SPINOR_OP_CYPRESS_DIE_ERASE; + params->opcodes.die_erase =3D SPINOR_OP_CYPRESS_DIE_ERASE; =20 return 0; } --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5FD29519901; Fri, 4 Sep 2026 18:13:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545603; cv=none; b=oceTFXzcd/OO4G4ZE81/zobbrRh6f6mi+NKmmg18VxDJRfQr7LlO4YtjBirJ4J70FAxgR1miPe2HXZhgOxnswmmtI1e4SV1eXM3JJ2yxXNX78wwyYiVih3o8Xe0Q4THYVp0XR7Fy5z9TyKSi/G81Yvtna/HKH3VE+l7UshW1F9c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545603; c=relaxed/simple; bh=LDpHZhoy1y8SW5PDxFSHPQ/oxRJuBp9q4KR9uNQGPuI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=vAD1ePUo8joSvaAnW91fVK4NFcoCgWoZXTFZduH/i2VIFXCEJey61RbyCIE1vv3pae+S7EBo/+XZ+aHl7gG/SJNguC0/Qxm2XS2FQknnd8+C8+aXvQkjrOk/FjDD1cvy9/4AHlkasE7zLYAtaXCTaW48aEw7ak9w6FW4wVwy7ZA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=yG94PTa2; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="yG94PTa2" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id CFFCE4E41522; Fri, 4 Sep 2026 18:13:17 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id A35E36057F; Fri, 4 Sep 2026 18:13:17 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 9BCC311C7931F; Fri, 4 Sep 2026 20:13:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545596; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=8msqKd+Oxs6rePCB9/DPOPG82hGkfvZ+jGvvh65rXx4=; b=yG94PTa23llVrPVVk9TZqfgaXIlTIvm/2oGO6p2tXjv7xXfUqICu/X6CXibY860Xs420ix uUKf9B71g36EydIr/Powrr5LAcXVlfTPoo83Xo1opmF4N6uDyuhHL0bQJ/+WVolIwPagw4 U15eY1E6NRk8gdh0RvhbRk4Iqi/PFVpt9j686oq5r1vCtgBf8HdVw8uDKxW0VDpPXJX0r4 4kiN9qf5c5XB2Iqpff0j0L7HXSV539a5esRCoVDW6Xqi7G0tcUz3MoNRE5Bx8gilTgrTFs DJ0hPMtJsxVqhQ+znNLgII62WKDo8PcgW3G46Ggrm9q7qBMAusFgsNFBFDOnqg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:40 +0200 Subject: [PATCH v5 03/25] mtd: spi-nor: Refactor Read Status/Write Status support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-3-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 SPI NOR has a lot of history. Additions over additions, the subtleties of the JESD216 specification, their implementations by the manufacturers and the hardware mistakes have generated a gigantic maze, let's try to understand what is really needed. The specification explains the QE (Quad Enable) bitfield as describing where the bit to enable the Quad capability is, but also how to set it. Unfortunately, the specification is not precise about what opcodes are supported exactly in all the cases. There is an introduction that basically states: - Opcode 0x05 reads SR1 - Opcode 0x35 reads SR2 - Opcode 0x01 writes SR1, and then SR2 if another byte is written Then the bitfield, among indicating the location of the QE bit, may indicate: - Reading SR1 and SR2 in one operation is not possible (loops over the content of SR1) - Reading SR2 directly is possible - Only writing SR1 zeroes SR2. One problem with the current implementation, is that it only focuses on the QE bit. A quad_enable function was created for each case, even though in practice, the logic was always the same: read, modify, write, read back and verify. One problem comes when other features need to play with the status registers, like software block protection or OTP: you never know how to properly handle the QE bit, nor where it is, nor how to read/write the Status registers. This lead to approximations/guessing (in swp.c, otp.c and obviously in legacy controller drivers like atmel.c) but also to the implementation of a gazillon of helpers for reading/writing/checking the status registers. In addition, I believe some design decisions had a negative impact over the years. - All possible situations had to be flagged by the core. This is likely wrong, because we no longer know why we need specific quirks. It was ineherent to the state of the SPI NOR core before the great cleanup that had happened the past few years. I believe this creates confusion in the core today, and we should push this to vendor fixups instead. As an example, in 2023 Hsin-Yi was facing an issue because his chip was setting the wrong QER value, leading to RDCR being prevented, thus falling into a condition blindly setting a random QE bit (I strongy believe it is done like that for wrong reasons). His chip actually had RDCR support! The correct fix should have been to mark the capability in a device fixup instead of handling this in the core. Link: https://lore.kernel.org/lkml/CAJMQK-hR0eaO0b4Vd0U8_KAndLyZapqdHjVLA= oe42rWi9rdLkA@mail.gmail.com/ - SFDP parsing is over cautious. I believe BFPT_DWORD15_QER_SR2_BIT1_NO_RD is abusive (nothing states that RDCR is not supported), and BFPT_DWORD15_QER_SR2_BIT1 is also out of specification when forcing 16-bit Status writes. - SNOR_F_HAS_16BIT_SR is only imposing 16bit Status writes, whereas reads can still be 8-bit wide. - The usage of helpers verifying the writes was also spread for IMHO no really good reason. Why shouldn't we trust spi operations when it comes to Status Registers? We do not read back our page reads, so why status registers should be treated with so much care, if it's not because we are unsure of what is being done? My proposal includes a check when it comes to the QE bit (done once) but we don't need these checks otherwise. If the QE bit was written properly, there are high chances that the other register accesses will just be fine, no? Asde from my main quest, I also observed no good reason to ask the read/write status register callers to use nor->bouncebuf while the low-level helpers could do it themselves (we are talking about one or two bytes being copied). So after these observations, my proposal is the following: - Create private low level helpers that just read or write a status register. They are flexible, we can give the opcode (which varies based on the SFDP QER field) and the length (1 or 2). - Create public generic accessors which will be used to read/write sr1 and/or sr2. This is where all the cleverness shall be. The helpers use the available opcodes for a given chip in order to fullfill the request. - Provide a single generic ->quad_enable() hook which generically does all the steps mentioned above (read, modify, write, read back and verify). - Create a list of opcodes for all 6 possible situations: {read, write} {sr1, sr2, sr1 and sr2}. These opcodes are filled/cleared based on the QER field. An opcode set to 0 indicates the absence of support (there is no 0x00 opcode in SPI NOR). I tried my best to analyze the current behavior and to mimic it as much as possible, but this is a risky cleanup. However, if we go for this, it will be *much* easier in the future to handle all kind of chip variations. We won't be limited to a couple of flags anymore, but rather we'll be able to just disable a read or write capability using a single line. Known deviations: - The Atmel manufacturer driver drives non SFDP chips which by default were receiving the HAS_16B_WR flag, forcing SR2 writes all the times, but it was deliberately making single bytes writes to SR1 for its locking operations. The flag is likely wrong for them, so I removed it. - I am proposing on purpose a single quad_enable helper. It should match all the cases, with 1 identified difference which I believe is harmless: in the SR2_BIT7 case, the helper would make an extra SR1 read/write which was not done before. This entry explicitly supports reading and writing the two registers. Note: no manufacturer has been identified to actually use that entry yet. Signed-off-by: Miquel Raynal --- This is a really hard to review patch, it is big, full of changes everywhere, but I cannot really split it further. The commit log is really important, it tries to explain the steps I went through when trying to refactor the whole QE/SR handling for which I received feedback from Michael, Tudor and Sashiko. Ideally we could expect test coverage of each case: - BFPT_DWORD15_QER_NONE: Probably not needed - BFPT_DWORD15_QER_SR2_BIT1_BUGGY: Expected from Hsin-Yi (flag is being renamed _NO_1B_WR) - BFPT_DWORD15_QER_SR2_BIT1_NO_RD: Tested with a chip re-enabling RDCR in a fixup - BFPT_DWORD15_QER_SR1_BIT6: TBD - BFPT_DWORD15_QER_SR2_BIT7: TBD - BFPT_DWORD15_QER_SR2_BIT1: TBD - BFPT_DWORD15_QER_SR2_BIT1_1B: Done. There will probably be breakages on older chips. These cannot be guessed because they are not properly listed in manufacturer fixups (yet). If we want a cleanup/simplification, we will have to cope with this risk. I hope the diff stats will motivate people to have a look and report their testing. I will also eagerly monitor Sashiko's output which will probably be very useful to catch niche weird cases where these changes might break. --- Documentation/driver-api/mtd/spi-nor.rst | 2 +- drivers/mtd/spi-nor/atmel.c | 52 ++- drivers/mtd/spi-nor/core.c | 664 ++++++++++-----------------= ---- drivers/mtd/spi-nor/core.h | 59 ++- drivers/mtd/spi-nor/debugfs.c | 2 - drivers/mtd/spi-nor/gigadevice.c | 6 +- drivers/mtd/spi-nor/issi.c | 3 +- drivers/mtd/spi-nor/macronix.c | 12 +- drivers/mtd/spi-nor/micron-st.c | 4 +- drivers/mtd/spi-nor/otp.c | 16 +- drivers/mtd/spi-nor/sfdp.c | 41 +- drivers/mtd/spi-nor/spansion.c | 16 +- drivers/mtd/spi-nor/sst.c | 5 +- drivers/mtd/spi-nor/swp.c | 99 +++-- drivers/mtd/spi-nor/winbond.c | 4 +- include/linux/mtd/spi-nor.h | 4 - 16 files changed, 392 insertions(+), 597 deletions(-) diff --git a/Documentation/driver-api/mtd/spi-nor.rst b/Documentation/drive= r-api/mtd/spi-nor.rst index 747a326fb6c0..5441fa7d4f04 100644 --- a/Documentation/driver-api/mtd/spi-nor.rst +++ b/Documentation/driver-api/mtd/spi-nor.rst @@ -118,7 +118,7 @@ section, after the ``---`` marker. write size 1 page size 256 address nbytes 3 - flags HAS_LOCK | HAS_16BIT_SR | SOFT_RESET | SWP_IS_VOLATILE + flags HAS_LOCK | SOFT_RESET | SWP_IS_VOLATILE =20 opcodes read 0xeb diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c index 82c592f0a1e1..8741c0bda497 100644 --- a/drivers/mtd/spi-nor/atmel.c +++ b/drivers/mtd/spi-nor/atmel.c @@ -23,18 +23,28 @@ static int at25fs_nor_lock(struct spi_nor *nor, loff_t = ofs, u64 len) =20 static int at25fs_nor_unlock(struct spi_nor *nor, loff_t ofs, u64 len) { + /* Write 0x00 to the status register to disable write protection */ + u8 sr =3D 0; int ret; =20 /* We only support unlocking the whole flash array */ if (ofs || len !=3D nor->params->size) return -EINVAL; =20 - /* Write 0x00 to the status register to disable write protection */ - ret =3D spi_nor_write_sr_and_check(nor, 0); + ret =3D spi_nor_write_sr1(nor, &sr); if (ret) - dev_dbg(nor->dev, "unable to clear BP bits, WP# asserted?\n"); + return ret; =20 - return ret; + ret =3D spi_nor_read_sr1(nor, &sr); + if (ret) + return ret; + + if (sr) { + dev_dbg(nor->dev, "unable to clear BP bits, WP# asserted?\n"); + return -EIO; + } + + return 0; } =20 static int at25fs_nor_is_locked(struct spi_nor *nor, loff_t ofs, u64 len) @@ -50,6 +60,7 @@ static const struct spi_nor_locking_ops at25fs_nor_lockin= g_ops =3D { =20 static int at25fs_nor_late_init(struct spi_nor *nor) { + nor->params->opcodes.write_sr1 =3D SPINOR_OP_WRSR; nor->params->locking_ops =3D &at25fs_nor_locking_ops; =20 return 0; @@ -69,6 +80,7 @@ static const struct spi_nor_fixups at25fs_nor_fixups =3D { * Return: 0 on success, -error otherwise. */ static int atmel_nor_set_global_protection(struct spi_nor *nor, loff_t ofs, + u64 len, bool is_protect) { int ret; @@ -78,19 +90,24 @@ static int atmel_nor_set_global_protection(struct spi_n= or *nor, loff_t ofs, if (ofs || len !=3D nor->params->size) return -EINVAL; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1(nor, &sr); if (ret) return ret; =20 - sr =3D nor->bouncebuf[0]; - /* SRWD bit needs to be cleared, otherwise the protection doesn't change = */ if (sr & SR_SRWD) { sr &=3D ~SR_SRWD; - ret =3D spi_nor_write_sr_and_check(nor, sr); - if (ret) { - dev_dbg(nor->dev, "unable to clear SRWD bit, WP# asserted?\n"); + ret =3D spi_nor_write_sr1(nor, &sr); + if (ret) return ret; + + ret =3D spi_nor_read_sr1(nor, &sr); + if (ret) + return ret; + + if (sr & SR_SRWD) { + dev_dbg(nor->dev, "unable to clear SRWD bit, WP# asserted?\n"); + return -EIO; } } =20 @@ -108,14 +125,7 @@ static int atmel_nor_set_global_protection(struct spi_= nor *nor, loff_t ofs, sr &=3D ~ATMEL_SR_GLOBAL_PROTECT_MASK; } =20 - nor->bouncebuf[0] =3D sr; - - /* - * We cannot use the spi_nor_write_sr_and_check() because this command - * isn't really setting any bits, instead it is an pseudo command for - * "Global Unprotect" or "Global Protect" - */ - return spi_nor_write_sr(nor, nor->bouncebuf, 1); + return spi_nor_write_sr1(nor, &sr); } =20 static int atmel_nor_global_protect(struct spi_nor *nor, loff_t ofs, u64 l= en) @@ -131,16 +141,17 @@ static int atmel_nor_global_unprotect(struct spi_nor = *nor, loff_t ofs, u64 len) static int atmel_nor_is_global_protected(struct spi_nor *nor, loff_t ofs, u64 len) { + u8 sr; int ret; =20 if (ofs >=3D nor->params->size || (ofs + len) > nor->params->size) return -EINVAL; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1(nor, &sr); if (ret) return ret; =20 - return ((nor->bouncebuf[0] & ATMEL_SR_GLOBAL_PROTECT_MASK) =3D=3D ATMEL_S= R_GLOBAL_PROTECT_MASK); + return ((sr & ATMEL_SR_GLOBAL_PROTECT_MASK) =3D=3D ATMEL_SR_GLOBAL_PROTEC= T_MASK); } =20 static const struct spi_nor_locking_ops atmel_nor_global_protection_ops = =3D { @@ -151,6 +162,7 @@ static const struct spi_nor_locking_ops atmel_nor_globa= l_protection_ops =3D { =20 static int atmel_nor_global_protection_late_init(struct spi_nor *nor) { + nor->params->opcodes.write_sr1 =3D SPINOR_OP_WRSR; nor->params->locking_ops =3D &atmel_nor_global_protection_ops; =20 return 0; diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 886f3c956309..1f2a58acae1e 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -444,75 +444,6 @@ int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 = ndummy, u8 *id, return ret; } =20 -/** - * spi_nor_read_sr() - Read the Status Register. - * @nor: pointer to 'struct spi_nor'. - * @sr: pointer to a DMA-able buffer where the value of the - * Status Register will be written. Should be at least 2 byte= s. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_read_sr(struct spi_nor *nor, u8 *sr) -{ - int ret; - - if (nor->spimem) { - struct spi_mem_op op =3D SPI_NOR_RDSR_OP(sr); - - if (nor->reg_proto =3D=3D SNOR_PROTO_8_8_8_DTR) { - op.addr.nbytes =3D nor->params->rdsr_addr_nbytes; - op.dummy.nbytes =3D nor->params->rdsr_dummy; - /* - * We don't want to read only one byte in DTR mode. So, - * read 2 and then discard the second byte. - */ - op.data.nbytes =3D 2; - } - - spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); - - ret =3D spi_mem_exec_op(nor->spimem, &op); - } else { - ret =3D spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDSR, sr, - 1); - } - - if (ret) - dev_dbg(nor->dev, "error %d reading SR\n", ret); - - return ret; -} - -/** - * spi_nor_read_cr() - Read the Configuration Register using the - * SPINOR_OP_RDCR (35h) command. - * @nor: pointer to 'struct spi_nor' - * @cr: pointer to a DMA-able buffer where the value of the - * Configuration Register will be written. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_read_cr(struct spi_nor *nor, u8 *cr) -{ - int ret; - - if (nor->spimem) { - struct spi_mem_op op =3D SPI_NOR_RDCR_OP(cr); - - spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); - - ret =3D spi_mem_exec_op(nor->spimem, &op); - } else { - ret =3D spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDCR, cr, - 1); - } - - if (ret) - dev_dbg(nor->dev, "error %d reading CR\n", ret); - - return ret; -} - /** * spi_nor_set_4byte_addr_mode_en4b_ex4b() - Enter/Exit 4-byte address mode * using SPINOR_OP_EN4B/SPINOR_OP_EX4B. Typically used by @@ -618,12 +549,13 @@ int spi_nor_set_4byte_addr_mode_brwr(struct spi_nor *= nor, bool enable) int spi_nor_sr_ready(struct spi_nor *nor) { int ret; + u8 sr; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1(nor, &sr); if (ret) return ret; =20 - return !(nor->bouncebuf[0] & SR_WIP); + return !(sr & SR_WIP); } =20 /** @@ -785,34 +717,91 @@ int spi_nor_global_block_unlock(struct spi_nor *nor) } =20 /** - * spi_nor_write_sr() - Write the Status Register. + * spi_nor_read_sr_ll() - Low-level Status Registers read. * @nor: pointer to 'struct spi_nor'. - * @sr: pointer to DMA-able buffer to write to the Status Register. - * @len: number of bytes to write to the Status Register. + * @opcode: opcode for the status register read operation. + * @sr: pointer to buffer for storing the content of the status registers. + * @len: number of status registers to read (1 or 2). * * Return: 0 on success, -errno otherwise. */ -int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len) +int spi_nor_read_sr_ll(struct spi_nor *nor, u8 opcode, u8 *sr, + unsigned int len) { - int ret; + int ret, i; =20 - ret =3D spi_nor_write_enable(nor); - if (ret) - return ret; + if (len > 2) + return -EINVAL; + + for (i =3D 0; i < len; i++) + nor->bouncebuf[i] =3D 0; =20 if (nor->spimem) { - struct spi_mem_op op =3D SPI_NOR_WRSR_OP(sr, len); + struct spi_mem_op op =3D SPI_NOR_RDSR_OP(opcode, nor->bouncebuf, len); + + if (nor->reg_proto =3D=3D SNOR_PROTO_8_8_8_DTR) { + op.addr.nbytes =3D nor->params->rdsr_addr_nbytes; + op.dummy.nbytes =3D nor->params->rdsr_dummy; + /* + * We don't want to read only one byte in DTR mode. So, + * read 2 and then discard the second byte. + */ + op.data.nbytes =3D 2; + } =20 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); =20 ret =3D spi_mem_exec_op(nor->spimem, &op); } else { - ret =3D spi_nor_controller_ops_write_reg(nor, SPINOR_OP_WRSR, sr, - len); + ret =3D spi_nor_controller_ops_read_reg(nor, opcode, nor->bouncebuf, len= ); + } + + memcpy(sr, nor->bouncebuf, len); + + if (ret) + dev_dbg(nor->dev, "Error %d reading Status Registers\n", ret); + + return ret; +} + +/** + * spi_nor_write_sr_ll() - Low-level Status Registers write. + * @nor: pointer to 'struct spi_nor'. + * @opcode: opcode for the status register write operation. + * @sr: pointer to status registers buffer to write. + * @len: number of status registers to write. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_write_sr_ll(struct spi_nor *nor, u8 opcode, const u8 *s= r, + unsigned int len) +{ + int ret, i; + + if (len > 2) + return -EINVAL; + + ret =3D spi_nor_write_enable(nor); + if (ret) + return ret; + + for (i =3D 0; i < len; i++) + nor->bouncebuf[i] =3D sr[i]; + + if (nor->spimem) { + struct spi_mem_op op =3D SPI_NOR_WRSR_OP(opcode, + nor->bouncebuf, len); + + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + + ret =3D spi_mem_exec_op(nor->spimem, &op); + } else { + ret =3D spi_nor_controller_ops_write_reg(nor, opcode, + nor->bouncebuf, len); } =20 if (ret) { - dev_dbg(nor->dev, "error %d writing SR\n", ret); + dev_dbg(nor->dev, "Error %d writing Status Registers\n", ret); return ret; } =20 @@ -820,309 +809,193 @@ int spi_nor_write_sr(struct spi_nor *nor, const u8 = *sr, size_t len) } =20 /** - * spi_nor_write_sr1_and_check() - Write one byte to the Status Register 1= and - * ensure that the byte written match the received value. - * @nor: pointer to a 'struct spi_nor'. - * @sr1: byte value to be written to the Status Register. + * spi_nor_read_sr1() - Read SR1 only + * Useful for: + * - The core to offer a generic "read SR1 and SR2" capability + * - Manufacturer drivers (since they know the chip SR layout) + * - Polling the BUSY bit in the core * - * Return: 0 on success, -errno otherwise. + * @nor: the spi_nor structure + * @sr1: pointer to a valid SR1 buffer + * + * Return 0 or errno. */ -static int spi_nor_write_sr1_and_check(struct spi_nor *nor, u8 sr1) +int spi_nor_read_sr1(struct spi_nor *nor, u8 *sr1) { - int ret; - - nor->bouncebuf[0] =3D sr1; - - ret =3D spi_nor_write_sr(nor, nor->bouncebuf, 1); - if (ret) - return ret; - - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); - if (ret) - return ret; - - if (nor->bouncebuf[0] !=3D sr1) { - dev_dbg(nor->dev, "SR1: read back test failed\n"); - return -EIO; - } - - return 0; + return spi_nor_read_sr_ll(nor, nor->params->opcodes.read_sr1, sr1, 1); } =20 /** - * spi_nor_write_16bit_sr_and_check() - Write the Status Register 1 and the - * Status Register 2 in one shot. Ensure that the byte written in the Stat= us - * Register 1 match the received value, and that the 16-bit Write did not - * affect what was already in the Status Register 2. - * @nor: pointer to a 'struct spi_nor'. - * @sr1: byte value to be written to the Status Register 1. + * spi_nor_read_sr2() - Read SR2 only + * Useful for: + * - The core to offer a generic "read SR1 and SR2" capability + * - Manufacturer drivers (since they know the chip SR layout) + * - SR2 based OTP configuration * - * Return: 0 on success, -errno otherwise. + * @nor: the spi_nor structure + * @sr2: pointer to a valid SR2 buffer + * + * Return 0 or errno. */ -static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1) +int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2) +{ + struct spi_nor_flash_parameter *params =3D nor->params; + + if (!params->opcodes.read_sr2) + return -EINVAL; + + return spi_nor_read_sr_ll(nor, params->opcodes.read_sr2, sr2, 1); +} + +/** + * spi_nor_read_sr1_and_sr2() - Read SR1 then SR2 + * General purpose helper. + * + * @nor: the spi_nor structure + * @sr: pointer to a valid 2-byte array + * + * Return 0 or errno. + */ +int spi_nor_read_sr1_and_sr2(struct spi_nor *nor, u8 *sr) +{ + int ret; + + ret =3D spi_nor_read_sr1(nor, &sr[0]); + if (ret) + return ret; + + return spi_nor_read_sr2(nor, &sr[1]); +} + +/** + * spi_nor_write_sr1() - Write SR1 only + * Useful for: + * - Manufacturer drivers (since they know the chip SR layout) + * + * @nor: the spi_nor structure + * @sr1: pointer to a valid SR1 buffer + * + * Return 0 or errno. + */ +int spi_nor_write_sr1(struct spi_nor *nor, const u8 *sr1) +{ + if (WARN_ONCE(!nor->params->opcodes.write_sr1, + "Restricted helper use, write SR1 not supported")) + return -EIO; + + return spi_nor_write_sr_ll(nor, nor->params->opcodes.write_sr1, sr1, 1); +} + +/** + * spi_nor_write_sr2() - Write SR2 only + * Useful for: + * - Manufacturer drivers (since they know the chip SR layout) + * - SR2 based OTP configuration + * + * @nor: the spi_nor structure + * @sr2: pointer to a valid SR2 buffer + * + * Return 0 or errno. + */ +int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2) +{ + if (WARN_ONCE(!nor->params->opcodes.write_sr2, + "Restricted helper use, write SR2 not supported")) + return -EIO; + + return spi_nor_write_sr_ll(nor, nor->params->opcodes.write_sr2, sr2, 1); +} + +/** + * spi_nor_write_sr1_and_sr2() - Write SR1 then SR2 + * General purpose helper, always safe to call. Will expectedly ignore + * SR2 on certain chips. + * + * @nor: the spi_nor structure + * @sr: pointer to a valid 2-byte array + * + * Return 0 or errno. + */ +static int spi_nor_write_sr1_and_sr2(struct spi_nor *nor, const u8 *sr) { struct spi_nor_flash_parameter *params =3D nor->params; int ret; - u8 *sr_cr =3D nor->bouncebuf; - u8 cr_written; =20 - /* Make sure we don't overwrite the contents of Status Register 2. */ - if (!(params->flags & SNOR_F_NO_READ_CR)) { - ret =3D spi_nor_read_cr(nor, &sr_cr[1]); - if (ret) - return ret; - } else if ((spi_nor_get_protocol_width(nor->read_proto) =3D=3D 4 || - spi_nor_get_protocol_width(nor->write_proto) =3D=3D 4) && - nor->params->quad_enable) { - /* - * If the Status Register 2 Read command (35h) is not - * supported, we should at least be sure we don't - * change the value of the SR2 Quad Enable bit. - * - * When the Quad Enable method is set and the buswidth is 4, we - * can safely assume that the value of the QE bit is one, as a - * consequence of the nor->params->quad_enable() call. - * - * According to the JESD216 revB standard, BFPT DWORDS[15], - * bits 22:20, the 16-bit Write Status (01h) command is - * available just for the cases in which the QE bit is - * described in SR2 at BIT(1). - */ - sr_cr[1] =3D SR2_QUAD_EN_BIT1; - } else { - sr_cr[1] =3D 0; - } + if (params->opcodes.write_sr1_and_sr2) + return spi_nor_write_sr_ll(nor, + params->opcodes.write_sr1_and_sr2, + sr, 2); =20 - sr_cr[0] =3D sr1; - - ret =3D spi_nor_write_sr(nor, sr_cr, 2); + ret =3D spi_nor_write_sr1(nor, &sr[0]); if (ret) return ret; =20 - ret =3D spi_nor_read_sr(nor, sr_cr); - if (ret) - return ret; - - if (sr1 !=3D sr_cr[0]) { - dev_dbg(nor->dev, "SR: Read back test failed\n"); - return -EIO; - } - - if (params->flags & SNOR_F_NO_READ_CR) - return 0; - - cr_written =3D sr_cr[1]; - - ret =3D spi_nor_read_cr(nor, &sr_cr[1]); - if (ret) - return ret; - - if (cr_written !=3D sr_cr[1]) { - dev_dbg(nor->dev, "CR: read back test failed\n"); - return -EIO; - } + if (params->opcodes.write_sr2) + return spi_nor_write_sr2(nor, &sr[1]); =20 return 0; } =20 /** - * spi_nor_write_16bit_cr_and_check() - Write the Status Register 1 and the - * Configuration Register in one shot. Ensure that the byte written in the - * Configuration Register match the received value, and that the 16-bit Wr= ite - * did not affect what was already in the Status Register 1. - * @nor: pointer to a 'struct spi_nor'. - * @cr: byte value to be written to the Configuration Register. + * spi_nor_write_sr1_and_sr2_and_check() - Write SR1 then SR2, then read + * them back and verifies + * General purpose helper, always safe to call. Will expectedly ignore + * SR2 on certain chips. * - * Return: 0 on success, -errno otherwise. + * @nor: the spi_nor structure + * @sr: pointer to a valid 2-byte array + * + * Return 0 or errno. */ -int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr) +int spi_nor_write_sr1_and_sr2_and_check(struct spi_nor *nor, const u8 *sr) { + u8 tmp[2]; int ret; - u8 *sr_cr =3D nor->bouncebuf; - u8 sr_written; =20 - /* Keep the current value of the Status Register 1. */ - ret =3D spi_nor_read_sr(nor, sr_cr); + ret =3D spi_nor_write_sr1_and_sr2(nor, sr); if (ret) return ret; =20 - sr_cr[1] =3D cr; - - ret =3D spi_nor_write_sr(nor, sr_cr, 2); + ret =3D spi_nor_read_sr1_and_sr2(nor, tmp); if (ret) return ret; =20 - sr_written =3D sr_cr[0]; - - ret =3D spi_nor_read_sr(nor, sr_cr); - if (ret) - return ret; - - if (sr_written !=3D sr_cr[0]) { - dev_dbg(nor->dev, "SR: Read back test failed\n"); + if (sr[0] !=3D tmp[0] || sr[1] !=3D tmp[1]) return -EIO; - } - - if (nor->params->flags & SNOR_F_NO_READ_CR) - return 0; - - ret =3D spi_nor_read_cr(nor, &sr_cr[1]); - if (ret) - return ret; - - if (cr !=3D sr_cr[1]) { - dev_dbg(nor->dev, "CR: read back test failed\n"); - return -EIO; - } =20 return 0; } =20 /** - * spi_nor_write_16bit_sr_cr_and_check() - Write the Status Register 1 and= the - * Configuration Register in one shot. Ensure that the bytes written in bo= th - * registers match the received value. - * @nor: pointer to a 'struct spi_nor'. - * @regs: two-byte array with values to be written to the status and - * configuration registers. + * spi_nor_generic_quad_enable() - Read the status registers, + * apply the QE bit mask, + * write the status registers, + * read them back and check the content. + * + * @nor: pointer to 'struct spi_nor' * * Return: 0 on success, -errno otherwise. */ -static int spi_nor_write_16bit_sr_cr_and_check(struct spi_nor *nor, const = u8 *regs) +static int spi_nor_generic_quad_enable(struct spi_nor *nor) { - u8 written_regs[2]; + u8 *qe_mask =3D nor->params->qe_mask; + u8 sr[2] =3D {}; int ret; =20 - written_regs[0] =3D regs[0]; - written_regs[1] =3D regs[1]; - nor->bouncebuf[0] =3D regs[0]; - nor->bouncebuf[1] =3D regs[1]; - - ret =3D spi_nor_write_sr(nor, nor->bouncebuf, 2); - if (ret) - return ret; - - ret =3D spi_nor_read_sr(nor, &nor->bouncebuf[0]); - if (ret) - return ret; - - if (written_regs[0] !=3D nor->bouncebuf[0]) { - dev_dbg(nor->dev, "SR: Read back test failed\n"); - return -EIO; - } - - if (nor->params->flags & SNOR_F_NO_READ_CR) + if (!qe_mask[0] && !qe_mask[1]) return 0; =20 - ret =3D spi_nor_read_cr(nor, &nor->bouncebuf[1]); + ret =3D spi_nor_read_sr1_and_sr2(nor, sr); if (ret) return ret; =20 - if (written_regs[1] !=3D nor->bouncebuf[1]) { - dev_dbg(nor->dev, "CR: read back test failed\n"); - return -EIO; - } + if (sr[0] & qe_mask[0] || sr[1] & qe_mask[1]) + return 0; =20 - return 0; -} + sr[0] |=3D qe_mask[0]; + sr[1] |=3D qe_mask[1]; =20 -/** - * spi_nor_write_sr_and_check() - Write the Status Register 1 and ensure t= hat - * the byte written match the received value without affecting other bits = in the - * Status Register 1 and 2. - * @nor: pointer to a 'struct spi_nor'. - * @sr1: byte value to be written to the Status Register. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1) -{ - if (nor->params->flags & SNOR_F_HAS_16BIT_SR) - return spi_nor_write_16bit_sr_and_check(nor, sr1); - - return spi_nor_write_sr1_and_check(nor, sr1); -} - -/** - * spi_nor_write_sr_cr_and_check() - Write the Status Register 1 and ensur= e that - * the byte written match the received value. Same for the Control Registe= r if - * available. - * @nor: pointer to a 'struct spi_nor'. - * @regs: byte array to be written to the registers. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_write_sr_cr_and_check(struct spi_nor *nor, const u8 *regs) -{ - if (nor->params->flags & SNOR_F_HAS_16BIT_SR) - return spi_nor_write_16bit_sr_cr_and_check(nor, regs); - - return spi_nor_write_sr1_and_check(nor, regs[0]); -} - -/** - * spi_nor_write_sr2() - Write the Status Register 2 using the - * SPINOR_OP_WRSR2 (3eh) command. - * @nor: pointer to 'struct spi_nor'. - * @sr2: pointer to DMA-able buffer to write to the Status Register 2. - * - * Return: 0 on success, -errno otherwise. - */ -static int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2) -{ - int ret; - - ret =3D spi_nor_write_enable(nor); - if (ret) - return ret; - - if (nor->spimem) { - struct spi_mem_op op =3D SPI_NOR_WRSR2_OP(sr2); - - spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); - - ret =3D spi_mem_exec_op(nor->spimem, &op); - } else { - ret =3D spi_nor_controller_ops_write_reg(nor, SPINOR_OP_WRSR2, - sr2, 1); - } - - if (ret) { - dev_dbg(nor->dev, "error %d writing SR2\n", ret); - return ret; - } - - return spi_nor_wait_till_ready(nor); -} - -/** - * spi_nor_read_sr2() - Read the Status Register 2 using the - * SPINOR_OP_RDSR2 (3fh) command. - * @nor: pointer to 'struct spi_nor'. - * @sr2: pointer to DMA-able buffer where the value of the - * Status Register 2 will be written. - * - * Return: 0 on success, -errno otherwise. - */ -static int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2) -{ - int ret; - - if (nor->spimem) { - struct spi_mem_op op =3D SPI_NOR_RDSR2_OP(sr2); - - spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); - - ret =3D spi_mem_exec_op(nor->spimem, &op); - } else { - ret =3D spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDSR2, sr2, - 1); - } - - if (ret) - dev_dbg(nor->dev, "error %d reading SR2\n", ret); - - return ret; + return spi_nor_write_sr1_and_sr2_and_check(nor, sr); } =20 /** @@ -1914,106 +1787,6 @@ static int spi_nor_erase(struct mtd_info *mtd, stru= ct erase_info *instr) return ret; } =20 -/** - * spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Stat= us - * Register 1. - * @nor: pointer to a 'struct spi_nor' - * - * Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI mem= ories. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor) -{ - int ret; - - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); - if (ret) - return ret; - - if (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6) - return 0; - - nor->bouncebuf[0] |=3D SR1_QUAD_EN_BIT6; - - return spi_nor_write_sr1_and_check(nor, nor->bouncebuf[0]); -} - -/** - * spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Stat= us - * Register 2. - * @nor: pointer to a 'struct spi_nor'. - * - * Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI mem= ories. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor) -{ - int ret; - - if (nor->params->flags & SNOR_F_NO_READ_CR) - return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1); - - ret =3D spi_nor_read_cr(nor, nor->bouncebuf); - if (ret) - return ret; - - if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1) - return 0; - - nor->bouncebuf[0] |=3D SR2_QUAD_EN_BIT1; - - return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]); -} - -/** - * spi_nor_sr2_bit7_quad_enable() - set QE bit in Status Register 2. - * @nor: pointer to a 'struct spi_nor' - * - * Set the Quad Enable (QE) bit in the Status Register 2. - * - * This is one of the procedures to set the QE bit described in the SFDP - * (JESD216 rev B) specification but no manufacturer using this procedure = has - * been identified yet, hence the name of the function. - * - * Return: 0 on success, -errno otherwise. - */ -int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor) -{ - u8 *sr2 =3D nor->bouncebuf; - int ret; - u8 sr2_written; - - /* Check current Quad Enable bit value. */ - ret =3D spi_nor_read_sr2(nor, sr2); - if (ret) - return ret; - if (*sr2 & SR2_QUAD_EN_BIT7) - return 0; - - /* Update the Quad Enable bit. */ - *sr2 |=3D SR2_QUAD_EN_BIT7; - - ret =3D spi_nor_write_sr2(nor, sr2); - if (ret) - return ret; - - sr2_written =3D *sr2; - - /* Read back and check it. */ - ret =3D spi_nor_read_sr2(nor, sr2); - if (ret) - return ret; - - if (*sr2 !=3D sr2_written) { - dev_dbg(nor->dev, "SR2: Read back test failed\n"); - return -EIO; - } - - return 0; -} - static const struct spi_nor_manufacturer *manufacturers[] =3D { &spi_nor_atmel, &spi_nor_eon, @@ -2504,6 +2277,7 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32= *hwcaps) { struct spi_nor_flash_parameter *params =3D nor->params; unsigned int cap; + u8 opcode; =20 /* X-X-X modes are not supported yet, mask them all. */ *hwcaps &=3D ~SNOR_HWCAPS_X_X_X; @@ -2535,14 +2309,15 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u= 32 *hwcaps) *hwcaps &=3D ~BIT(cap); } =20 - /* Some SPI controllers might not support CR read opcode. */ - if (!(params->flags & SNOR_F_NO_READ_CR)) { - struct spi_mem_op op =3D SPI_NOR_RDCR_OP(nor->bouncebuf); + /* Some SPI controllers might not support reading SR2 */ + opcode =3D nor->params->opcodes.read_sr2; + if (opcode) { + struct spi_mem_op op =3D SPI_NOR_RDSR_OP(opcode, nor->bouncebuf, 1); =20 spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); =20 if (!spi_mem_supports_op(nor->spimem, &op)) - params->flags |=3D SNOR_F_NO_READ_CR; + nor->params->opcodes.read_sr2 =3D 0; } } =20 @@ -3057,11 +2832,14 @@ static void spi_nor_init_default_params(struct spi_= nor *nor) const struct flash_info *info =3D nor->info; struct device_node *np =3D spi_nor_get_flash_node(nor); =20 - params->quad_enable =3D spi_nor_sr2_bit1_quad_enable; - params->otp.org =3D info->otp; + /* Default to 16-bit Read/Write Status commands */ + params->opcodes.read_sr1 =3D SPINOR_OP_RDSR; + params->opcodes.read_sr2 =3D SPINOR_OP_RDCR; + params->opcodes.write_sr1_and_sr2 =3D SPINOR_OP_WRSR; + params->quad_enable =3D spi_nor_generic_quad_enable; + params->qe_mask[1] =3D BIT(1); =20 - /* Default to 16-bit Write Status (01h) Command */ - params->flags |=3D SNOR_F_HAS_16BIT_SR; + params->otp.org =3D info->otp; =20 /* Set SPI NOR sizes. */ params->writesize =3D 1; diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 4b36d99ce8f6..b8a0db02e0f1 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -37,36 +37,18 @@ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_NO_DATA) =20 -#define SPI_NOR_RDSR_OP(buf) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0), \ +#define SPI_NOR_RDSR_OP(opcode, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \ SPI_MEM_OP_NO_ADDR, \ SPI_MEM_OP_NO_DUMMY, \ - SPI_MEM_OP_DATA_IN(1, buf, 0)) + SPI_MEM_OP_DATA_IN(len, buf, 0)) =20 -#define SPI_NOR_WRSR_OP(buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0), \ +#define SPI_NOR_WRSR_OP(opcode, buf, len) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \ SPI_MEM_OP_NO_ADDR, \ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_OUT(len, buf, 0)) =20 -#define SPI_NOR_RDSR2_OP(buf) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0), \ - SPI_MEM_OP_NO_ADDR, \ - SPI_MEM_OP_NO_DUMMY, \ - SPI_MEM_OP_DATA_OUT(1, buf, 0)) - -#define SPI_NOR_WRSR2_OP(buf) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0), \ - SPI_MEM_OP_NO_ADDR, \ - SPI_MEM_OP_NO_DUMMY, \ - SPI_MEM_OP_DATA_OUT(1, buf, 0)) - -#define SPI_NOR_RDCR_OP(buf) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0), \ - SPI_MEM_OP_NO_ADDR, \ - SPI_MEM_OP_NO_DUMMY, \ - SPI_MEM_OP_DATA_IN(1, buf, 0)) - #define SPI_NOR_EN4B_EX4B_OP(enable) \ SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, 0), \ SPI_MEM_OP_NO_ADDR, \ @@ -131,8 +113,6 @@ enum spi_nor_option_flags { SNOR_F_4B_OPCODES =3D BIT(3), SNOR_F_HAS_4BAIT =3D BIT(4), SNOR_F_HAS_LOCK =3D BIT(5), - SNOR_F_HAS_16BIT_SR =3D BIT(6), - SNOR_F_NO_READ_CR =3D BIT(7), SNOR_F_HAS_SR_TB_BIT6 =3D BIT(8), SNOR_F_HAS_4BIT_BP =3D BIT(9), SNOR_F_HAS_SR_BP3_BIT6 =3D BIT(10), @@ -347,9 +327,19 @@ struct spi_nor_otp { * List of variable opcodes used by the chip. * * @die_erase: opcode for erasing a die, defaults to SPINOR_OP_CHIP_ERASE + * @read_sr1: opcode for reading SR1 alone + * @read_sr2: opcode for reading SR2 alone + * @write_sr1: opcode for writing SR1 alone + * @write_sr2: opcode for writing SR2 alone + * @write_sr1_and_sr2: opcode for writing SR1 then SR2 in one operation */ struct spi_nor_opcodes { u8 die_erase; + u8 read_sr1; + u8 read_sr2; + u8 write_sr1; + u8 write_sr2; + u8 write_sr1_and_sr2; }; =20 /** @@ -388,6 +378,7 @@ struct spi_nor_opcodes { * @otp: SPI NOR OTP info. * @set_octal_dtr: enables or disables SPI NOR octal DTR mode. * @quad_enable: enables SPI NOR quad mode. + * @qe_mask: two bytes mask used to set/clear the QE bit * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode. * @ready: (optional) flashes might use a different mechanism * than reading the status register to indicate they @@ -420,6 +411,7 @@ struct spi_nor_flash_parameter { =20 int (*set_octal_dtr)(struct spi_nor *nor, bool enable); int (*quad_enable)(struct spi_nor *nor); + u8 qe_mask[2]; int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable); int (*ready)(struct spi_nor *nor); =20 @@ -645,18 +637,17 @@ int spi_nor_wait_till_ready(struct spi_nor *nor); int spi_nor_global_block_unlock(struct spi_nor *nor); int spi_nor_prep_and_lock(struct spi_nor *nor); void spi_nor_unlock_and_unprep(struct spi_nor *nor); -int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor); -int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor); -int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor); int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id, enum spi_nor_protocol reg_proto); -int spi_nor_read_sr(struct spi_nor *nor, u8 *sr); int spi_nor_sr_ready(struct spi_nor *nor); -int spi_nor_read_cr(struct spi_nor *nor, u8 *cr); -int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len); -int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1); -int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr); -int spi_nor_write_sr_cr_and_check(struct spi_nor *nor, const u8 *regs); +int spi_nor_read_sr_ll(struct spi_nor *nor, u8 opcode, u8 *sr, + unsigned int len); +int spi_nor_read_sr1(struct spi_nor *nor, u8 *sr1); +int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2); +int spi_nor_read_sr1_and_sr2(struct spi_nor *nor, u8 *sr); +int spi_nor_write_sr1(struct spi_nor *nor, const u8 *sr1); +int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2); +int spi_nor_write_sr1_and_sr2_and_check(struct spi_nor *nor, const u8 *sr); =20 ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf); diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index 5a7372e7f802..51c0582f793a 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -18,8 +18,6 @@ static const char *const snor_f_names[] =3D { SNOR_F_NAME(4B_OPCODES), SNOR_F_NAME(HAS_4BAIT), SNOR_F_NAME(HAS_LOCK), - SNOR_F_NAME(HAS_16BIT_SR), - SNOR_F_NAME(NO_READ_CR), SNOR_F_NAME(HAS_SR_TB_BIT6), SNOR_F_NAME(HAS_4BIT_BP), SNOR_F_NAME(HAS_SR_BP3_BIT6), diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadev= ice.c index ef1edd0add70..4070a692e968 100644 --- a/drivers/mtd/spi-nor/gigadevice.c +++ b/drivers/mtd/spi-nor/gigadevice.c @@ -23,8 +23,10 @@ gd25q256_post_bfpt(struct spi_nor *nor, * GD25Q256E | SFDP_JESD216_MAJOR | SFDP_JESD216B_MINOR */ if (bfpt_header->major =3D=3D SFDP_JESD216_MAJOR && - bfpt_header->minor =3D=3D SFDP_JESD216_MINOR) - nor->params->quad_enable =3D spi_nor_sr1_bit6_quad_enable; + bfpt_header->minor =3D=3D SFDP_JESD216_MINOR) { + nor->params->qe_mask[0] =3D BIT(6); + nor->params->qe_mask[1] =3D 0; + } =20 return 0; } diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c index 18d9a00aa22e..04db42b5141e 100644 --- a/drivers/mtd/spi-nor/issi.c +++ b/drivers/mtd/spi-nor/issi.c @@ -131,7 +131,8 @@ static const struct flash_info issi_nor_parts[] =3D { =20 static void issi_nor_default_init(struct spi_nor *nor) { - nor->params->quad_enable =3D spi_nor_sr1_bit6_quad_enable; + nor->params->qe_mask[0] =3D BIT(6); + nor->params->qe_mask[1] =3D 0; } =20 static const struct spi_nor_fixups issi_fixups =3D { diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c index 9610d9e14e4c..954e7df21ff9 100644 --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c @@ -65,11 +65,12 @@ mx25l3255e_late_init_fixups(struct spi_nor *nor) =20 /* * SFDP of MX25L3255E is JESD216, which does not include the Quad - * Enable bit Requirement in BFPT. As a result, during BFPT parsing, - * the quad_enable method is not set to spi_nor_sr1_bit6_quad_enable. - * Therefore, it is necessary to correct this setting by late_init. + * Enable bit Requirement in BFPT. As a result, during BFPT parsing + * the quad_enable mask is reset. Therefore, it is necessary to + * correct this setting by late_init. */ - params->quad_enable =3D spi_nor_sr1_bit6_quad_enable; + params->qe_mask[0] =3D BIT(6); + params->qe_mask[1] =3D 0; =20 /* * In addition, MX25L3255E also supports 1-4-4 page program in 3-byte @@ -340,7 +341,8 @@ static int macronix_nor_set_octal_dtr(struct spi_nor *n= or, bool enable) =20 static void macronix_nor_default_init(struct spi_nor *nor) { - nor->params->quad_enable =3D spi_nor_sr1_bit6_quad_enable; + nor->params->qe_mask[0] =3D BIT(6); + nor->params->qe_mask[1] =3D 0; } =20 static int macronix_nor_late_init(struct spi_nor *nor) diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-s= t.c index 3c89bd9b575c..21d0ceac1ed7 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -229,7 +229,7 @@ static int mt25qu512a_post_bfpt_fixup(struct spi_nor *n= or, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt) { - nor->params->flags &=3D ~SNOR_F_HAS_16BIT_SR; + nor->params->opcodes.write_sr1 =3D 0; return 0; } =20 @@ -633,7 +633,7 @@ static int micron_st_nor_ready(struct spi_nor *nor) static void micron_st_nor_default_init(struct spi_nor *nor) { nor->params->flags |=3D SNOR_F_HAS_LOCK; - nor->params->flags &=3D ~SNOR_F_HAS_16BIT_SR; + nor->params->opcodes.write_sr1 =3D 0; nor->params->quad_enable =3D NULL; } =20 diff --git a/drivers/mtd/spi-nor/otp.c b/drivers/mtd/spi-nor/otp.c index 7d0b145d78d8..1eeb33a20091 100644 --- a/drivers/mtd/spi-nor/otp.c +++ b/drivers/mtd/spi-nor/otp.c @@ -175,24 +175,24 @@ static int spi_nor_otp_lock_bit_cr(unsigned int regio= n) */ int spi_nor_otp_lock_sr2(struct spi_nor *nor, unsigned int region) { - u8 *cr =3D nor->bouncebuf; int ret, lock_bit; + u8 sr[2]; =20 lock_bit =3D spi_nor_otp_lock_bit_cr(region); if (lock_bit < 0) return lock_bit; =20 - ret =3D spi_nor_read_cr(nor, cr); + ret =3D spi_nor_read_sr1_and_sr2(nor, sr); if (ret) return ret; =20 /* no need to write the register if region is already locked */ - if (cr[0] & lock_bit) + if (sr[1] & lock_bit) return 0; =20 - cr[0] |=3D lock_bit; + sr[1] |=3D lock_bit; =20 - return spi_nor_write_16bit_cr_and_check(nor, cr[0]); + return spi_nor_write_sr1_and_sr2_and_check(nor, sr); } =20 /** @@ -207,18 +207,18 @@ int spi_nor_otp_lock_sr2(struct spi_nor *nor, unsigne= d int region) */ int spi_nor_otp_is_locked_sr2(struct spi_nor *nor, unsigned int region) { - u8 *cr =3D nor->bouncebuf; int ret, lock_bit; + u8 sr2; =20 lock_bit =3D spi_nor_otp_lock_bit_cr(region); if (lock_bit < 0) return lock_bit; =20 - ret =3D spi_nor_read_cr(nor, cr); + ret =3D spi_nor_read_sr2(nor, &sr2); if (ret) return ret; =20 - return cr[0] & lock_bit; + return sr2 & lock_bit; } =20 static loff_t spi_nor_otp_region_start(const struct spi_nor *nor, unsigned= int region) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index ab57fa60f718..20156914e254 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -592,10 +592,21 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, val >>=3D BFPT_DWORD11_PAGE_SIZE_SHIFT; params->page_size =3D 1U << val; =20 + /* + * The standard declares various read and write status methods, some of + * them will be overloaded based on the QER field. + */ + params->opcodes.read_sr1 =3D SPINOR_OP_RDSR; + params->opcodes.read_sr2 =3D SPINOR_OP_RDCR; + params->opcodes.write_sr1 =3D SPINOR_OP_WRSR; + params->opcodes.write_sr1_and_sr2 =3D SPINOR_OP_WRSR; + + params->qe_mask[0] =3D 0; + params->qe_mask[1] =3D 0; + /* Quad Enable Requirements. */ switch (bfpt.dwords[SFDP_DWORD(15)] & BFPT_DWORD15_QER_MASK) { case BFPT_DWORD15_QER_NONE: - params->quad_enable =3D NULL; break; =20 case BFPT_DWORD15_QER_SR2_BIT1_NO_1B_WR: @@ -603,23 +614,28 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, * Writing only one byte to the Status Register has the * side-effect of clearing Status Register 2. */ + fallthrough; case BFPT_DWORD15_QER_SR2_BIT1_NO_RD: /* * Read Configuration Register (35h) instruction is not - * supported. + * supported. 16-bit writes expected. */ - params->flags |=3D SNOR_F_HAS_16BIT_SR | SNOR_F_NO_READ_CR; - params->quad_enable =3D spi_nor_sr2_bit1_quad_enable; + params->opcodes.read_sr2 =3D 0; + params->opcodes.write_sr1 =3D 0; + params->qe_mask[1] =3D BIT(1); break; =20 case BFPT_DWORD15_QER_SR1_BIT6: - params->flags &=3D ~SNOR_F_HAS_16BIT_SR; - params->quad_enable =3D spi_nor_sr1_bit6_quad_enable; + params->opcodes.read_sr2 =3D 0; + params->opcodes.write_sr1_and_sr2 =3D 0; + params->qe_mask[0] =3D BIT(6); break; =20 case BFPT_DWORD15_QER_SR2_BIT7: - params->flags &=3D ~SNOR_F_HAS_16BIT_SR; - params->quad_enable =3D spi_nor_sr2_bit7_quad_enable; + params->opcodes.read_sr2 =3D SPINOR_OP_RDSR2; + params->opcodes.write_sr1_and_sr2 =3D 0; + params->opcodes.write_sr2 =3D SPINOR_OP_WRSR2; + params->qe_mask[1] =3D BIT(7); break; =20 case BFPT_DWORD15_QER_SR2_BIT1: @@ -629,9 +645,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, * Register 2, so let's be cautious and keep the default * assumption of a 16-bit Write Status (01h) command. */ - params->flags |=3D SNOR_F_HAS_16BIT_SR; - - params->quad_enable =3D spi_nor_sr2_bit1_quad_enable; + params->opcodes.write_sr1 =3D 0; + params->qe_mask[1] =3D BIT(1); break; =20 default: @@ -639,6 +654,10 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, break; } =20 + /* opcodes sanity check */ + WARN_ON(!params->opcodes.read_sr1 || + (!params->opcodes.write_sr1 && !params->opcodes.write_sr1_and_sr2)); + dword =3D bfpt.dwords[SFDP_DWORD(16)] & BFPT_DWORD16_4B_ADDR_MODE_MASK; if (SFDP_MASK_CHECK(dword, BFPT_DWORD16_4B_ADDR_MODE_BRWR)) params->set_4byte_addr_mode =3D spi_nor_set_4byte_addr_mode_brwr; diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c index d29a901900f8..ce2e233108c4 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -399,8 +399,9 @@ static int cypress_nor_determine_addr_mode_by_sr1(struc= t spi_nor *nor, nor->bouncebuf); bool is3byte, is4byte; int ret; + u8 sr; =20 - ret =3D spi_nor_read_sr(nor, &nor->bouncebuf[1]); + ret =3D spi_nor_read_sr1(nor, &sr); if (ret) return ret; =20 @@ -408,7 +409,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struc= t spi_nor *nor, if (ret) return ret; =20 - is3byte =3D (nor->bouncebuf[0] =3D=3D nor->bouncebuf[1]); + is3byte =3D (nor->bouncebuf[0] =3D=3D sr); =20 op =3D (struct spi_mem_op) CYPRESS_NOR_RD_ANY_REG_OP(4, SPINOR_REG_CYPRESS_STR1V, 0, @@ -417,7 +418,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struc= t spi_nor *nor, if (ret) return ret; =20 - is4byte =3D (nor->bouncebuf[0] =3D=3D nor->bouncebuf[1]); + is4byte =3D (nor->bouncebuf[0] =3D=3D sr); =20 if (is3byte =3D=3D is4byte) return -EIO; @@ -1105,13 +1106,14 @@ static const struct flash_info spansion_nor_parts[]= =3D { static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor) { int ret; + u8 sr; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1(nor, &sr); if (ret) return ret; =20 - if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) { - if (nor->bouncebuf[0] & SR_E_ERR) + if (sr & (SR_E_ERR | SR_P_ERR)) { + if (sr & SR_E_ERR) dev_err(nor->dev, "Erase Error occurred\n"); else dev_err(nor->dev, "Programming Error occurred\n"); @@ -1131,7 +1133,7 @@ static int spansion_nor_sr_ready_and_clear(struct spi= _nor *nor) return -EIO; } =20 - return !(nor->bouncebuf[0] & SR_WIP); + return !(sr & SR_WIP); } =20 static int spansion_nor_late_init(struct spi_nor *nor) diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c index db02c14ba16f..77a0bc41d4e5 100644 --- a/drivers/mtd/spi-nor/sst.c +++ b/drivers/mtd/spi-nor/sst.c @@ -21,16 +21,17 @@ static int sst26vf_nor_lock(struct spi_nor *nor, loff_t= ofs, u64 len) static int sst26vf_nor_unlock(struct spi_nor *nor, loff_t ofs, u64 len) { int ret; + u8 cr; =20 /* We only support unlocking the entire flash array. */ if (ofs !=3D 0 || len !=3D nor->params->size) return -EINVAL; =20 - ret =3D spi_nor_read_cr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr2(nor, &cr); if (ret) return ret; =20 - if (!(nor->bouncebuf[0] & SST26VF_CR_BPNV)) { + if (!(cr & SST26VF_CR_BPNV)) { dev_dbg(nor->dev, "Any block has been permanently locked\n"); return -EINVAL; } diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c index 62720045a9ab..7e667e4ca84d 100644 --- a/drivers/mtd/spi-nor/swp.c +++ b/drivers/mtd/spi-nor/swp.c @@ -41,7 +41,7 @@ static u8 spi_nor_get_sr_cmp_mask(struct spi_nor *nor) { struct spi_nor_flash_parameter *params =3D nor->params; =20 - if (!(params->flags & SNOR_F_NO_READ_CR) && + if (params->opcodes.read_sr2 && params->flags & SNOR_F_HAS_SR2_CMP_BIT6) return SR2_CMP_BIT6; else @@ -201,13 +201,51 @@ static int spi_nor_build_sr(struct spi_nor *nor, cons= t u8 *old_sr, u8 *new_sr, return 0; } =20 +/* + * Make sure we do our best to guess SR2. This has historically only be ne= eded + * for swp.c, so let's keep this extra carefulness in this file. + */ +static int spi_nor_read_sr2_careful(struct spi_nor *nor, u8 *sr2) +{ + struct spi_nor_flash_parameter *params =3D nor->params; + int ret; + + if (params->opcodes.read_sr2) { + ret =3D spi_nor_read_sr_ll(nor, params->opcodes.read_sr2, sr2, 1); + if (ret) + return ret; + } else if ((spi_nor_get_protocol_width(nor->read_proto) =3D=3D 4 || + spi_nor_get_protocol_width(nor->write_proto) =3D=3D 4) && + nor->params->quad_enable) { + /* + * Make sure the QE bit is persistently kept. qe_mask[1] will be + * 0 if the QE bit is in SR1. + */ + *sr2 =3D params->qe_mask[1]; + } else { + return 0; + } + + return 0; +} + +static int spi_nor_read_sr1_and_sr2_careful(struct spi_nor *nor, u8 *sr) +{ + int ret; + + ret =3D spi_nor_read_sr1(nor, &sr[0]); + if (ret) + return ret; + + return spi_nor_read_sr2_careful(nor, &sr[1]); +} + /* * Keep a local cache containing all lock-related bits for debugfs use onl= y. * This way, debugfs never needs to access the flash directly. */ void spi_nor_cache_sr_lock_bits(struct spi_nor *nor, u8 *sr) { - struct spi_nor_flash_parameter *params =3D nor->params; u8 bp_mask =3D spi_nor_get_sr_bp_mask(nor); u8 tb_mask =3D spi_nor_get_sr_tb_mask(nor); u8 cmp_mask =3D spi_nor_get_sr_cmp_mask(nor); @@ -215,17 +253,9 @@ void spi_nor_cache_sr_lock_bits(struct spi_nor *nor, u= 8 *sr) =20 =20 if (!sr) { - if (spi_nor_read_sr(nor, nor->bouncebuf)) + if (spi_nor_read_sr1_and_sr2_careful(nor, sr_cr)) return; =20 - sr_cr[0] =3D nor->bouncebuf[0]; - - if (!(params->flags & SNOR_F_NO_READ_CR)) { - if (spi_nor_read_cr(nor, nor->bouncebuf)) - return; - } - - sr_cr[1] =3D nor->bouncebuf[0]; sr =3D sr_cr; } =20 @@ -282,20 +312,10 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_= t ofs, u64 len) int ret; u8 pow; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1_and_sr2_careful(nor, status_old); if (ret) return ret; =20 - status_old[0] =3D nor->bouncebuf[0]; - - if (!(params->flags & SNOR_F_NO_READ_CR)) { - ret =3D spi_nor_read_cr(nor, nor->bouncebuf); - if (ret) - return ret; - - status_old[1] =3D nor->bouncebuf[0]; - } - /* If nothing in our range is unlocked, we don't need to do anything */ if (spi_nor_is_locked_sr(nor, ofs, len, status_old)) return 0; @@ -387,10 +407,7 @@ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t= ofs, u64 len) (ofs_old < ofs_new || (ofs_new + len_new) < (ofs_old + len_old))) return -EINVAL; =20 - if (params->flags & SNOR_F_NO_READ_CR) - ret =3D spi_nor_write_sr_and_check(nor, best_status_new[0]); - else - ret =3D spi_nor_write_sr_cr_and_check(nor, best_status_new); + ret =3D spi_nor_write_sr1_and_sr2_and_check(nor, best_status_new); if (ret) return ret; =20 @@ -419,20 +436,10 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, lof= f_t ofs, u64 len) int ret; u8 pow; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1_and_sr2_careful(nor, status_old); if (ret) return ret; =20 - status_old[0] =3D nor->bouncebuf[0]; - - if (!(params->flags & SNOR_F_NO_READ_CR)) { - ret =3D spi_nor_read_cr(nor, nor->bouncebuf); - if (ret) - return ret; - - status_old[1] =3D nor->bouncebuf[0]; - } - /* If nothing in our range is locked, we don't need to do anything */ if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old)) return 0; @@ -522,10 +529,7 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, loff= _t ofs, u64 len) (ofs_new < ofs_old || (ofs_old + len_old) < (ofs_new + len_new))) return -EINVAL; =20 - if (params->flags & SNOR_F_NO_READ_CR) - ret =3D spi_nor_write_sr_and_check(nor, best_status_new[0]); - else - ret =3D spi_nor_write_sr_cr_and_check(nor, best_status_new); + ret =3D spi_nor_write_sr1_and_sr2_and_check(nor, best_status_new); if (ret) return ret; =20 @@ -543,24 +547,13 @@ static int spi_nor_sr_unlock(struct spi_nor *nor, lof= f_t ofs, u64 len) */ static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, u64 len) { - struct spi_nor_flash_parameter *params =3D nor->params; u8 sr_cr[2] =3D {}; int ret; =20 - ret =3D spi_nor_read_sr(nor, nor->bouncebuf); + ret =3D spi_nor_read_sr1_and_sr2_careful(nor, sr_cr); if (ret) return ret; =20 - sr_cr[0] =3D nor->bouncebuf[0]; - - if (!(params->flags & SNOR_F_NO_READ_CR)) { - ret =3D spi_nor_read_cr(nor, nor->bouncebuf); - if (ret) - return ret; - - sr_cr[1] =3D nor->bouncebuf[0]; - } - return spi_nor_is_locked_sr(nor, ofs, len, sr_cr); } =20 diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index f59587b859a9..df4688c637a2 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -520,12 +520,12 @@ static int winbond_nor_late_init(struct spi_nor *nor) * been to declare CR reads as unsupported, whereas the Jedec * specification doesn't clearly state that. In practice, all these * chips do support reading back the CR, which is needed for SWP support, - * so make sure that capability remains enabled (needed for SWP). + * so make sure that capability remains enabled. * In practice, only exclude the old W25X family (JEDEC ID: EF 30 xx) * which actually does not support this feature. */ if (nor->id[1] > 0x30) - nor->params->flags &=3D ~SNOR_F_NO_READ_CR; + params->opcodes.read_sr2 =3D SPINOR_OP_RDCR; =20 /* * Winbond has reused many IDs, up to four times at this diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 099c5016b485..a901ddfac405 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -113,20 +113,16 @@ #define SR_E_ERR BIT(5) #define SR_P_ERR BIT(6) =20 -#define SR1_QUAD_EN_BIT6 BIT(6) - #define SR_BP_SHIFT 2 =20 /* Enhanced Volatile Configuration Register bits */ #define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ =20 /* Status Register 2 bits. */ -#define SR2_QUAD_EN_BIT1 BIT(1) #define SR2_LB1 BIT(3) /* Security Register Lock Bit 1 */ #define SR2_LB2 BIT(4) /* Security Register Lock Bit 2 */ #define SR2_LB3 BIT(5) /* Security Register Lock Bit 3 */ #define SR2_CMP_BIT6 BIT(6) -#define SR2_QUAD_EN_BIT7 BIT(7) =20 /* Supported SPI protocols */ #define SNOR_PROTO_INST_MASK GENMASK(23, 16) --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4490B51C344; Fri, 4 Sep 2026 18:13:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545603; cv=none; b=Lh9SzOforfzNfx0toVlSjZZG8Xlh/Hsp5UbNK/rwwOXzeDZSKIF0Jor2GIavhyqW67wbZFxSI7lXO+hM/XjO4KQ88MNPh3MCUF+ItMZ9hEuoDEu+P1i+lgCowtCN/39VfTbfBjnpxpNBs9MJ5XfQgxbZTxzSfHRWtSe3GVFBq2o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545603; c=relaxed/simple; bh=Cx90LmcZjOdDyZXkcegzQNj5f17y4JENdDvZUnOO1/4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=l05KnEbhtO6Mw6iddS/Ww7s/bpqDxl8TxYEttpAMH4F156lc7LwCDP775O2vgJA7p3G0InbyebydhfQNrCz9Z21GP4AyRbWSxwO2Sbqla+0JzX5XS4hfx/OvrNXbC5pTC3TTyXh8Yb+hrPfAgZ6khISvuCXoZdjklkIZcyRU/m8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=ZN24nX9r; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ZN24nX9r" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id C75824E41523; Fri, 4 Sep 2026 18:13:19 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 9B8746057F; Fri, 4 Sep 2026 18:13:19 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E7AA811C79351; Fri, 4 Sep 2026 20:13:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545598; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Nqp2rAsZbBi3yuJ+oYFg/H+DOQXz2fdcMr31I5bTzJ8=; b=ZN24nX9rb8sAqbrENBPPkEzGfmHX3WoAv221OJhyM3Jijj7/nN71ZBxR/NoB82JVCEUevI UpqejHIgP8uWCKr5knymuafexYhGkwIrvvZe/Mt9y54PAohwydBFl+W1JZKm7VcOiVNcwd YZXmvJYKMmXSiXw789two+rYSPqc218goti6BpQRmyviAo+abaZNqYM3pg8pvI990M0oUG 6D5JCfBWLliCl8ZVMWG7SeMk3vNY+cGYJ0Hct1ttK5304CsoSnPkNe1ksosGWgXFZKeg0V U8bTDox4VcT/aVZklu373zKz3tjY2ABu2MySVxkKqVQG6jah3Ja0PHeTBBLhwQ== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:41 +0200 Subject: [PATCH v5 04/25] mtd: spi-nor: Add support for the new JESD216 rev F QER field Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-4-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Revision F of the JEDEC JESD216 standard includes yet another supported setting in the QER 3-bit bitfield: 110b. This setting implies that the QE bit is bit 1 of SR2 (which is an already supported case) but this time it makes it very clear that both reading and writing to SR2 is supported, but not with the usual opcodes. The write operation uses an alternate WRSR2 opcode: 0x31 (instead of 0x3E) and both the reads and writes manipulate a single register at a time. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/sfdp.c | 6 ++++++ drivers/mtd/spi-nor/sfdp.h | 8 ++++++++ include/linux/mtd/spi-nor.h | 1 + 3 files changed, 15 insertions(+) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 20156914e254..23c11fbc68c3 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -649,6 +649,12 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, params->qe_mask[1] =3D BIT(1); break; =20 + case BFPT_DWORD15_QER_SR2_BIT1_1B: + params->qe_mask[1] =3D BIT(1); + params->opcodes.write_sr1_and_sr2 =3D 0; + params->opcodes.write_sr2 =3D SPINOR_OP_WRSR2_ALT; + break; + default: dev_dbg(nor->dev, "BFPT QER reserved value used\n"); break; diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h index d976c6c9a4ad..e8ed814c6530 100644 --- a/drivers/mtd/spi-nor/sfdp.h +++ b/drivers/mtd/spi-nor/sfdp.h @@ -12,6 +12,7 @@ #define SFDP_JESD216_MINOR 0 #define SFDP_JESD216A_MINOR 5 #define SFDP_JESD216B_MINOR 6 +#define SFDP_JESD216F_MINOR 10 =20 /* SFDP DWORDS are indexed from 1 but C arrays are indexed from 0. */ #define SFDP_DWORD(i) ((i) - 1) @@ -81,6 +82,12 @@ struct sfdp_bfpt { * instruction 35h. QE is set via Write Status instruction 01h with * two data bytes where bit 1 of the second byte is one. * [...] + * (from JESD216 rev F) + * - 110b: QE is bit 1 of status register 2. Status register 1 is read usi= ng + * Read Status instruction 05h. Status register2 is read using + * instruction 35h, and status register 3 is read using instructio= n 15h. + * QE is set via Write Status Register instruction 31h with one da= ta + * byte. */ #define BFPT_DWORD15_QER_MASK GENMASK(22, 20) #define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */ @@ -89,6 +96,7 @@ struct sfdp_bfpt { #define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20) #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */ +#define BFPT_DWORD15_QER_SR2_BIT1_1B (0x6UL << 20) /* Winbond */ =20 #define BFPT_DWORD16_EN4B_MASK GENMASK(31, 24) #define BFPT_DWORD16_EN4B_ALWAYS_4B BIT(30) diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index a901ddfac405..539eb514588c 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -25,6 +25,7 @@ #define SPINOR_OP_WRSR 0x01 /* Write status register 1 */ #define SPINOR_OP_RDSR2 0x3f /* Read status register 2 */ #define SPINOR_OP_WRSR2 0x3e /* Write status register 2 */ +#define SPINOR_OP_WRSR2_ALT 0x31 /* Write status register 2 (alternative) = */ #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ #define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */ --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9436151C33C; Fri, 4 Sep 2026 18:13:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545606; cv=none; b=uK2KlOHNdaYTOtu13wHchUdn7LGP7RUygDWMW4hA9/IFcONCidirpbjE1Nj2R3Uu0HuGkKVnEduYDPTdiuHcVvG4lDuiTGU3Cb0zjlZyBv9joni1HsyfxJCrBPDGoWSGB6YXipRC/t3zkY7cYuZep5D3IBD4TjtQd7ggLcoP57w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545606; c=relaxed/simple; bh=pWQ+tpdrnpoRdLpfkHUphrTxvawh0UQIx1E5fKD7hkQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y5gtWXBv2LWdyKTt0b+CenTDc7ShWkq6vFoZQm3TnaJNfuZ0gNPSijyd713xUF4//PIs8AhufEo12bGgbsWhwM4gFx5m8RyCBhTIblambLnO2R/FsT0/q6OdDoRJt0GTFVBjzfbTGOVkjwtaKkDg1Y+qvGSDJ8s93fElzI1h7C4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=XXy7kRDd; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="XXy7kRDd" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 15C174E41521; Fri, 4 Sep 2026 18:13:22 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id DEECB6057F; Fri, 4 Sep 2026 18:13:21 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 08EAF11C78158; Fri, 4 Sep 2026 20:13:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545600; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=DoJhcIuLmh6+sKg9z8bWeXpiDy/4jMYORUyQ4GnfyQc=; b=XXy7kRDdZ51ij+7oMP1JnHSomUw5oVZNxAA92gQavqOK+x+evtmcFt+oN3osUONZIoVyO5 fPAIrh+tjqvQ/x0lf98ZDodgedC1Tmf+X73X+zJHEhjhD4XPv9asmOu7G86frqupKMWoFo v3WLJpVIQEpHri19Qvxoh5jNRzO9wy7JDmEylyWqTXauu0p8oYeKkk3K6XVlSgFeyXBaHx 9YKHdAfUl54QIKy+H5SwTz2lJOnUT20G4irwBVlg5cEwBXnS2eN7x8xliui6sAObzR4OF6 +7Icr1ZbI9uA6uDbIsRlUmyKwvyfZdLpazhTYlBVDzAf6Zwr/Uk6NQ9b592BNw== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:42 +0200 Subject: [PATCH v5 05/25] mtd: spi-nor: Create the concept of fixup table with match function Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-5-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Manufacturer ID tables increase and fixup() hooks proliferate. Having one possible structure per chip was fine until the fixups started being more and more common and needed, to some extend due to ID reuses. Mixing fixups and chips becomes hard and requires extra helpers to sort which ones are needed for a given chip, which every time this happens requires a lot of rework. Replace the two-level fixup association (a manufacturer wide hook and a per flash_info hook) with a per-manufacturer list of fixups that can be looked up by flash ID and/or match function. The match logic works as follows: - If there is an ID, it must match - If there is a match function, it must match (cumulative) - If there is no identifier (no ID nor any match function), it's a catch-all entry typically used for flagging manufacturer fixups. Suggested-by: Michael Walle Tested-by: Takahiro Kuwano Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/atmel.c | 23 +++++++----- drivers/mtd/spi-nor/core.c | 59 ++++++++++++++++++++++-------- drivers/mtd/spi-nor/core.h | 23 ++++++++++-- drivers/mtd/spi-nor/everspin.c | 7 +++- drivers/mtd/spi-nor/gigadevice.c | 7 +++- drivers/mtd/spi-nor/issi.c | 22 ++++++++--- drivers/mtd/spi-nor/macronix.c | 25 ++++++++----- drivers/mtd/spi-nor/micron-st.c | 43 ++++++++++++++++------ drivers/mtd/spi-nor/sfdp.c | 79 ++++++++++++++++++++++++++----------= ---- drivers/mtd/spi-nor/spansion.c | 41 ++++++++++++--------- drivers/mtd/spi-nor/sst.c | 11 ++++-- drivers/mtd/spi-nor/winbond.c | 17 ++++++--- 12 files changed, 248 insertions(+), 109 deletions(-) diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c index 8741c0bda497..bccc702a2c4a 100644 --- a/drivers/mtd/spi-nor/atmel.c +++ b/drivers/mtd/spi-nor/atmel.c @@ -194,47 +194,40 @@ static const struct flash_info atmel_nor_parts[] =3D { .size =3D SZ_512K, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &atmel_nor_global_protection_fixups, }, { .id =3D SNOR_ID(0x1f, 0x45, 0x01), .name =3D "at26df081a", .size =3D SZ_1M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &atmel_nor_global_protection_fixups }, { .id =3D SNOR_ID(0x1f, 0x46, 0x01), .name =3D "at26df161a", .size =3D SZ_2M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &atmel_nor_global_protection_fixups }, { .id =3D SNOR_ID(0x1f, 0x47, 0x00), .name =3D "at25df321", .size =3D SZ_4M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &atmel_nor_global_protection_fixups }, { .id =3D SNOR_ID(0x1f, 0x47, 0x01), .name =3D "at25df321a", .size =3D SZ_4M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &atmel_nor_global_protection_fixups }, { .id =3D SNOR_ID(0x1f, 0x47, 0x08), .name =3D "at25ff321a", .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, - .fixups =3D &atmel_nor_global_protection_fixups }, { .id =3D SNOR_ID(0x1f, 0x48, 0x00), .name =3D "at25df641", .size =3D SZ_8M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &atmel_nor_global_protection_fixups }, { .id =3D SNOR_ID(0x1f, 0x66, 0x01), .name =3D "at25fs010", @@ -242,14 +235,12 @@ static const struct flash_info atmel_nor_parts[] =3D { .size =3D SZ_128K, .flags =3D SPI_NOR_HAS_LOCK, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &at25fs_nor_fixups }, { .id =3D SNOR_ID(0x1f, 0x66, 0x04), .name =3D "at25fs040", .size =3D SZ_512K, .flags =3D SPI_NOR_HAS_LOCK, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &at25fs_nor_fixups }, { .id =3D SNOR_ID(0x1f, 0x87, 0x01), .size =3D SZ_4M, @@ -257,8 +248,22 @@ static const struct flash_info atmel_nor_parts[] =3D { }, }; =20 +static const struct spi_nor_fixup atmel_fixups[] =3D { + { .id =3D SNOR_ID(0x1f, 0x44, 0x01), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x45, 0x01), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x46, 0x01), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x47, 0x00), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x47, 0x01), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x47, 0x08), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x48, 0x00), .fixups =3D &atmel_nor_global_protec= tion_fixups }, + { .id =3D SNOR_ID(0x1f, 0x66, 0x01), .fixups =3D &at25fs_nor_fixups }, + { .id =3D SNOR_ID(0x1f, 0x66, 0x04), .fixups =3D &at25fs_nor_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_atmel =3D { .name =3D "atmel", .parts =3D atmel_nor_parts, .nparts =3D ARRAY_SIZE(atmel_nor_parts), + .fixups =3D atmel_fixups, + .nfixups =3D ARRAY_SIZE(atmel_fixups), }; diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 1f2a58acae1e..322683738ef1 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2618,6 +2618,26 @@ static int spi_nor_setup(struct spi_nor *nor, return spi_nor_set_addr_nbytes(nor); } =20 +bool spi_nor_fixup_match(const struct spi_nor *nor, + const struct spi_nor_fixup *fixup) +{ + const struct spi_nor_id *id =3D nor->info ? nor->info->id : NULL; + + /* Filter by ID first, if available */ + if (fixup->id) { + if (!id || fixup->id->len > id->len || + memcmp(id->bytes, fixup->id->bytes, fixup->id->len)) + return false; + } + + /* Further filter with the match callback, if provided */ + if (fixup->match) + return fixup->match(nor); + + /* Either there was an ID and it matched, or it is a catch-all entry */ + return true; +} + /** * spi_nor_manufacturer_init_params() - Initialize the flash's parameters = and * settings based on MFR register and ->default_init() hook. @@ -2625,12 +2645,19 @@ static int spi_nor_setup(struct spi_nor *nor, */ static void spi_nor_manufacturer_init_params(struct spi_nor *nor) { - if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->default_init) - nor->manufacturer->fixups->default_init(nor); + const struct spi_nor_fixup *fixups; + unsigned int i; =20 - if (nor->info->fixups && nor->info->fixups->default_init) - nor->info->fixups->default_init(nor); + if (!nor->manufacturer || !nor->manufacturer->fixups) + return; + + fixups =3D nor->manufacturer->fixups; + + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (fixups[i].fixups->default_init && + spi_nor_fixup_match(nor, &fixups[i])) + fixups[i].fixups->default_init(nor); + } } =20 /** @@ -2780,22 +2807,24 @@ static void spi_nor_init_fixup_flags(struct spi_nor= *nor) static int spi_nor_late_init_params(struct spi_nor *nor) { struct spi_nor_flash_parameter *params =3D nor->params; + const struct spi_nor_fixup *fixups; + unsigned int i; int ret; =20 /* Needed by some late_init hooks */ spi_nor_init_flags(nor); =20 - if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->late_init) { - ret =3D nor->manufacturer->fixups->late_init(nor); - if (ret) - return ret; - } + if (nor->manufacturer && nor->manufacturer->fixups) { + fixups =3D nor->manufacturer->fixups; =20 - if (nor->info->fixups && nor->info->fixups->late_init) { - ret =3D nor->info->fixups->late_init(nor); - if (ret) - return ret; + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (fixups[i].fixups->late_init && + spi_nor_fixup_match(nor, &fixups[i])) { + ret =3D fixups[i].fixups->late_init(nor); + if (ret) + return ret; + } + } } =20 if (!nor->params->opcodes.die_erase) diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index b8a0db02e0f1..28069f62429c 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -452,6 +452,19 @@ struct spi_nor_fixups { int (*late_init)(struct spi_nor *nor); }; =20 +/** + * struct spi_nor_fixup - SPI NOR fixup registration. + * @id: (optional) flash ID this fixup applies to, may only match the + * ID prefix, eg. just the first few bytes to match a whole family + * @match: (optional) custom match function (can be used together with @id) + * @fixups: the fixup hooks to apply when this entry matches + */ +struct spi_nor_fixup { + const struct spi_nor_id *id; + bool (*match)(const struct spi_nor *nor); + const struct spi_nor_fixups *fixups; +}; + /** * struct spi_nor_id - SPI NOR flash ID. * @@ -564,7 +577,6 @@ struct flash_info { u8 mfr_flags; =20 const struct spi_nor_otp_organization *otp; - const struct spi_nor_fixups *fixups; }; =20 #define SNOR_ID(...) \ @@ -586,13 +598,16 @@ struct flash_info { * @name: manufacturer name * @parts: array of parts supported by this manufacturer * @nparts: number of entries in the parts array - * @fixups: hooks called at various points in time during spi_nor_scan() + * @fixups: list of fixups, each matched by ID (or a custom match function= ), + * applied to any part of this manufacturer. + * @nfixups: number of entries in the fixups array */ struct spi_nor_manufacturer { const char *name; const struct flash_info *parts; unsigned int nparts; - const struct spi_nor_fixups *fixups; + const struct spi_nor_fixup *fixups; + unsigned int nfixups; }; =20 /** @@ -623,6 +638,8 @@ extern const struct spi_nor_manufacturer spi_nor_xmc; =20 extern const struct attribute_group *spi_nor_sysfs_groups[]; =20 +bool spi_nor_fixup_match(const struct spi_nor *nor, + const struct spi_nor_fixup *fixup); void spi_nor_spimem_setup_op(const struct spi_nor *nor, struct spi_mem_op *op, const enum spi_nor_protocol proto); diff --git a/drivers/mtd/spi-nor/everspin.c b/drivers/mtd/spi-nor/everspin.c index add37104d673..864dffba0e9c 100644 --- a/drivers/mtd/spi-nor/everspin.c +++ b/drivers/mtd/spi-nor/everspin.c @@ -44,9 +44,14 @@ static const struct spi_nor_fixups everspin_nor_fixups = =3D { .default_init =3D everspin_nor_default_init, }; =20 +static const struct spi_nor_fixup everspin_fixups[] =3D { + { .fixups =3D &everspin_nor_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_everspin =3D { .name =3D "everspin", .parts =3D everspin_nor_parts, .nparts =3D ARRAY_SIZE(everspin_nor_parts), - .fixups =3D &everspin_nor_fixups, + .fixups =3D everspin_fixups, + .nfixups =3D ARRAY_SIZE(everspin_fixups), }; diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadev= ice.c index 4070a692e968..f76fd0dedd0a 100644 --- a/drivers/mtd/spi-nor/gigadevice.c +++ b/drivers/mtd/spi-nor/gigadevice.c @@ -64,7 +64,6 @@ static const struct flash_info gigadevice_nor_parts[] =3D= { .id =3D SNOR_ID(0xc8, 0x40, 0x19), .name =3D "gd25q256", .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6, - .fixups =3D &gd25q256_fixups, .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0xc8, 0x60, 0x16), @@ -87,8 +86,14 @@ static const struct flash_info gigadevice_nor_parts[] = =3D { }, }; =20 +static const struct spi_nor_fixup gigadevice_fixups[] =3D { + { .id =3D SNOR_ID(0xc8, 0x40, 0x19), .fixups =3D &gd25q256_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_gigadevice =3D { .name =3D "gigadevice", .parts =3D gigadevice_nor_parts, .nparts =3D ARRAY_SIZE(gigadevice_nor_parts), + .fixups =3D gigadevice_fixups, + .nfixups =3D ARRAY_SIZE(gigadevice_fixups), }; diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c index 04db42b5141e..7af850eea9ff 100644 --- a/drivers/mtd/spi-nor/issi.c +++ b/drivers/mtd/spi-nor/issi.c @@ -52,13 +52,11 @@ static const struct flash_info issi_nor_parts[] =3D { .sector_size =3D SZ_32K, .size =3D SZ_64K, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &pm25lv_nor_fixups }, { .name =3D "pm25lv010", .sector_size =3D SZ_32K, .size =3D SZ_128K, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &pm25lv_nor_fixups }, { .id =3D SNOR_ID(0x7f, 0x9d, 0x20), .name =3D "is25cd512", @@ -103,7 +101,6 @@ static const struct flash_info issi_nor_parts[] =3D { }, { .id =3D SNOR_ID(0x9d, 0x60, 0x19), .name =3D "is25lp256", - .fixups =3D &is25lp256_fixups, .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0x9d, 0x70, 0x16), @@ -124,7 +121,6 @@ static const struct flash_info issi_nor_parts[] =3D { .id =3D SNOR_ID(0x9d, 0x70, 0x19), .name =3D "is25wp256", .flags =3D SPI_NOR_QUAD_PP, - .fixups =3D &is25lp256_fixups, .fixup_flags =3D SPI_NOR_4B_OPCODES, } }; @@ -139,9 +135,25 @@ static const struct spi_nor_fixups issi_fixups =3D { .default_init =3D issi_nor_default_init, }; =20 +/* PM25LV parts have no JEDEC ID and are likely matched by name */ +static bool issi_pm25lv_match(const struct spi_nor *nor) +{ + const char *name =3D nor->info ? nor->info->name : NULL; + + return name && strstarts(name, "pm25lv"); +} + +static const struct spi_nor_fixup issi_fixup_list[] =3D { + { .fixups =3D &issi_fixups }, + { .match =3D issi_pm25lv_match, .fixups =3D &pm25lv_nor_fixups }, + { .id =3D SNOR_ID(0x9d, 0x60, 0x19), .fixups =3D &is25lp256_fixups }, + { .id =3D SNOR_ID(0x9d, 0x70, 0x19), .fixups =3D &is25lp256_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_issi =3D { .name =3D "issi", .parts =3D issi_nor_parts, .nparts =3D ARRAY_SIZE(issi_nor_parts), - .fixups =3D &issi_fixups, + .fixups =3D issi_fixup_list, + .nfixups =3D ARRAY_SIZE(issi_fixup_list), }; diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c index 954e7df21ff9..a96bd0d7c2ec 100644 --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c @@ -159,24 +159,19 @@ static const struct flash_info macronix_nor_parts[] = =3D { .size =3D SZ_16M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP, .no_sfdp_flags =3D SECT_4K, - .fixups =3D &mx25l12805d_4pp3b_fixups, }, { /* MX25L25635E, MX25L25645G */ .id =3D SNOR_ID(0xc2, 0x20, 0x19), - .fixups =3D &mx25l25635_fixups }, { /* MX25L51245G, MX25L51273G, MX66L51235F */ .id =3D SNOR_ID(0xc2, 0x20, 0x1a), .fixup_flags =3D SPI_NOR_4B_OPCODES, - .fixups =3D ¯onix_qpp4b_fixups, }, { /* MX66L1G45G */ .id =3D SNOR_ID(0xc2, 0x20, 0x1b), - .fixups =3D ¯onix_qpp4b_fixups, }, { /* MX66L2G45G */ .id =3D SNOR_ID(0xc2, 0x20, 0x1c), - .fixups =3D ¯onix_qpp4b_fixups, }, { .id =3D SNOR_ID(0xc2, 0x23, 0x14), .name =3D "mx25v8035f", @@ -215,15 +210,12 @@ static const struct flash_info macronix_nor_parts[] = =3D { }, { /* MX25U51245G, MX25U51293G */ .id =3D SNOR_ID(0xc2, 0x25, 0x3a), - .fixups =3D ¯onix_qpp4b_fixups, }, { /* MX66U1G45G, MX66U1G93G */ .id =3D SNOR_ID(0xc2, 0x25, 0x3b), - .fixups =3D ¯onix_qpp4b_fixups, }, { /* MX66U2G45G */ .id =3D SNOR_ID(0xc2, 0x25, 0x3c), - .fixups =3D ¯onix_qpp4b_fixups, }, { .id =3D SNOR_ID(0xc2, 0x26, 0x18), .name =3D "mx25l12855e", @@ -255,7 +247,6 @@ static const struct flash_info macronix_nor_parts[] =3D= { }, { /* MX25L3255E */ .id =3D SNOR_ID(0xc2, 0x9e, 0x16), - .fixups =3D &mx25l3255e_fixups, }, /* * This spares us of adding new flash entries for flashes that can be @@ -359,9 +350,23 @@ static const struct spi_nor_fixups macronix_nor_fixups= =3D { .late_init =3D macronix_nor_late_init, }; =20 +static const struct spi_nor_fixup macronix_fixups[] =3D { + { .fixups =3D ¯onix_nor_fixups }, + { .id =3D SNOR_ID(0xc2, 0x20, 0x18), .fixups =3D &mx25l12805d_4pp3b_fixup= s }, + { .id =3D SNOR_ID(0xc2, 0x20, 0x19), .fixups =3D &mx25l25635_fixups }, + { .id =3D SNOR_ID(0xc2, 0x20, 0x1a), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x20, 0x1b), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x20, 0x1c), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x25, 0x3a), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x25, 0x3b), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x25, 0x3c), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x9e, 0x16), .fixups =3D &mx25l3255e_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_macronix =3D { .name =3D "macronix", .parts =3D macronix_nor_parts, .nparts =3D ARRAY_SIZE(macronix_nor_parts), - .fixups =3D ¯onix_nor_fixups, + .fixups =3D macronix_fixups, + .nfixups =3D ARRAY_SIZE(macronix_fixups), }; diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-s= t.c index 21d0ceac1ed7..dc1b52bd34df 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -206,13 +206,11 @@ static const struct flash_info micron_nor_parts[] =3D= { .id =3D SNOR_ID(0x2c, 0x5b, 0x1a), .mfr_flags =3D USE_FSR, .fixup_flags =3D SPI_NOR_IO_MODE_EN_VOLATILE, - .fixups =3D &mt35xu512aba_fixups, }, { /* MT35XU01GBBA */ .id =3D SNOR_ID(0x2c, 0x5b, 0x1b), .mfr_flags =3D USE_FSR, .fixup_flags =3D SPI_NOR_IO_MODE_EN_VOLATILE, - .fixups =3D &mt35_two_die_fixups, }, { .id =3D SNOR_ID(0x2c, 0x5b, 0x1c), .name =3D "mt35xu02g", @@ -221,7 +219,6 @@ static const struct flash_info micron_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_OCTAL_READ, .mfr_flags =3D USE_FSR, .fixup_flags =3D SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE, - .fixups =3D &mt35_two_die_fixups, }, }; =20 @@ -233,6 +230,17 @@ static int mt25qu512a_post_bfpt_fixup(struct spi_nor *= nor, return 0; } =20 +/* + * n25q00a parts share the first same 3 ID bytes with mt25qu01g. + * In order to not mix the fixups, further filter out using the part name. + */ +static bool n25q00a_match(const struct spi_nor *nor) +{ + const char *name =3D nor->info ? nor->info->name : NULL; + + return name && !strncmp(name, "n25q00a", 7); +} + static const struct spi_nor_fixups mt25qu512a_fixups =3D { .post_bfpt =3D mt25qu512a_post_bfpt_fixup, }; @@ -426,14 +434,12 @@ static const struct flash_info st_nor_parts[] =3D { SPI_NOR_BP3_SR_BIT6, .no_sfdp_flags =3D SECT_4K | SPI_NOR_QUAD_READ, .mfr_flags =3D USE_FSR, - .fixups =3D &n25q00_fixups, }, { .id =3D SNOR_ID(0x20, 0xba, 0x22), .name =3D "mt25ql02g", .size =3D SZ_256M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_QUAD_READ, .mfr_flags =3D USE_FSR, - .fixups =3D &mt25q02_fixups, }, { .id =3D SNOR_ID(0x20, 0xbb, 0x15), .name =3D "n25q016a", @@ -480,7 +486,6 @@ static const struct flash_info st_nor_parts[] =3D { .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6, .mfr_flags =3D USE_FSR, - .fixups =3D &mt25qu512a_fixups, }, { .id =3D SNOR_ID(0x20, 0xbb, 0x20), .name =3D "n25q512a", @@ -493,21 +498,18 @@ static const struct flash_info st_nor_parts[] =3D { .id =3D SNOR_ID(0x20, 0xbb, 0x21, 0x10, 0x44, 0x00), .name =3D "mt25qu01g", .mfr_flags =3D USE_FSR, - .fixups =3D &mt25q01_fixups, }, { .id =3D SNOR_ID(0x20, 0xbb, 0x21), .name =3D "n25q00a", .size =3D SZ_128M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_QUAD_READ, .mfr_flags =3D USE_FSR, - .fixups =3D &n25q00_fixups, }, { .id =3D SNOR_ID(0x20, 0xbb, 0x22), .name =3D "mt25qu02g", .size =3D SZ_256M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .mfr_flags =3D USE_FSR, - .fixups =3D &mt25q02_fixups, } }; =20 @@ -657,16 +659,35 @@ static const struct spi_nor_fixups micron_st_nor_fixu= ps =3D { .late_init =3D micron_st_nor_late_init, }; =20 +static const struct spi_nor_fixup micron_fixups[] =3D { + { .fixups =3D µn_st_nor_fixups }, + { .id =3D SNOR_ID(0x2c, 0x5b, 0x1a), .fixups =3D &mt35xu512aba_fixups }, + { .id =3D SNOR_ID(0x2c, 0x5b, 0x1b), .fixups =3D &mt35_two_die_fixups }, + { .id =3D SNOR_ID(0x2c, 0x5b, 0x1c), .fixups =3D &mt35_two_die_fixups }, +}; + +static const struct spi_nor_fixup st_fixups[] =3D { + { .fixups =3D µn_st_nor_fixups }, + { .id =3D SNOR_ID(0x20, 0xba, 0x21), .fixups =3D &n25q00_fixups }, + { .id =3D SNOR_ID(0x20, 0xba, 0x22), .fixups =3D &mt25q02_fixups }, + { .id =3D SNOR_ID(0x20, 0xbb, 0x20, 0x10, 0x44, 0x00), .fixups =3D &mt25q= u512a_fixups }, + { .id =3D SNOR_ID(0x20, 0xbb, 0x21, 0x10, 0x44, 0x00), .fixups =3D &mt25q= 01_fixups }, + { .id =3D SNOR_ID(0x20, 0xbb, 0x21), .match =3D n25q00a_match, .fixups = =3D &n25q00_fixups }, + { .id =3D SNOR_ID(0x20, 0xbb, 0x22), .fixups =3D &mt25q02_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_micron =3D { .name =3D "micron", .parts =3D micron_nor_parts, .nparts =3D ARRAY_SIZE(micron_nor_parts), - .fixups =3D µn_st_nor_fixups, + .fixups =3D micron_fixups, + .nfixups =3D ARRAY_SIZE(micron_fixups), }; =20 const struct spi_nor_manufacturer spi_nor_st =3D { .name =3D "st", .parts =3D st_nor_parts, .nparts =3D ARRAY_SIZE(st_nor_parts), - .fixups =3D µn_st_nor_fixups, + .fixups =3D st_fixups, + .nfixups =3D ARRAY_SIZE(st_fixups), }; diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 23c11fbc68c3..b0b753fb2345 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -416,18 +416,23 @@ static int spi_nor_post_bfpt_fixups(struct spi_nor *n= or, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt) { + const struct spi_nor_fixup *fixups; + unsigned int i; int ret; =20 - if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->post_bfpt) { - ret =3D nor->manufacturer->fixups->post_bfpt(nor, bfpt_header, - bfpt); - if (ret) - return ret; - } + if (!nor->manufacturer || !nor->manufacturer->fixups) + return 0; =20 - if (nor->info->fixups && nor->info->fixups->post_bfpt) - return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt); + fixups =3D nor->manufacturer->fixups; + + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (fixups[i].fixups->post_bfpt && + spi_nor_fixup_match(nor, &fixups[i])) { + ret =3D fixups[i].fixups->post_bfpt(nor, bfpt_header, bfpt); + if (ret) + return ret; + } + } =20 return 0; } @@ -758,12 +763,19 @@ static u8 spi_nor_smpt_addr_nbytes(const struct spi_n= or *nor, const u32 settings static void spi_nor_smpt_read_dummy_fixups(const struct spi_nor *nor, u8 *read_dummy) { - if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->smpt_read_dummy) - nor->manufacturer->fixups->smpt_read_dummy(nor, read_dummy); + const struct spi_nor_fixup *fixups; + unsigned int i; =20 - if (nor->info->fixups && nor->info->fixups->smpt_read_dummy) - nor->info->fixups->smpt_read_dummy(nor, read_dummy); + if (!nor->manufacturer || !nor->manufacturer->fixups) + return; + + fixups =3D nor->manufacturer->fixups; + + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (fixups[i].fixups->smpt_read_dummy && + spi_nor_fixup_match(nor, &fixups[i])) + fixups[i].fixups->smpt_read_dummy(nor, read_dummy); + } } =20 /** @@ -788,12 +800,19 @@ static u8 spi_nor_smpt_read_dummy(const struct spi_no= r *nor, const u32 settings) =20 static void spi_nor_smpt_map_id_fixups(const struct spi_nor *nor, u8 *map_= id) { - if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->smpt_map_id) - nor->manufacturer->fixups->smpt_map_id(nor, map_id); + const struct spi_nor_fixup *fixups; + unsigned int i; =20 - if (nor->info->fixups && nor->info->fixups->smpt_map_id) - nor->info->fixups->smpt_map_id(nor, map_id); + if (!nor->manufacturer || !nor->manufacturer->fixups) + return; + + fixups =3D nor->manufacturer->fixups; + + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (fixups[i].fixups->smpt_map_id && + spi_nor_fixup_match(nor, &fixups[i])) + fixups[i].fixups->smpt_map_id(nor, map_id); + } } =20 /** @@ -1445,17 +1464,23 @@ static int spi_nor_parse_sccr_mc(struct spi_nor *no= r, */ static int spi_nor_post_sfdp_fixups(struct spi_nor *nor) { + const struct spi_nor_fixup *fixups; + unsigned int i; int ret; =20 - if (nor->manufacturer && nor->manufacturer->fixups && - nor->manufacturer->fixups->post_sfdp) { - ret =3D nor->manufacturer->fixups->post_sfdp(nor); - if (ret) - return ret; - } + if (!nor->manufacturer || !nor->manufacturer->fixups) + return 0; =20 - if (nor->info->fixups && nor->info->fixups->post_sfdp) - return nor->info->fixups->post_sfdp(nor); + fixups =3D nor->manufacturer->fixups; + + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (fixups[i].fixups->post_sfdp && + spi_nor_fixup_match(nor, &fixups[i])) { + ret =3D fixups[i].fixups->post_sfdp(nor); + if (ret) + return ret; + } + } =20 return 0; } diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c index ce2e233108c4..52aa31a84fc8 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -907,7 +907,6 @@ static const struct flash_info spansion_nor_parts[] =3D= { .sector_size =3D SZ_256K, .no_sfdp_flags =3D SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .mfr_flags =3D USE_CLSR, - .fixups =3D &s25fs_s_nor_fixups, }, { .id =3D SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x00), .name =3D "s25sl12800", @@ -943,7 +942,6 @@ static const struct flash_info spansion_nor_parts[] =3D= { .size =3D SZ_16M, .no_sfdp_flags =3D SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .mfr_flags =3D USE_CLSR, - .fixups =3D &s25fs_s_nor_fixups, }, { .id =3D SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01), .name =3D "s25fl129p1", @@ -1003,76 +1001,61 @@ static const struct flash_info spansion_nor_parts[]= =3D { .id =3D SNOR_ID(0x34, 0x2a, 0x1a, 0x0f, 0x03, 0x90), .name =3D "s25hl512t", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25hx_t_fixups }, { .id =3D SNOR_ID(0x34, 0x2a, 0x1b, 0x0f, 0x03, 0x90), .name =3D "s25hl01gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25hx_t_fixups }, { .id =3D SNOR_ID(0x34, 0x2a, 0x1c, 0x0f, 0x00, 0x90), .name =3D "s25hl02gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25hx_t_fixups }, { .id =3D SNOR_ID(0x34, 0x2b, 0x19, 0x0f, 0x08, 0x90), .name =3D "s25fs256t", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25fs256t_fixups }, { .id =3D SNOR_ID(0x34, 0x2b, 0x1a, 0x0f, 0x03, 0x90), .name =3D "s25hs512t", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25hx_t_fixups }, { .id =3D SNOR_ID(0x34, 0x2b, 0x1b, 0x0f, 0x03, 0x90), .name =3D "s25hs01gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25hx_t_fixups }, { .id =3D SNOR_ID(0x34, 0x2b, 0x1c, 0x0f, 0x00, 0x90), .name =3D "s25hs02gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s25hx_t_fixups }, { /* S28HL256T */ .id =3D SNOR_ID(0x34, 0x5a, 0x19), .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0x34, 0x5a, 0x1a), .name =3D "s28hl512t", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0x34, 0x5a, 0x1b), .name =3D "s28hl01gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { /* S28HL02GT */ .id =3D SNOR_ID(0x34, 0x5a, 0x1c), .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0x34, 0x5b, 0x19), .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0x34, 0x5b, 0x1a), .name =3D "s28hs512t", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0x34, 0x5b, 0x1b), .name =3D "s28hs01gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0x34, 0x5b, 0x1c), .name =3D "s28hs02gt", .mfr_flags =3D USE_CLPEF, - .fixups =3D &s28hx_t_fixups, }, { .id =3D SNOR_ID(0xef, 0x40, 0x13), .name =3D "s25fl004k", @@ -1172,9 +1155,31 @@ static const struct spi_nor_fixups spansion_nor_fixu= ps =3D { .late_init =3D spansion_nor_late_init, }; =20 +static const struct spi_nor_fixup spansion_fixups[] =3D { + { .fixups =3D &spansion_nor_fixups }, + { .id =3D SNOR_ID(0x01, 0x02, 0x20, 0x4d, 0x00, 0x81), .fixups =3D &s25fs= _s_nor_fixups }, + { .id =3D SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01, 0x81), .fixups =3D &s25fs= _s_nor_fixups }, + { .id =3D SNOR_ID(0x34, 0x2a, 0x1a, 0x0f, 0x03, 0x90), .fixups =3D &s25hx= _t_fixups }, + { .id =3D SNOR_ID(0x34, 0x2a, 0x1b, 0x0f, 0x03, 0x90), .fixups =3D &s25hx= _t_fixups }, + { .id =3D SNOR_ID(0x34, 0x2a, 0x1c, 0x0f, 0x00, 0x90), .fixups =3D &s25hx= _t_fixups }, + { .id =3D SNOR_ID(0x34, 0x2b, 0x19, 0x0f, 0x08, 0x90), .fixups =3D &s25fs= 256t_fixups }, + { .id =3D SNOR_ID(0x34, 0x2b, 0x1a, 0x0f, 0x03, 0x90), .fixups =3D &s25hx= _t_fixups }, + { .id =3D SNOR_ID(0x34, 0x2b, 0x1b, 0x0f, 0x03, 0x90), .fixups =3D &s25hx= _t_fixups }, + { .id =3D SNOR_ID(0x34, 0x2b, 0x1c, 0x0f, 0x00, 0x90), .fixups =3D &s25hx= _t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5a, 0x19), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5a, 0x1a), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5a, 0x1b), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5a, 0x1c), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5b, 0x19), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5b, 0x1a), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5b, 0x1b), .fixups =3D &s28hx_t_fixups }, + { .id =3D SNOR_ID(0x34, 0x5b, 0x1c), .fixups =3D &s28hx_t_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_spansion =3D { .name =3D "spansion", .parts =3D spansion_nor_parts, .nparts =3D ARRAY_SIZE(spansion_nor_parts), - .fixups =3D &spansion_nor_fixups, + .fixups =3D spansion_fixups, + .nfixups =3D ARRAY_SIZE(spansion_fixups), }; diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c index 77a0bc41d4e5..c460803b278b 100644 --- a/drivers/mtd/spi-nor/sst.c +++ b/drivers/mtd/spi-nor/sst.c @@ -152,14 +152,12 @@ static const struct flash_info sst_nor_parts[] =3D { .id =3D SNOR_ID(0xbf, 0x26, 0x42), .name =3D "sst26vf032b", .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, - .fixups =3D &sst26vf_nor_fixups, }, { .id =3D SNOR_ID(0xbf, 0x26, 0x43), .name =3D "sst26vf064b", .size =3D SZ_8M, .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixups =3D &sst26vf_nor_fixups, }, { .id =3D SNOR_ID(0xbf, 0x26, 0x51), .name =3D "sst26wf016b", @@ -278,9 +276,16 @@ static const struct spi_nor_fixups sst_nor_fixups =3D { .late_init =3D sst_nor_late_init, }; =20 +static const struct spi_nor_fixup sst_fixups[] =3D { + { .fixups =3D &sst_nor_fixups }, + { .id =3D SNOR_ID(0xbf, 0x26, 0x42), .fixups =3D &sst26vf_nor_fixups }, + { .id =3D SNOR_ID(0xbf, 0x26, 0x43), .fixups =3D &sst26vf_nor_fixups }, +}; + const struct spi_nor_manufacturer spi_nor_sst =3D { .name =3D "sst", .parts =3D sst_nor_parts, .nparts =3D ARRAY_SIZE(sst_nor_parts), - .fixups =3D &sst_nor_fixups, + .fixups =3D sst_fixups, + .nfixups =3D ARRAY_SIZE(sst_fixups), }; diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index df4688c637a2..063b85e041cd 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -219,7 +219,6 @@ static const struct flash_info winbond_nor_parts[] =3D { .size =3D SZ_16M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, - .fixups =3D &w25q128_fixups, }, { /* W25Q256JV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x19), @@ -228,7 +227,6 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, - .fixups =3D &w25q256_fixups, }, { /* W25Q512JV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x20), @@ -242,7 +240,6 @@ static const struct flash_info winbond_nor_parts[] =3D { .id =3D SNOR_ID(0xef, 0x40, 0x21), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, - .fixups =3D &winbond_nor_multi_die_fixups, }, { .id =3D SNOR_ID(0xef, 0x50, 0x12), .name =3D "w25q20bw", @@ -345,13 +342,11 @@ static const struct flash_info winbond_nor_parts[] = =3D { .id =3D SNOR_ID(0xef, 0x70, 0x21), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, - .fixups =3D &winbond_nor_multi_die_fixups, }, { /* W25Q02JV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x22), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, - .fixups =3D &winbond_nor_multi_die_fixups, }, { .id =3D SNOR_ID(0xef, 0x71, 0x19), .name =3D "w25m512jv", @@ -553,9 +548,19 @@ static const struct spi_nor_fixups winbond_nor_fixups = =3D { .late_init =3D winbond_nor_late_init, }; =20 +static const struct spi_nor_fixup winbond_fixups[] =3D { + { .fixups =3D &winbond_nor_fixups }, + { .id =3D SNOR_ID(0xef, 0x40, 0x18), .fixups =3D &w25q128_fixups }, + { .id =3D SNOR_ID(0xef, 0x40, 0x19), .fixups =3D &w25q256_fixups }, + { .id =3D SNOR_ID(0xef, 0x40, 0x21), .fixups =3D &winbond_nor_multi_die_f= ixups }, + { .id =3D SNOR_ID(0xef, 0x70, 0x21), .fixups =3D &winbond_nor_multi_die_f= ixups }, + { .id =3D SNOR_ID(0xef, 0x70, 0x22), .fixups =3D &winbond_nor_multi_die_f= ixups }, +}; + const struct spi_nor_manufacturer spi_nor_winbond =3D { .name =3D "winbond", .parts =3D winbond_nor_parts, .nparts =3D ARRAY_SIZE(winbond_nor_parts), - .fixups =3D &winbond_nor_fixups, + .fixups =3D winbond_fixups, + .nfixups =3D ARRAY_SIZE(winbond_fixups), }; --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31ACB51D508 for ; Fri, 4 Sep 2026 18:13:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545608; cv=none; b=KyhE4BO9+Pqb/gxZ/lWaSHM30G7KPsCw9J93tXz1DaExMpOzMUpYhIAJ5ZHV9zm7iNyDFgLEtn1oDQ1m79oUhcjHaey20OrGpmpIFa8mvCaBOsU9HlFJx9HxI7TdnATcrYX6OQmJTRh24gH8G3t0ooy0xiBfNNjj8H24aJYBoy4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545608; c=relaxed/simple; bh=bon9RXplHAGCXxe0nHECRLT4fLF6V2Ui+FOXlaigj+c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ceuZV8KoSD7fK33mPjipLbetvgUi41v17Be84mvPiPSP0gEZa9ANRCXtTMlqv3AFPvvlqrIfTtGv4tbm/UYidHyeoHwuTXAkU2NhY7Bgf+1OJVwc4YWnW/FqkgX23BUJXK95IOK8q8DMEzppA/UYMu82eZN6dZN5iSxEWQ/Cu2w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=LUT4439U; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="LUT4439U" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id BECC74E41522; Fri, 4 Sep 2026 18:13:24 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 92D716057F; Fri, 4 Sep 2026 18:13:24 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 4001B11C78705; Fri, 4 Sep 2026 20:13:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545603; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=9vo735+/VekKj0gwB9ZY2UViOx30Itxy7IxkP1oXQHM=; b=LUT4439UdCZB7wfWzTStSWIbJeqp7Tg7+B1FGGX42B1SfI2Oo6p3Yjpuc+hA5VgI9qWe2c 5/EAL1jgggzwrkdtCIrJqSHx/fsYKu63aRMOq5+BQwjTvK9YMbNqvqfjY5itDCOlAMQtYm vdU2oETpAJCORWErGwJOa1Q+W4JVk5w1b/02ITXwQn0pdqqpalJveNl3R1+8I7mMxL42oT wB5wZcJviUly4030KP9u5bOUtXZTVtXiMrtzGUtrGLST45X1jnGqvcsb1gpxyiY/AtA/DF TZqYZJFcc7aW+BmrzRzZEHtIKKxPlWeoCPBKeQO3lCXevjUMZbSkk/n2M9pPTQ== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:43 +0200 Subject: [PATCH v5 06/25] mtd: spi-nor: Move the fixup flags into the fixup list Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-6-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 The idea of the fixup flags is to enable fixups without having to repeat the same fixup function over and over again. It overall reduces the boilerplate with a similar intent: fixing our knowledge of the flash. Move the fixup_flags field as well as the associated flag definitions to the spi_nor_fixup structure and enable them based on the IDs. No functional change. Suggested-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/core.c | 25 ++++++++++++++++++------- drivers/mtd/spi-nor/core.h | 30 ++++++++++++++---------------- drivers/mtd/spi-nor/gigadevice.c | 4 ++-- drivers/mtd/spi-nor/issi.c | 8 ++++---- drivers/mtd/spi-nor/macronix.c | 4 ++-- drivers/mtd/spi-nor/micron-st.c | 21 ++++++++++++--------- drivers/mtd/spi-nor/sfdp.c | 10 +++++----- drivers/mtd/spi-nor/spansion.c | 6 +++--- 8 files changed, 60 insertions(+), 48 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 322683738ef1..d1fd94c391f4 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2654,7 +2654,7 @@ static void spi_nor_manufacturer_init_params(struct s= pi_nor *nor) fixups =3D nor->manufacturer->fixups; =20 for (i =3D 0; i < nor->manufacturer->nfixups; i++) { - if (fixups[i].fixups->default_init && + if (fixups[i].fixups && fixups[i].fixups->default_init && spi_nor_fixup_match(nor, &fixups[i])) fixups[i].fixups->default_init(nor); } @@ -2787,13 +2787,24 @@ static void spi_nor_init_flags(struct spi_nor *nor) static void spi_nor_init_fixup_flags(struct spi_nor *nor) { struct spi_nor_flash_parameter *params =3D nor->params; - const u8 fixup_flags =3D nor->info->fixup_flags; + const struct spi_nor_fixup *fixups; + unsigned int i; =20 - if (fixup_flags & SPI_NOR_4B_OPCODES) - params->flags |=3D SNOR_F_4B_OPCODES; + if (!nor->manufacturer || !nor->manufacturer->fixups) + return; =20 - if (fixup_flags & SPI_NOR_IO_MODE_EN_VOLATILE) - params->flags |=3D SNOR_F_IO_MODE_EN_VOLATILE; + fixups =3D nor->manufacturer->fixups; + + for (i =3D 0; i < nor->manufacturer->nfixups; i++) { + if (!fixups[i].fixup_flags || + !spi_nor_fixup_match(nor, &fixups[i])) + continue; + + if (fixups[i].fixup_flags & SPI_NOR_4B_OPCODES) + params->flags |=3D SNOR_F_4B_OPCODES; + if (fixups[i].fixup_flags & SPI_NOR_IO_MODE_EN_VOLATILE) + params->flags |=3D SNOR_F_IO_MODE_EN_VOLATILE; + } } =20 /** @@ -2818,7 +2829,7 @@ static int spi_nor_late_init_params(struct spi_nor *n= or) fixups =3D nor->manufacturer->fixups; =20 for (i =3D 0; i < nor->manufacturer->nfixups; i++) { - if (fixups[i].fixups->late_init && + if (fixups[i].fixups && fixups[i].fixups->late_init && spi_nor_fixup_match(nor, &fixups[i])) { ret =3D fixups[i].fixups->late_init(nor); if (ret) diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 28069f62429c..670182b3c2ad 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -457,11 +457,25 @@ struct spi_nor_fixups { * @id: (optional) flash ID this fixup applies to, may only match the * ID prefix, eg. just the first few bytes to match a whole family * @match: (optional) custom match function (can be used together with @id) + * @fixup_flags: flags that indicate support that can be discovered via SF= DP + * ideally, but can not be discovered for this particular flash + * because the SFDP table that indicates this support is not + * defined by the flash. In case the table for this support is + * defined but has wrong values, one should instead use a + * post_sfdp() hook to set the SNOR_F equivalent flag. + * + * SPI_NOR_4B_OPCODES: use dedicated 4byte address op codes to support + * memory size above 128Mib. + * SPI_NOR_IO_MODE_EN_VOLATILE: flash enables the best available I/O mode + * via a volatile bit. * @fixups: the fixup hooks to apply when this entry matches */ struct spi_nor_fixup { const struct spi_nor_id *id; bool (*match)(const struct spi_nor *nor); + u8 fixup_flags; +#define SPI_NOR_4B_OPCODES BIT(0) +#define SPI_NOR_IO_MODE_EN_VOLATILE BIT(1) const struct spi_nor_fixups *fixups; }; =20 @@ -524,22 +538,10 @@ struct spi_nor_id { * SPI_NOR_OCTAL_DTR_READ: flash supports octal DTR Read. * SPI_NOR_OCTAL_DTR_PP: flash supports Octal DTR Page Program. * - * @fixup_flags: flags that indicate support that can be discovered via= SFDP - * ideally, but can not be discovered for this particular= flash - * because the SFDP table that indicates this support is = not - * defined by the flash. In case the table for this suppo= rt is - * defined but has wrong values, one should instead use a - * post_sfdp() hook to set the SNOR_F equivalent flag. - * - * SPI_NOR_4B_OPCODES: use dedicated 4byte address op codes to supp= ort - * memory size above 128Mib. - * SPI_NOR_IO_MODE_EN_VOLATILE: flash enables the best available I/O mode - * via a volatile bit. * @mfr_flags: manufacturer private flags. Used in the manufacturer f= ixup * hooks to differentiate support between flashes of the = same * manufacturer. * @otp_org: flash's OTP organization. - * @fixups: part specific fixup hooks. */ struct flash_info { char *name; @@ -570,10 +572,6 @@ struct flash_info { #define SPI_NOR_OCTAL_DTR_READ BIT(6) #define SPI_NOR_OCTAL_DTR_PP BIT(7) =20 - u8 fixup_flags; -#define SPI_NOR_4B_OPCODES BIT(0) -#define SPI_NOR_IO_MODE_EN_VOLATILE BIT(1) - u8 mfr_flags; =20 const struct spi_nor_otp_organization *otp; diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadev= ice.c index f76fd0dedd0a..6a2e6ebda148 100644 --- a/drivers/mtd/spi-nor/gigadevice.c +++ b/drivers/mtd/spi-nor/gigadevice.c @@ -64,7 +64,6 @@ static const struct flash_info gigadevice_nor_parts[] =3D= { .id =3D SNOR_ID(0xc8, 0x40, 0x19), .name =3D "gd25q256", .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6, - .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0xc8, 0x60, 0x16), .name =3D "gd25lq32", @@ -87,7 +86,8 @@ static const struct flash_info gigadevice_nor_parts[] =3D= { }; =20 static const struct spi_nor_fixup gigadevice_fixups[] =3D { - { .id =3D SNOR_ID(0xc8, 0x40, 0x19), .fixups =3D &gd25q256_fixups }, + { .id =3D SNOR_ID(0xc8, 0x40, 0x19), .fixups =3D &gd25q256_fixups, + .fixup_flags =3D SPI_NOR_4B_OPCODES }, }; =20 const struct spi_nor_manufacturer spi_nor_gigadevice =3D { diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c index 7af850eea9ff..2f057d731df2 100644 --- a/drivers/mtd/spi-nor/issi.c +++ b/drivers/mtd/spi-nor/issi.c @@ -101,7 +101,6 @@ static const struct flash_info issi_nor_parts[] =3D { }, { .id =3D SNOR_ID(0x9d, 0x60, 0x19), .name =3D "is25lp256", - .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0x9d, 0x70, 0x16), .name =3D "is25wp032", @@ -121,7 +120,6 @@ static const struct flash_info issi_nor_parts[] =3D { .id =3D SNOR_ID(0x9d, 0x70, 0x19), .name =3D "is25wp256", .flags =3D SPI_NOR_QUAD_PP, - .fixup_flags =3D SPI_NOR_4B_OPCODES, } }; =20 @@ -146,8 +144,10 @@ static bool issi_pm25lv_match(const struct spi_nor *no= r) static const struct spi_nor_fixup issi_fixup_list[] =3D { { .fixups =3D &issi_fixups }, { .match =3D issi_pm25lv_match, .fixups =3D &pm25lv_nor_fixups }, - { .id =3D SNOR_ID(0x9d, 0x60, 0x19), .fixups =3D &is25lp256_fixups }, - { .id =3D SNOR_ID(0x9d, 0x70, 0x19), .fixups =3D &is25lp256_fixups }, + { .id =3D SNOR_ID(0x9d, 0x60, 0x19), .fixups =3D &is25lp256_fixups, + .fixup_flags =3D SPI_NOR_4B_OPCODES }, + { .id =3D SNOR_ID(0x9d, 0x70, 0x19), .fixups =3D &is25lp256_fixups, + .fixup_flags =3D SPI_NOR_4B_OPCODES }, }; =20 const struct spi_nor_manufacturer spi_nor_issi =3D { diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c index a96bd0d7c2ec..b3fdb4b2fa1c 100644 --- a/drivers/mtd/spi-nor/macronix.c +++ b/drivers/mtd/spi-nor/macronix.c @@ -165,7 +165,6 @@ static const struct flash_info macronix_nor_parts[] =3D= { }, { /* MX25L51245G, MX25L51273G, MX66L51235F */ .id =3D SNOR_ID(0xc2, 0x20, 0x1a), - .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { /* MX66L1G45G */ .id =3D SNOR_ID(0xc2, 0x20, 0x1b), @@ -354,7 +353,8 @@ static const struct spi_nor_fixup macronix_fixups[] =3D= { { .fixups =3D ¯onix_nor_fixups }, { .id =3D SNOR_ID(0xc2, 0x20, 0x18), .fixups =3D &mx25l12805d_4pp3b_fixup= s }, { .id =3D SNOR_ID(0xc2, 0x20, 0x19), .fixups =3D &mx25l25635_fixups }, - { .id =3D SNOR_ID(0xc2, 0x20, 0x1a), .fixups =3D ¯onix_qpp4b_fixups }, + { .id =3D SNOR_ID(0xc2, 0x20, 0x1a), .fixups =3D ¯onix_qpp4b_fixups, + .fixup_flags =3D SPI_NOR_4B_OPCODES }, { .id =3D SNOR_ID(0xc2, 0x20, 0x1b), .fixups =3D ¯onix_qpp4b_fixups }, { .id =3D SNOR_ID(0xc2, 0x20, 0x1c), .fixups =3D ¯onix_qpp4b_fixups }, { .id =3D SNOR_ID(0xc2, 0x25, 0x3a), .fixups =3D ¯onix_qpp4b_fixups }, diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-s= t.c index dc1b52bd34df..f97f2dead8c2 100644 --- a/drivers/mtd/spi-nor/micron-st.c +++ b/drivers/mtd/spi-nor/micron-st.c @@ -205,12 +205,10 @@ static const struct flash_info micron_nor_parts[] =3D= { /* MT35XU512ABA */ .id =3D SNOR_ID(0x2c, 0x5b, 0x1a), .mfr_flags =3D USE_FSR, - .fixup_flags =3D SPI_NOR_IO_MODE_EN_VOLATILE, }, { /* MT35XU01GBBA */ .id =3D SNOR_ID(0x2c, 0x5b, 0x1b), .mfr_flags =3D USE_FSR, - .fixup_flags =3D SPI_NOR_IO_MODE_EN_VOLATILE, }, { .id =3D SNOR_ID(0x2c, 0x5b, 0x1c), .name =3D "mt35xu02g", @@ -218,7 +216,6 @@ static const struct flash_info micron_nor_parts[] =3D { .size =3D SZ_256M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_OCTAL_READ, .mfr_flags =3D USE_FSR, - .fixup_flags =3D SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE, }, }; =20 @@ -403,7 +400,6 @@ static const struct flash_info st_nor_parts[] =3D { .name =3D "mt25ql256a", .size =3D SZ_32M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixup_flags =3D SPI_NOR_4B_OPCODES, .mfr_flags =3D USE_FSR, }, { .id =3D SNOR_ID(0x20, 0xba, 0x19), @@ -416,7 +412,6 @@ static const struct flash_info st_nor_parts[] =3D { .name =3D "mt25ql512a", .size =3D SZ_64M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixup_flags =3D SPI_NOR_4B_OPCODES, .mfr_flags =3D USE_FSR, }, { .id =3D SNOR_ID(0x20, 0xba, 0x20), @@ -472,7 +467,6 @@ static const struct flash_info st_nor_parts[] =3D { .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixup_flags =3D SPI_NOR_4B_OPCODES, .mfr_flags =3D USE_FSR, }, { .id =3D SNOR_ID(0x20, 0xbb, 0x19), @@ -661,13 +655,22 @@ static const struct spi_nor_fixups micron_st_nor_fixu= ps =3D { =20 static const struct spi_nor_fixup micron_fixups[] =3D { { .fixups =3D µn_st_nor_fixups }, - { .id =3D SNOR_ID(0x2c, 0x5b, 0x1a), .fixups =3D &mt35xu512aba_fixups }, - { .id =3D SNOR_ID(0x2c, 0x5b, 0x1b), .fixups =3D &mt35_two_die_fixups }, - { .id =3D SNOR_ID(0x2c, 0x5b, 0x1c), .fixups =3D &mt35_two_die_fixups }, + { .id =3D SNOR_ID(0x2c, 0x5b, 0x1a), .fixups =3D &mt35xu512aba_fixups, + .fixup_flags =3D SPI_NOR_IO_MODE_EN_VOLATILE }, + { .id =3D SNOR_ID(0x2c, 0x5b, 0x1b), .fixups =3D &mt35_two_die_fixups, + .fixup_flags =3D SPI_NOR_IO_MODE_EN_VOLATILE }, + { .id =3D SNOR_ID(0x2c, 0x5b, 0x1c), .fixups =3D &mt35_two_die_fixups, + .fixup_flags =3D SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE }, }; =20 static const struct spi_nor_fixup st_fixups[] =3D { { .fixups =3D µn_st_nor_fixups }, + { .id =3D SNOR_ID(0x20, 0xba, 0x19, 0x10, 0x44, 0x00), + .fixup_flags =3D SPI_NOR_4B_OPCODES }, + { .id =3D SNOR_ID(0x20, 0xba, 0x20, 0x10, 0x44, 0x00), + .fixup_flags =3D SPI_NOR_4B_OPCODES }, + { .id =3D SNOR_ID(0x20, 0xbb, 0x19, 0x10, 0x44, 0x00), + .fixup_flags =3D SPI_NOR_4B_OPCODES }, { .id =3D SNOR_ID(0x20, 0xba, 0x21), .fixups =3D &n25q00_fixups }, { .id =3D SNOR_ID(0x20, 0xba, 0x22), .fixups =3D &mt25q02_fixups }, { .id =3D SNOR_ID(0x20, 0xbb, 0x20, 0x10, 0x44, 0x00), .fixups =3D &mt25q= u512a_fixups }, diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index b0b753fb2345..823cda6874aa 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -417,8 +417,8 @@ static int spi_nor_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_bfpt *bfpt) { const struct spi_nor_fixup *fixups; - unsigned int i; int ret; + unsigned int i; =20 if (!nor->manufacturer || !nor->manufacturer->fixups) return 0; @@ -426,7 +426,7 @@ static int spi_nor_post_bfpt_fixups(struct spi_nor *nor, fixups =3D nor->manufacturer->fixups; =20 for (i =3D 0; i < nor->manufacturer->nfixups; i++) { - if (fixups[i].fixups->post_bfpt && + if (fixups[i].fixups && fixups[i].fixups->post_bfpt && spi_nor_fixup_match(nor, &fixups[i])) { ret =3D fixups[i].fixups->post_bfpt(nor, bfpt_header, bfpt); if (ret) @@ -772,7 +772,7 @@ static void spi_nor_smpt_read_dummy_fixups(const struct= spi_nor *nor, fixups =3D nor->manufacturer->fixups; =20 for (i =3D 0; i < nor->manufacturer->nfixups; i++) { - if (fixups[i].fixups->smpt_read_dummy && + if (fixups[i].fixups && fixups[i].fixups->smpt_read_dummy && spi_nor_fixup_match(nor, &fixups[i])) fixups[i].fixups->smpt_read_dummy(nor, read_dummy); } @@ -809,7 +809,7 @@ static void spi_nor_smpt_map_id_fixups(const struct spi= _nor *nor, u8 *map_id) fixups =3D nor->manufacturer->fixups; =20 for (i =3D 0; i < nor->manufacturer->nfixups; i++) { - if (fixups[i].fixups->smpt_map_id && + if (fixups[i].fixups && fixups[i].fixups->smpt_map_id && spi_nor_fixup_match(nor, &fixups[i])) fixups[i].fixups->smpt_map_id(nor, map_id); } @@ -1474,7 +1474,7 @@ static int spi_nor_post_sfdp_fixups(struct spi_nor *n= or) fixups =3D nor->manufacturer->fixups; =20 for (i =3D 0; i < nor->manufacturer->nfixups; i++) { - if (fixups[i].fixups->post_sfdp && + if (fixups[i].fixups && fixups[i].fixups->post_sfdp && spi_nor_fixup_match(nor, &fixups[i])) { ret =3D fixups[i].fixups->post_sfdp(nor); if (ret) diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c index 52aa31a84fc8..02943b7d1f49 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -978,19 +978,16 @@ static const struct flash_info spansion_nor_parts[] = =3D { .name =3D "s25fl064l", .size =3D SZ_8M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0x01, 0x60, 0x18), .name =3D "s25fl128l", .size =3D SZ_16M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0x01, 0x60, 0x19), .name =3D "s25fl256l", .size =3D SZ_32M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .fixup_flags =3D SPI_NOR_4B_OPCODES, }, { .id =3D SNOR_ID(0x04, 0x2c, 0xc2, 0x7f, 0x7f, 0x7f), .name =3D "cy15x104q", @@ -1159,6 +1156,9 @@ static const struct spi_nor_fixup spansion_fixups[] = =3D { { .fixups =3D &spansion_nor_fixups }, { .id =3D SNOR_ID(0x01, 0x02, 0x20, 0x4d, 0x00, 0x81), .fixups =3D &s25fs= _s_nor_fixups }, { .id =3D SNOR_ID(0x01, 0x20, 0x18, 0x4d, 0x01, 0x81), .fixups =3D &s25fs= _s_nor_fixups }, + { .id =3D SNOR_ID(0x01, 0x60, 0x17), .fixup_flags =3D SPI_NOR_4B_OPCODES = }, + { .id =3D SNOR_ID(0x01, 0x60, 0x18), .fixup_flags =3D SPI_NOR_4B_OPCODES = }, + { .id =3D SNOR_ID(0x01, 0x60, 0x19), .fixup_flags =3D SPI_NOR_4B_OPCODES = }, { .id =3D SNOR_ID(0x34, 0x2a, 0x1a, 0x0f, 0x03, 0x90), .fixups =3D &s25hx= _t_fixups }, { .id =3D SNOR_ID(0x34, 0x2a, 0x1b, 0x0f, 0x03, 0x90), .fixups =3D &s25hx= _t_fixups }, { .id =3D SNOR_ID(0x34, 0x2a, 0x1c, 0x0f, 0x00, 0x90), .fixups =3D &s25hx= _t_fixups }, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 57C4051D516 for ; Fri, 4 Sep 2026 18:13:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545610; cv=none; b=JnyI5QaKf/DiyQLljOU0yJG7oCB2TE7/3p5vFmMyfmhPJo/Oy41RV7Ljgo3RTJIHwMrxv56P/SXgRrnPb45FUoy1kESfhhDpsMnVd5to0XAigu/HdIwlIfITUtAecmkJauncbAhOqoYOhfSIEp8NPD7LWofn/9pHt2lixj96rPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545610; c=relaxed/simple; bh=PGCVQXoDr4iemvU1sZkXYSIZg5+xXRsmbndPzEp7jnk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mfVFQdUd9XjnsVawItPdjgfYOjcx+rU8QeE0gIrW6CqxjV1qzQMxyMThjd3+Bbf5weK2SQy1bJmnU1pWzsWgyBQIeACThIRnb0FGvirofxUNNCZquDK+VC9Yx9stDjFZcmb01matAaQq0P0VbizfShDxCDG2sjZ04VULzm5naqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=2Y/7jvYT; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="2Y/7jvYT" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id DCABE4E41521; Fri, 4 Sep 2026 18:13:26 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id B02046057F; Fri, 4 Sep 2026 18:13:26 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 0138711C78158; Fri, 4 Sep 2026 20:13:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545605; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=BYi4mQbvSQqfgAThIxSjeUC7ka2DI1ogavUu6IUjT3I=; b=2Y/7jvYTDeKgfGjk+dzS6wCeh0R0lJ7zcMKb4b5BMEXqJrvCLQiggOhL+ZZ8+z9QRFvI1/ CoKMddIu11CSbCmAz1nQcGgNqroge5OF7zPEf8wO2LtO8aD7uh82IEntit888PZNs+pD71 Cz8Jq6LC5ecjQp3tzWq0viNFMngLE0Vh/Vw2NOV6RiAl1dple0xr82kYAL+ELEMUD7JPrq pn8jXhhMP3RdP9fljjwiRMD9U52CE8qdkWLPtYIrc4vfquz3VQ6XMQ69Y6VxWUS0PVvD0M WEqHOpQjJNFWezVTzzf8ytw6jQ3O9PsfcYxTpQHyzI7ZnGq5OpmnyGRn7UDRLg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:44 +0200 Subject: [PATCH v5 07/25] mtd: spi-nor: Create an indirection on the part name Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-7-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 We currently print through sysfs and debugfs the name of the part if the .name field, which is legacy, has been filled in the ID table (otherwise "(null)" is printed). These IDs had an interest until manufacturers started re-using more and more extensively the so called unique JEDEC IDs. At this stage, a name that was tailored for a chip sold in 2016 may no longer be relevant for a chip sold in 2026. Still showing this name through the various filesystems may confuse people, removing these names cannot be done since they are now part of the user ABI (because of sysfs). In order to allow overwriting the .name field (which is part of a read-only structure), let's create a spi-nor pointer which will by default point to that .name, but which can be cleared in fixup hooks to make sure the name is hidden on newer parts. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/core.c | 1 + drivers/mtd/spi-nor/debugfs.c | 3 +-- drivers/mtd/spi-nor/sysfs.c | 4 ++-- include/linux/mtd/spi-nor.h | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index d1fd94c391f4..e2b6efafdd8d 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -3438,6 +3438,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *nam= e, return PTR_ERR(info); =20 nor->info =3D info; + nor->partname =3D info->name; =20 mutex_init(&nor->lock); =20 diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index 51c0582f793a..5c738786145f 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -81,13 +81,12 @@ static int spi_nor_params_show(struct seq_file *s, void= *data) struct spi_nor_flash_parameter *params =3D nor->params; struct spi_nor_erase_map *erase_map =3D ¶ms->erase_map; struct spi_nor_erase_region *region =3D erase_map->regions; - const struct flash_info *info =3D nor->info; char buf[16], *str; loff_t lock_start; u64 lock_length; unsigned int i; =20 - seq_printf(s, "name\t\t%s\n", info->name); + seq_printf(s, "name\t\t%s\n", nor->partname); seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id); string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf)); seq_printf(s, "size\t\t%s\n", buf); diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c index 643513ee891b..a2dabe4c6422 100644 --- a/drivers/mtd/spi-nor/sysfs.c +++ b/drivers/mtd/spi-nor/sysfs.c @@ -25,7 +25,7 @@ static ssize_t partname_show(struct device *dev, struct spi_mem *spimem =3D spi_get_drvdata(spi); struct spi_nor *nor =3D spi_mem_get_drvdata(spimem); =20 - return sysfs_emit(buf, "%s\n", nor->info->name); + return sysfs_emit(buf, "%s\n", nor->partname); } static DEVICE_ATTR_RO(partname); =20 @@ -78,7 +78,7 @@ static umode_t spi_nor_sysfs_is_visible(struct kobject *k= obj, =20 if (attr =3D=3D &dev_attr_manufacturer.attr && !nor->manufacturer) return 0; - if (attr =3D=3D &dev_attr_partname.attr && !nor->info->name) + if (attr =3D=3D &dev_attr_partname.attr && !nor->partname) return 0; if (attr =3D=3D &dev_attr_jedec_id.attr && !nor->info->id && !nor->id) return 0; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 539eb514588c..b3e3c6b10186 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -393,6 +393,7 @@ struct spi_nor { u8 *id; const struct flash_info *info; const struct spi_nor_manufacturer *manufacturer; + const char *partname; u8 addr_nbytes; u8 erase_opcode; u8 read_opcode; --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C6BF51D52F; Fri, 4 Sep 2026 18:13:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545614; cv=none; b=VeXZuaglKgcB0Q9OPJO+ArD74C4XqFO/cTeuilowEVkGnAme9efgUIe8GFRSbyoUksFGy7vtxkwoQ5cFMAuW+r7aRfL7omkNTmeuVV1aoJbj44JxzgoT4fWOJBRpoZ01cODO8w2TtGI4suxZqMK2WqPu3Q5+XP4KVi94XPr4f6U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545614; c=relaxed/simple; bh=+L1lrKBjyJdeBXSTKyLcZ3EMObECOkwNX4quZMlyzS0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ayp5lQXhp9t1qaDtceQb4/LSmEDVOb7lRZc4eN2mNK0KLfgOM+Iu2Rdg5xX2NXb2t9/PLEScVNpRpIHabkK4qRj4/9s7DklgsFoyd79jA4/WuVkrMt0U+p9o4ARPyI0K6TBPipTTLTaWoKhWI+fF/wSp6f8YUvAYoUP4n3zpVK4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=VHEU8zv0; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="VHEU8zv0" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 9349F4E41522; Fri, 4 Sep 2026 18:13:29 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 67C9F6057F; Fri, 4 Sep 2026 18:13:29 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 0CC9C11C787BD; Fri, 4 Sep 2026 20:13:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545608; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=BX6HzhqbTWzSYL12wdwc/dDBHVdUwewc3tbQce5ggU0=; b=VHEU8zv0u5soAmlctAMc/ksCtOG3IZ0bVeSJHNEwxhZTdgIcGU4zI+j2+1jZANW4YN7dvW tY39bqSK30Dsu0Hs7j2rpJ6iaIRLfiJ2Yi6UWTx1GrecqHzD5+7r7IZplk67n4gui91/Ws Xr6sphPI9gFFpocJuLmS8QZcnkvQtlfi7C1LoYwKCTIZZvyOzO4A+ARKEjsRnm92G1CSBh ucaz9pkUammEpaVSOO9y0AxauNgQ2aVClQScgO52V8G8S7/zuuPF7C8OGsSMLOumeiElF3 F2m5g2fTzXzbdy2bu3diYSr5XggmOKcSnoMKsppTFNpS/mvdmfVbqDwlfHwcGA== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:45 +0200 Subject: [PATCH v5 08/25] mtd: spi-nor: Move the SFDP header structure to a C header Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-8-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 The sfdp_header structure is currently defined in sfdp.c, whereas the sfdp_parameter_header structure is defined in sfdp.h. In order to ease the reuse of this structure outside of the sfdp.c file, move this structure to the sfdp C header (.h). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/sfdp.c | 11 ----------- drivers/mtd/spi-nor/sfdp.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 823cda6874aa..95f47c0c9317 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -34,17 +34,6 @@ =20 #define SFDP_SIGNATURE 0x50444653U =20 -struct sfdp_header { - u32 signature; /* Ox50444653U <=3D> "SFDP" */ - u8 minor; - u8 major; - u8 nph; /* 0-base number of parameter headers */ - u8 unused; - - /* Basic Flash Parameter Table. */ - struct sfdp_parameter_header bfpt_header; -}; - /* Fast Read settings. */ struct sfdp_bfpt_read { /* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */ diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h index e8ed814c6530..2cbe22246c5e 100644 --- a/drivers/mtd/spi-nor/sfdp.h +++ b/drivers/mtd/spi-nor/sfdp.h @@ -149,4 +149,15 @@ struct sfdp_parameter_header { u8 id_msb; }; =20 +struct sfdp_header { + u32 signature; /* Ox50444653U <=3D> "SFDP" */ + u8 minor; + u8 major; + u8 nph; /* 0-base number of parameter headers */ + u8 unused; + + /* Basic Flash Parameter Table. */ + struct sfdp_parameter_header bfpt_header; +}; + #endif /* __LINUX_MTD_SFDP_H */ --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 63A7051E445; Fri, 4 Sep 2026 18:13:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545615; cv=none; b=WpJGiKPQry6PX8BegG9aOc1UulLP27Nrz2OTTzBY49wMujGFZoZyxtpfcokULKF6eqFyLMxIDybSp8S+jgy2AMl4MC+ZnvFZmPG23HQZQqcK8e4VoU4yBkt9KOtGBbUKi6dI+YdYUN/t9UiiklDie5CPyO9lytNhMXFKzket/Ek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545615; c=relaxed/simple; bh=e9Na8yqXbo8Mrmip4BI6lHUbI82d372LE0SeToe8ppE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qdg+8uHz4KwbkqVqn5eiEs2hrIr3Z/rxVYgQym3LQeb9XupRM3+T/h0OfTVVS/0A8OORVoqmGR9CzPkg+Uz0AQWDllOMzFmA6sLVi5UeXs1Zo300zucqaVhCDHKSQypb7UmmjFqAw1wQ4UVNqIZZeEEEoNUz6AiSNpRNmr83dYo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=DAr0TWvT; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="DAr0TWvT" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id DD1F54E41521; Fri, 4 Sep 2026 18:13:31 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id B03186057F; Fri, 4 Sep 2026 18:13:31 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B7D3011C78158; Fri, 4 Sep 2026 20:13:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545610; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Hqt+/88NUF/qb77dZgpUKJJCWtbSkZ9Fc6rtIcnbhOg=; b=DAr0TWvT042hR3ajMlsc8JEGYKUZhEhvDZsrtkd1c55WHzKag2mhFI6OqWwbYARat1b8p4 dlNPzTjhG6d2d9FuGw9QZpaYNMVtcpcdp2QMGzpRxDWbPmVsJPpq596ofYMx+LxfkGgF5p Yg48iO/Tnx/+ukVfOcbCZ6C4E/IBdqNkp9kZviSfF54rupg2xeXwH+XV3/z/eDuEDYiGiT IzqDKhUfN+rkeFTVCxJsK75hTWM2EGe5BrdWp4HKoIMviWAw/WmCOE7K51AFoXGz/gI7k3 i0F7Vk/IKV2CLgnwYRyMNewwTRsPwZKHXBZe8QSQQcwMgH78pfX7ueyKvPEMxw== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:46 +0200 Subject: [PATCH v5 09/25] mtd: spi-nor: winbond: Prepare introduction of W25QxxRV-Q/N parts Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-9-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision between the JV and RV families. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). They also do not require the multi-die fixups which must remain assigned to the JV chips. Finally, since they share the IDs but not the names, we must hide the names using a fixup. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/sfdp.c | 11 ++++++++ drivers/mtd/spi-nor/sfdp.h | 2 ++ drivers/mtd/spi-nor/winbond.c | 60 +++++++++++++++++++++++++++++++++++++++= +--- 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 95f47c0c9317..c21a6953db96 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -1715,3 +1715,14 @@ int spi_nor_parse_sfdp(struct spi_nor *nor) =20 return err; } + +/** + * spi_nor_sfdp_get_header() - retrieves the SFDP header + * @nor: pointer to a 'struct spi_nor' with a valid SFDP field + * + * Return: the cached SFDP header. + */ +struct sfdp_header *spi_nor_sfdp_get_header(const struct spi_nor *nor) +{ + return (struct sfdp_header *)nor->sfdp->dwords; +} diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h index 2cbe22246c5e..1e49ed548a7e 100644 --- a/drivers/mtd/spi-nor/sfdp.h +++ b/drivers/mtd/spi-nor/sfdp.h @@ -160,4 +160,6 @@ struct sfdp_header { struct sfdp_parameter_header bfpt_header; }; =20 +struct sfdp_header *spi_nor_sfdp_get_header(const struct spi_nor *nor); + #endif /* __LINUX_MTD_SFDP_H */ diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 063b85e041cd..9af4f21e82bf 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -24,6 +24,39 @@ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_OUT(1, buf, 0)) =20 +static bool is_w25qxxrv(const struct spi_nor *nor) +{ + struct sfdp_header *sfdp_h =3D spi_nor_sfdp_get_header(nor); + + /* + * W25QxxRV chips re-use the same ID as the W25QxxJV family. + * + * Chips are very similar, W25QxxRV brings mostly performance and power + * consumption improvements. The RV family does not require the multi + * die fixup. + * + * They can be distinguished based on their SFDP minor revision: + * W25QxxJV: JESD216A, minor revision =3D=3D 05h + * W25Q512/01/02JV: JESD216B, minor revision =3D=3D 06h + * W25QxxRV: JESD216F, minor revision >=3D 0Ah + */ + return sfdp_h->minor >=3D SFDP_JESD216F_MINOR; +} + +/* + * Since SFDP is populated after ->default_init(), the match functions usi= ng + * nor->sfdp as discriminant cannot be used for this specific early fixup. + */ +static bool winbond_jv_match(const struct spi_nor *nor) +{ + return !nor->sfdp || !is_w25qxxrv(nor); +} + +static bool winbond_rv_match(const struct spi_nor *nor) +{ + return nor->sfdp && is_w25qxxrv(nor); +} + static int w25q128_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, @@ -146,6 +179,22 @@ static const struct spi_nor_fixups winbond_nor_multi_d= ie_fixups =3D { .post_sfdp =3D winbond_nor_multi_die_post_sfdp_fixups, }; =20 +static int winbond_nor_partname_post_sfdp_fixups(struct spi_nor *nor) +{ + /* + * W25QxxRV parts re-use the JEDEC IDs of the JV family. Their name + * being a legacy field, it is kept for the already established JV parts + * but must not be exposed by the newer RV ones. + */ + nor->partname =3D NULL; + + return 0; +} + +static const struct spi_nor_fixups winbond_nor_partname_fixups =3D { + .post_sfdp =3D winbond_nor_partname_post_sfdp_fixups, +}; + static const struct flash_info winbond_nor_parts[] =3D { { .id =3D SNOR_ID(0xef, 0x30, 0x10), @@ -552,9 +601,14 @@ static const struct spi_nor_fixup winbond_fixups[] =3D= { { .fixups =3D &winbond_nor_fixups }, { .id =3D SNOR_ID(0xef, 0x40, 0x18), .fixups =3D &w25q128_fixups }, { .id =3D SNOR_ID(0xef, 0x40, 0x19), .fixups =3D &w25q256_fixups }, - { .id =3D SNOR_ID(0xef, 0x40, 0x21), .fixups =3D &winbond_nor_multi_die_f= ixups }, - { .id =3D SNOR_ID(0xef, 0x70, 0x21), .fixups =3D &winbond_nor_multi_die_f= ixups }, - { .id =3D SNOR_ID(0xef, 0x70, 0x22), .fixups =3D &winbond_nor_multi_die_f= ixups }, + { .id =3D SNOR_ID(0xef, 0x40), .match =3D winbond_rv_match, + .fixups =3D &winbond_nor_partname_fixups }, + { .id =3D SNOR_ID(0xef, 0x40, 0x21), .match =3D winbond_jv_match, + .fixups =3D &winbond_nor_multi_die_fixups }, + { .id =3D SNOR_ID(0xef, 0x70, 0x21), .match =3D winbond_jv_match, + .fixups =3D &winbond_nor_multi_die_fixups }, + { .id =3D SNOR_ID(0xef, 0x70, 0x22), .match =3D winbond_jv_match, + .fixups =3D &winbond_nor_multi_die_fixups }, }; =20 const struct spi_nor_manufacturer spi_nor_winbond =3D { --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8140551C350 for ; Fri, 4 Sep 2026 18:13:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545622; cv=none; b=KuoXy2ASopVb5fNKAMGw4jwFCRqGjKiFkPTp6y+kt9ZX2EYY0gbJXoLNjnUwbUoeYnfCtrLKrnKZVu7mXVsB4h78KG5XKs56gKC2FXKEu9umband9DVPnM4rvpSYcDa/hSYg7kwTIp3fq1z21jmD/CO5Eq19i8KN0YA4CQ7hD7Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545622; c=relaxed/simple; bh=iv/s7cyg5U5d/JUqwOSREcTPO74xtmbkFsfMpt0xqIw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=A1Qs7ck7mr1rmz6NUR00TLsaFCo+UyO//vCjZpRl2rh9HOHRMopKd4E8shV4cc3xjTO3KdCmJ+FvnibH29Jq2/4jT9n0XCsw5EVsXbcTDGyUDejtI6bg8BBETVOJfdXAHlh1giiFG1LgjoHuEiG2AtaB/4P76WkBVQfsSLG/rM8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Fs7bcVXm; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Fs7bcVXm" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 086194E41521; Fri, 4 Sep 2026 18:13:39 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id D03BC6057F; Fri, 4 Sep 2026 18:13:38 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 0ED1011C78705; Fri, 4 Sep 2026 20:13:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545612; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=FZNnPbNztZ4nwNywLEnE07ccojxkIbOZf30Xvpla9HA=; b=Fs7bcVXmkx1Xh2xzAJTv1yLYVyNaIILmDld7k9dAF9ACbcG0mWWrFaVYH3Va8rqsOr5d3J OF8GQNpvDp2AB3cw19siZREL6lqmj2TXuFZmUBetf49oQRF7u5zIJZYo0jVLPdHpHFvagC H/85SLdNjX2xZCZjvQ88c74WbWAbl5eQwJJK16vR/bbNGFh0sEDXLcg6h1qjeDZf4rc4cV bAYBfku092GttJd1efj4XvxuQVArr0JWakwU9KP/DJvVnslYa+0UA/MNEYSXLTv5xzFoA5 BF5ISAGzZlZjRwOfY/P2eVUVlqoNFPD8K4t4LnDGC7+Cvll/7lG+X+EE7gKApA== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:47 +0200 Subject: [PATCH v5 10/25] mtd: spi-nor: winbond: Add support for W25Q32RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-10-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4016 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0100ff00080117800000ffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f9ffffffff0144eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001432010183e314c2e96376337a757a75 f7a2d55c39f66dffe930f8800000000000002c0000000000f6f4ffff0f00 0000060d44bd27ed080d + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 2c0c54d6e360dae30b72615eac5f0faff59463aeb2237d46d08d6cfd77d6c9f6 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x03 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3b mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbb mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6b mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x02 1S-1S-4S opcode 0x32 + cat /sys/kernel/debug/spi-nor/spi0.0/p[ 84.112272] random: crng init do= ne arams name (null) id ef 40 16 00 00 00 size 4.00 MiB write size 1 page size 256 address nbytes 3 flags HAS_SR_TB | HAS_LOCK | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xeb dummy cycles 6 erase 0xd8 program 0x32 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 20 (4.00 KiB) [1] 52 (32.0 KiB) [2] d8 (64.0 KiB) [3] c7 (4.00 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-003fffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003fffff | unlocked | 64 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_read 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 4194304 (4M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x400000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_read 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003fffff | unlocked | 64 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x400000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_read 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_read 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_read2 9f76d5d40e1d8fc620967a019cc0cf223a3b11cf9c5bed9a02fb8e2c06b1c805 spi_test 831e9e5cc6efa7d3afe7b0584100549d93b9953d64ad237fd1df15f790f23ae6 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003fffff | locked | 64 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D4194304 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D64 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 4063232 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003dffff | unlocked | 62 003e0000-003fffff | locked | 2 + flash_lock -u /dev/mtd0 4063232 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003effff | unlocked | 63 003f0000-003fffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-003fffff | unlocked | 62 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-003fffff | unlocked | 63 + all_but_one=3D63 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 63 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-003fffff | locked | 63 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-003fffff | locked | 62 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 63 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003effff | locked | 63 003f0000-003fffff | unlocked | 1 + flash_lock -u /dev/mtd0 4063232 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003dffff | locked | 62 003e0000-003fffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 9af4f21e82bf..1a7522dad377 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -247,7 +247,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .size =3D SZ_1M, .no_sfdp_flags =3D SECT_4K, }, { - /* W25Q32JV-Q/N */ + /* W25Q32JV-Q/N, W25Q32RV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x16), .name =3D "w25q32", .size =3D SZ_4M, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EEAE151C350; Fri, 4 Sep 2026 18:13:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545629; cv=none; b=gVumuUWdnhRVugC+FbbkVRoOibAo+nHkT9m1/7mI+xnIvSNzqnBV5/SbmmUJtthSSMDiaTlRdiBNCxRT6LtQDYUs9gRaprTUUDMUYqOY8odLAfhcqTP+VGzTK7u+go7WTMmzId+NGWWiP3LJyAZmSMHfwE1GC/g0EaApgHnK8qo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545629; c=relaxed/simple; bh=UYZLKDIppEQSm3+ifWHGVp7rMOwTVxbPlZBtYixPyr4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FmEc9PYDP8VBqiHqF/6FaVaE5Fhgh6IS6EAgBCcIr412it4vOEtDmDX6GSRrSMEO/8CsmCBQ5plrl/M3v+tfSONLYv01L11Q4FIUImeC+W97PxiU2HPlZBOtL30mexrgaO+QHbZ4NBIlOg1j/xQ3LqHHpOOsmIXNAQ4jgCMF3Vs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=IuvbyRHM; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="IuvbyRHM" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 495761A19BE; Fri, 4 Sep 2026 18:13:45 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 1BE026057F; Fri, 4 Sep 2026 18:13:45 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 0241111C79355; Fri, 4 Sep 2026 20:13:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545620; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Jho9N70U/nMj8mJlp/0q4PC4US31j/rLLpnZeA/GSY0=; b=IuvbyRHMlJiNn478wC01Edn+nAdu+j5R/+sCHrNP/h+Lq5qkxxrXFpVQB6sx12CrQwukAe ZXZsw8BIMY1KQRNxvrVa8vQ54uEHZWuo4LWyZvMN2L7vuRAotN11gvlF+qjTvidFMJaZF9 qgbeNZkytjeagItFGfG7hK3PIMV44W/o6Bm7iTWd57a+7HITOXpKQLl8LhxTN4hZs9Ns9i SO2QcowZ8oGrSzSFFy06O88JXVwbCteUIU6ZmnZayqHlXbzmFCCZ3vldHh/LlE131ePwjq qDYcnu9JC0nXd7Wb5WssMO6tV2IKh/41nQbEOa/vClTTnJqWnaJ+XfGxo/ctvg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:48 +0200 Subject: [PATCH v5 11/25] mtd: spi-nor: winbond: Add support for W25Q64RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-11-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4017 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f3ffffffff0344eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d80000d639a50081d614c3e96376337a757a75 f7a4d55c39de6dffe970f9a50000000000002c000000000066ffffff0000 00000000000000000000ffffffffff0a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp c7fa99bdcdef9a930e609215704dd349dbed161487dee0ece8ea1b25d2d4dd25 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 40 17 00 00 00 size 8.00 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | SOFT_RESET | NO_WP |= HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (8.00 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-007fffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 7.803395] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_read eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 8388608 (8M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_read eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_read eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_read eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_read2 eca2ec05a4fbf9f14490a0147e43c8f3616298bf8f6e2b59f5c5e5076c1cfd02 spi_test 64f4a5c5a05eae4a6dffb9e76171d97328257a96110214f52222870681b7b28c spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | locked | 64 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D8388608 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D64 + ss=3D131072 + bps=3D2 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 8126464 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | unlocked | 62 007c0000-007fffff | locked | 2 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | unlocked | 63 007e0000-007fffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | locked | 2 00040000-007fffff | unlocked | 62 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 1 00020000-007fffff | unlocked | 63 + all_but_one=3D126 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 131072 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 1 00020000-007fffff | locked | 63 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | unlocked | 2 00040000-007fffff | locked | 62 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | locked | 63 007e0000-007fffff | unlocked | 1 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | locked | 62 007c0000-007fffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 1a7522dad377..a013234951f8 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -254,7 +254,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q64JV-Q/N */ + /* W25Q64JV-Q/N, W25Q64RV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x17), .name =3D "w25q64", .size =3D SZ_8M, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DC1751C34E; Fri, 4 Sep 2026 18:13:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545635; cv=none; b=OGjeNYMUMNTiAYDmOqSwQUQAFfrVJkawq9gp7TpZpjulCcqC9LTrOGQy99A1jxFp/sJUw+7p28jUZZ7NbUw7RxstDnUl9Sr+cXjFntyRX6rO8wa1jpMbI1xTVVZ8tb7U7NWn2BSLgk9iCy7MTdIMHztgqXLEwhi9k2bHtWDpEKA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545635; c=relaxed/simple; bh=ePlIJ9SpaqJwtHUt1aN/IlP5uN8b2SrHGwFotM6HkFk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=d2ZAqa57Pw9KN0XdF6ECh8x8EDl84SYsAfMCzHjLx40MypQ7pLZCozySD6hWpsIPY6g951EhiFnuq78U1jp0hSjAU6/SSYjgRA2FWibw5fnBAhVt0P2V1JB8c1U4D0qMW2YJB55QLOprW1013lMtNTqeWpSWas1zabdd3VEtzS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Hre+IcD5; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Hre+IcD5" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id A81954E41521; Fri, 4 Sep 2026 18:13:51 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 7C4756057F; Fri, 4 Sep 2026 18:13:51 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 6CCF511C78158; Fri, 4 Sep 2026 20:13:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545626; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Gs6vVGC6ZzX7C47iKNiTjsTWm9iauDbaCuRi1y/km98=; b=Hre+IcD5d+tayEFwajEah1rTQG7NmMKcNlwwzldIAasv7zVtkuRyU14eYmZ+k2AwWJKmM0 V2rrWQMZl6lz3y51PbsEUYhdWeoex1hRRFQOW79Y0MDHHBF83n4ydFsSpTBU5uDc9dWDyK f1OLCDYE5zgg2JSU3Hq/ml23+NG21ccMHka/tLX2+fDKGCSH28GkzeQicZVgAHwbTcHNSK emmYERiS3f7/fPziOzH4JD37D/OI6S7ZPPMLXrm+hbwRgIvwmiQq7NPWLtr+nqLZqaRoD3 NH9AeoShTRX4ShPIR6UN3v1fUZTDkEOpywlR9RzgptVFwSL1leFJXa8LCyJOCg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:49 +0200 Subject: [PATCH v5 12/25] mtd: spi-nor: winbond: Add support for W25Q12RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-12-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). This density wrongly advertizes its size and requires a fixup for that. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4018 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0100ff00080117800000ffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f9ffffffff0344eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d80000142a010186e114c1e96376337a757a75 f7a2d55c39f66dffe930f880000000000000ac0000000000f7f5ffff0f00 0000060d44bd27ed080d + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 94b52d6e903a2046e144eab0760384b6932c6fdbfec17eb7336f1778c3898daf /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x03 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3b mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbb mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6b mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x02 1S-1S-4S opcode 0x32 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 40 18 00 00 00 size 16.0 MiB write size 1 page size 256 address nbytes 3 flags HAS_SR_TB | HAS_LOCK | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xeb dummy cycles 6 erase 0xd8 program 0x32 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 20 (4.00 KiB) [1] 52 (32.0 KiB) [2] d8 (64.0 KiB) [3] c7 (16.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-007fffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 15.791564] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_read b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 8388608 (8M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_read b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_read b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_read b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_read2 b3260b68e0373cd253fc558fa9a5c89009d3edb2393f4110702318f69a6d74c2 spi_test 884cedd0494868db17c609edc62e2471ef344025e30cd511fa28b41b9b50e50d spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | locked | 64 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D8388608 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D64 + ss=3D131072 + bps=3D2 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 8126464 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | unlocked | 62 007c0000-007fffff | locked | 2 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | unlocked | 63 007e0000-007fffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | locked | 2 00040000-007fffff | unlocked | 62 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 1 00020000-007fffff | unlocked | 63 + all_but_one=3D126 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 131072 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 1 00020000-007fffff | locked | 63 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | unlocked | 2 00040000-007fffff | locked | 62 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | locked | 63 007e0000-007fffff | unlocked | 1 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | locked | 62 007c0000-007fffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index a013234951f8..38355d26bfd4 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -43,6 +43,20 @@ static bool is_w25qxxrv(const struct spi_nor *nor) return sfdp_h->minor >=3D SFDP_JESD216F_MINOR; } =20 +static bool is_zd25q128c(const struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header) +{ + /* + * Zetta ZD25Q128C is a clone of the Winbond device. But the encoded + * size is really wrong. It seems that they confused Mbit with MiB. + * Thus the flash is discovered as a 2MiB device. + */ + return bfpt_header->major =3D=3D SFDP_JESD216_MAJOR && + bfpt_header->minor =3D=3D SFDP_JESD216_MINOR && + nor->params->size =3D=3D SZ_2M && + nor->params->erase_map.regions[0].size =3D=3D SZ_2M; +} + /* * Since SFDP is populated after ->default_init(), the match functions usi= ng * nor->sfdp as discriminant cannot be used for this specific early fixup. @@ -62,15 +76,7 @@ w25q128_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt) { - /* - * Zetta ZD25Q128C is a clone of the Winbond device. But the encoded - * size is really wrong. It seems that they confused Mbit with MiB. - * Thus the flash is discovered as a 2MiB device. - */ - if (bfpt_header->major =3D=3D SFDP_JESD216_MAJOR && - bfpt_header->minor =3D=3D SFDP_JESD216_MINOR && - nor->params->size =3D=3D SZ_2M && - nor->params->erase_map.regions[0].size =3D=3D SZ_2M) { + if (is_zd25q128c(nor, bfpt_header) || winbond_rv_match(nor)) { nor->params->size =3D SZ_16M; nor->params->erase_map.regions[0].size =3D SZ_16M; } @@ -261,7 +267,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q128JV-Q/N */ + /* W25Q128JV-Q/N, W25Q12RV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x18), /* Flavors w/ and w/o SFDP. */ .name =3D "w25q128", --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7A3451D522 for ; Fri, 4 Sep 2026 18:13:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545638; cv=none; b=n5GICHyTyHJy9Y1WuzCpCOZDYSWLPIfmwSBOzAxUjno0cCuYunkgLHIvqxVa1GMd6FBLyh2Ivlq8cx4W50sUFFzwVCDz30W47+4CH+egzMcWVMNxJfUdWWr81yvZNt3bRYp+lT3zi7lBgunwBUQCxVxXmWlB/V+hyFannHZgr4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545638; c=relaxed/simple; bh=K4HgcdUK6zNRonBSUhXreZ/Cky9CX7Nl1kLnrwAt9wM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KyI2y012j4WFFXdy2hKVvhXZqEPiAoTqpy+yNI16JIa0EBUMhDzH+L9ewXVUxz3RVJgX3JhYjxRyhdpAwk4RtFGuX1lSqeuBjVsXYwsxmATS+ymdB+N8QYmE1hGkaCxhkNd9YlN/b0Kknb2aYKWG7Ymo5HrwCWCvM68L64IG/As= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Prrnf6D0; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Prrnf6D0" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 1B3B41A19BE; Fri, 4 Sep 2026 18:13:55 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id DD0216057F; Fri, 4 Sep 2026 18:13:54 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id C0E9C11C78705; Fri, 4 Sep 2026 20:13:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545633; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=q5YaU9adjEhd/4DB4BkxtbwGzepj9Mx2mPLuKpFzbk4=; b=Prrnf6D0/CusNpfEPQ/mUEeYLEZQoA9fUreS4SOOCOYm0osVmcHZYWNm4RM5EM+Ut7GNAa XzbstQcEtbQ/V8jdwUSlBPegLGrfTmkwvs4x3JS0gjPV7THFBDk+2PnZQiQL4e20LBBNca 7ZTIr/aRL8GXjOL3NsIvbJfabupmvzbIAO+DNw27/rtH/GXa/Zz5oVJKdsaz3tC7EvwEfA Gpj2YOMQmA3broXlBwipJg7SE/j0Nr4/Qcppv2A2Xs3DHKezE7J8XC5keFSmhTT3nSV0Zp HWY9bscVa0VHCm31qgIN7ThJzbmOdB3VVTXzQaVO9YkTva8ixJmBayUYURatIg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:50 +0200 Subject: [PATCH v5 13/25] mtd: spi-nor: winbond: Add support for W25Q25RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-13-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4019 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f3ffffffff0f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d80000d639a50081d614cee96376337a757a75 f7a4d55c39f66dffe970f9a50000000000002c0000000000f6ffffff0000 00000000000000000000ffffffffff0a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 05a7889e03e6de2ca02479e195acc717339481f2aa459df411fb9180d0e3998c /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 40 19 00 00 00 size 32.0 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (32.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-01ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01ffffff | unlocked | 512 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 24.169256] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_read ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 33554432 (32M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x2000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_read ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01ffffff | unlocked | 512 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x2000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_read ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_read ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_read2 ad25f48ad5b35e95d6055cd54fef93c6ad33c389907a8e494a9807e4787f8db9 spi_test 04a89ca2d9ae1bda059af80fb9d84b44e49a2a5ef1f8764254d1d80e533917ec spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01ffffff | locked | 512 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D33554432 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D512 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 33423360 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01fdffff | unlocked | 510 01fe0000-01ffffff | locked | 2 + flash_lock -u /dev/mtd0 33423360 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01feffff | unlocked | 511 01ff0000-01ffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 25165824 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-017fffff | unlocked | 384 01800000-01ffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-01ffffff | unlocked | 510 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-01ffffff | unlocked | 511 + all_but_one=3D511 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 511 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-01ffffff | locked | 511 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-01ffffff | locked | 510 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 511 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01feffff | locked | 511 01ff0000-01ffffff | unlocked | 1 + flash_lock -u /dev/mtd0 33423360 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01fdffff | locked | 510 01fe0000-01ffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 38355d26bfd4..4b6387a5fb43 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -275,7 +275,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q256JV-Q/N */ + /* W25Q256JV-Q/N, W25Q25RV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x19), .name =3D "w25q256", .size =3D SZ_32M, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E2F351FCD8 for ; Fri, 4 Sep 2026 18:13:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545641; cv=none; b=haJT4iA2btL5RVLUU8skKHlfbcJxL1avMbDG92dHErP8wk3Eypbxg6RNwhs5NJ50DvhXk+Z+nGtqpBcSmJF/UhaUcLS1hnr/t4hlV/Jr6ohr4FmrBqL9AVIkieOYX0WFbUIyVLMsSk7APaJ3DsXvGXj2QQk399Fo8pdm66joDp4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545641; c=relaxed/simple; bh=UPMQis8qn1xvQafAY5/xPY/gAJ1V+eKRjE6JFxBK/7Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QB5SVg/biONBpoTFcWMY2hbi2AsHhGLSH8Z67Hora67FbBEmdLWbHVENcfveBbfsLHQJhctAm36uHv7qzbjcmM1eWy+Yvx3hm5hexaJ6GnZY1sxKvxHdj+xO+o8jzAXZ9n8OcGC8SPsn9C7Fa7lYcqfrh9ojJBzgMu+oA+JoBB0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=iAbplt1y; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="iAbplt1y" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id A24094E41523; Fri, 4 Sep 2026 18:13:57 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 758C56057F; Fri, 4 Sep 2026 18:13:57 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 1DEB211C7931F; Fri, 4 Sep 2026 20:13:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545636; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=rp9sjhGrP5+nQbI8Mum3r1q1JZNj++X4gde4KQj+tl0=; b=iAbplt1y+Cl18sj/k9JHCu9Aaj8jgTd7Wj8ev0wYwp2ElBAkhzUnBT+wZfShrIImx5nxTx P9oHFkDHtZblweXAb+Apodm6ZEknkIRqMF51twLYA4kBUkd9jkpecD1tywlRZdU4CAsFxU 7CChAVTQ08/1Ll3012wzrBR+echFrzXttuy6QCtR5uMDO6w9U3oavJ45kaL+FbMG+lFuiC f3C978lfII0780eDhXlaRXsjYvpOs0ck5QJWa96TG3i6fL4Muvy0dG0gE+M120jlOOvEFy YU9EEYAMW983JE8/8kG15zNYm3/NSGpge02ov6My1ny9V6H2MRElMWw0h66hXQ== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:51 +0200 Subject: [PATCH v5 14/25] mtd: spi-nor: winbond: Add support for W25Q51RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-14-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4020 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f3ffffffff1f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001602a60081e214dde96376337a757a75 f7a4d55c39f66dffe970f9a50000000000002c0c0000000066ffffff0000 00000000000000000000ffffffffff0a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 74d21fecc7faa297b3f77f1136b1dc53f78b2a432629e226675b6384153fd9f9 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 40 20 00 00 00 size 64.0 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (64.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-03ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03ffffff | unlocked | 1024 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 25.427347] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_read cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 67108864 (64M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x4000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_read cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03ffffff | unlocked | 1024 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x4000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_read cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_read cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_read2 cd699acc82353b7769b98547efed68d5300854ed0bbc84bf831b07937bf941a5 spi_test f506020804f91fb750e8250e091fb2f732319221a645ed575e1b6ed3553d584c spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03ffffff | locked | 1024 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D67108864 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D1024 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 66977792 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03fdffff | unlocked | 1022 03fe0000-03ffffff | locked | 2 + flash_lock -u /dev/mtd0 66977792 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03feffff | unlocked | 1023 03ff0000-03ffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 58720256 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-037fffff | unlocked | 896 03800000-03ffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-03ffffff | unlocked | 1022 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-03ffffff | unlocked | 1023 + all_but_one=3D1023 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 1023 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-03ffffff | locked | 1023 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-03ffffff | locked | 1022 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 1023 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03feffff | locked | 1023 03ff0000-03ffffff | unlocked | 1 + flash_lock -u /dev/mtd0 66977792 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03fdffff | locked | 1022 03fe0000-03ffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 4b6387a5fb43..b7b74908fedc 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -283,7 +283,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, }, { - /* W25Q512JV-Q/N */ + /* W25Q512JV-Q/N, W25Q51RV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x20), .name =3D "w25q512jvq", .size =3D SZ_64M, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8BA4521205 for ; Fri, 4 Sep 2026 18:14:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545644; cv=none; b=jokQBU4kNoWqdgWdyp9XF3QreKdyKI3ZxW3PUB01sg/ctCjdFqW8tMFFfNrAtHMyuv3g7kgYv8ir2MkqG2a5E/nbM/TDGzl8+57aPxA8h011DTFhXpiHQznWQZxW7akF+duvvb4Uv7G8eQGb8SPn9iDIFiUCgXNr/HtBo0nMEHI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545644; c=relaxed/simple; bh=UQHuUL2F8VbvnWwSl4BY6Nd3KOZV0HJ1PHFMQwjmvRA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KQ3lg7EgWggOfufFqJkKwkl0g8toIFcf45vhmOfkk1HM0waKG+LDiEVhLe0HsHNIgMb4jGWFReKX5dUSVMVNJnHfq76/SxktpVM1bTfNMm5G6+taRZMZ8NM3AoKEXoklK1yjMjJ2u+JDahNQyGnsr4T1yv6axAcODcedeZN0nmk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Ljl+qKqh; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Ljl+qKqh" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 1DBFB4E41522; Fri, 4 Sep 2026 18:14:01 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id DFE606057F; Fri, 4 Sep 2026 18:14:00 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id BDD8B11C78767; Fri, 4 Sep 2026 20:13:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545639; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=YtFx4O5EtyamBMKLOEMxmfWtB7+YQ4OCSNYLy/WEl94=; b=Ljl+qKqhxKox5SLt8TUsDkkVAAp1q9TgpLGOCA4WWjlD4MAHChgiFekr7Q/LGC/uEPqvcS JeoaAyId5QChTaKD/2wotiDTrjoikM4LnLqRkfMmaxqMmBe/t/64pRQ0qXfOL+c4RBvi/W 6Zd3XoTwXHxlH3W+YqH5X++PWgDbPOBnlXMveLkj7XpqBDd1NAbEsxsuCnhDJjI0s4hQmS lLD0JcClOVInOJ85IARw2uEJ6W8nyuDq/6UtWQFxHm4/kL0slOpR5KTuMd2GfK+bPVUtKq a9MAeM4xvGTg0SCAiKpJFaRnrEYxrWxzoj8x6KxpBB2eFNkJboTTnDVS3jvI7A== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:52 +0200 Subject: [PATCH v5 15/25] mtd: spi-nor: winbond: Add support for W25Q01RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-15-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4021 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f3ffffffff3f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001602a60081e214dde9e378477a757a75 f7a4d55c39f66dffe970f9a50000000000002c0c0000000066ffffff0000 00000000000000000000ffffffffff0a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp f4ae2490acac0f9120cd05dc7778683df1cb61f2a05705549e80a427a8747a52 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 40 21 00 00 00 size 128 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (128 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-07ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | unlocked | 2048 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 40.768042] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_read 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 134217728 (128M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x8000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_read 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | unlocked | 2048 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x8000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_read 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_read 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_read2 197211dd852288d6e0dd6bc00b6c4c10a6981623b804a58b5c532246216ff1e9 spi_test 41e82fe34a7ce60c98a24651e27333abdcbe318d5efd95d0db01d35ed5c092ab spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | locked | 2048 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D134217728 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D2048 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 134086656 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07fdffff | unlocked | 2046 07fe0000-07ffffff | locked | 2 + flash_lock -u /dev/mtd0 134086656 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07feffff | unlocked | 2047 07ff0000-07ffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 125829120 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-077fffff | unlocked | 1920 07800000-07ffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-07ffffff | unlocked | 2046 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-07ffffff | unlocked | 2047 + all_but_one=3D2047 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 2047 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-07ffffff | locked | 2047 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-07ffffff | locked | 2046 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2047 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07feffff | locked | 2047 07ff0000-07ffffff | unlocked | 1 + flash_lock -u /dev/mtd0 134086656 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07fdffff | locked | 2046 07fe0000-07ffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index b7b74908fedc..4a6d4292fdb2 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -291,7 +291,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, }, { - /* W25Q01JV-Q/N */ + /* W25Q01JV-Q/N, W25Q01RV-Q/N */ .id =3D SNOR_ID(0xef, 0x40, 0x21), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 859D051474B; Fri, 4 Sep 2026 18:14:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545648; cv=none; b=I8OYy7u/VbU9ryk8yMeXeJxbypb36lh2HayNAhO0/0Q8VRDgpN8HmOjnybEMzDmXmYX1f061tBqS2pHca8Ok26iGskN1032LlQfIZKjysOTykQb6HcVsoBR/cwsC9YXujiEQpM4ESi2VXqCnCaiydjuZXjLSmYYCOwieD4tAzKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545648; c=relaxed/simple; bh=4+rjf2O+nOuZbiMRnGaN8561D3nKZyJrulB160NKmTI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XSrv3uQgDJDd8GL7mEkYbl7WENFRzQsTVKiZvKBGqgLX6vau4z9pxiG6CCPqPdlHFHy8IToa+J0SclCY84xmO0XQrr3DR8pdgLAKWGLQbJ5zt4RO+jFACpCEb6vEG63tce8f50xSbbbRQmd3pZT52qjlNgwAPLQyOjfNxU6o5XQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=gR6ROCZI; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="gR6ROCZI" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id DDAC14E41521; Fri, 4 Sep 2026 18:14:04 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id B10DF6057F; Fri, 4 Sep 2026 18:14:04 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 1EBFC11C78158; Fri, 4 Sep 2026 20:13:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545642; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=mky+QgCkcF4wW1IFBUfXutPfLyMAugM/GhiKs3ZGlBM=; b=gR6ROCZIIpXUC4MdUMvXx2zLkKQ4793B5ghILeVEffc2eW4AkJh26SDbiSVLykqa5xOsos giCBaZOC3Dr9mQ1s1hD2S86dA+9k1G8/Eaozt+AkkotpFOkfcBeIOUVFV+SdS9hSCHPj/z zegIAG3gH1mQswtFLVw6QOGY8Z4qR56NnkK5g7bJo52ZaByyBW8iKbytfX8XyEqiFyi3yo fYrXh1nEla8HxbEkdga7sY/Bz/BuJYZsvLxnk6uTjvqsc9IqwPZsu7Ls9pwcJrzDL/AA9F UitFG9mIyrxHzSXTL0+x5HAWO1fujEvVmswMhPO9j1P9a35hEW8xW0eL52EDrw== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:53 +0200 Subject: [PATCH v5 16/25] mtd: spi-nor: winbond: Add support for W25Q02RV-Q/N Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-16-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef4022 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f3ffffffff7f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001602a60081e214dde9e378477a757a75 f7a4d55c39f66dffe970f9a50000000000002c0c0000000066ffffff0000 00000000000000000000ffffffffff0a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 623c2663966d70cc6418f65db6c182a7d9146e15b190263f46ea81d9a934866c /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 40 22 00 00 00 size 256 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (256 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-0fffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0fffffff | unlocked | 4096 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 14.840645] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_read c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 268435456 (256M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x10000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_read c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0fffffff | unlocked | 4096 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x10000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_read c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_read c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_read2 c1c18ff55582ccab09e88cd6e6c14fe46c601c6461cb0012ac79949615f6c682 spi_test 28e04c28384aafd356a3e545ba79bf02e995cfb1e765ec663e35924c3f92b88d spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0fffffff | locked | 4096 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D268435456 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D4096 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 268304384 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffdffff | unlocked | 4094 0ffe0000-0fffffff | locked | 2 + flash_lock -u /dev/mtd0 268304384 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffeffff | unlocked | 4095 0fff0000-0fffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 260046848 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0f7fffff | unlocked | 3968 0f800000-0fffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-0fffffff | unlocked | 4094 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-0fffffff | unlocked | 4095 + all_but_one=3D4095 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 4095 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-0fffffff | locked | 4095 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-0fffffff | locked | 4094 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 4095 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffeffff | locked | 4095 0fff0000-0fffffff | unlocked | 1 + flash_lock -u /dev/mtd0 268304384 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffdffff | locked | 4094 0ffe0000-0fffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 4a6d4292fdb2..cd20622916b7 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -295,6 +295,11 @@ static const struct flash_info winbond_nor_parts[] =3D= { .id =3D SNOR_ID(0xef, 0x40, 0x21), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, + }, { + /* W25Q02RV-Q/N */ + .id =3D SNOR_ID(0xef, 0x40, 0x22), + .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | + SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, }, { .id =3D SNOR_ID(0xef, 0x50, 0x12), .name =3D "w25q20bw", @@ -611,6 +616,8 @@ static const struct spi_nor_fixup winbond_fixups[] =3D { .fixups =3D &winbond_nor_partname_fixups }, { .id =3D SNOR_ID(0xef, 0x40, 0x21), .match =3D winbond_jv_match, .fixups =3D &winbond_nor_multi_die_fixups }, + { .id =3D SNOR_ID(0xef, 0x40, 0x22), .match =3D winbond_jv_match, + .fixups =3D &winbond_nor_multi_die_fixups }, { .id =3D SNOR_ID(0xef, 0x70, 0x21), .match =3D winbond_jv_match, .fixups =3D &winbond_nor_multi_die_fixups }, { .id =3D SNOR_ID(0xef, 0x70, 0x22), .match =3D winbond_jv_match, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7180521224; Fri, 4 Sep 2026 18:14:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545650; cv=none; b=CM/eXYNnTJKIjO+miqspK0y1lcfyKwciK42re1O0T4Wy2/Z3kMTY2ur3RkPS/qgvqEdTMXoPJroxWQWN28CUJj9Ixitt87FxXqqktqqKv+GUgS/D37st4hTsxkQf6PO8UbT3X73TppaQRtFfts5AZtzQejH4edQNDgRAhty12wg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545650; c=relaxed/simple; bh=UhIg/r+XHFx1YT2WB715O2DN40C7Uz7gked1oNboJZs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MtX9wp0z05HROw/MMlhdvu7EhP8BO46JqNyPCew07u4sBcudzSbYcftbr4jpQWru3UPmg81gjwfBKlyqclpPj9cJq1USqgYxx4tZg4JaHHiMWtTvj5raiQGUwzBueTY+UDYyNsMGL02LrlCpiqw1DzqHTCzfSLb1bvylyT7Zz5k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=Ej778Hok; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Ej778Hok" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 46F024E41524; Fri, 4 Sep 2026 18:14:07 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 14AFF6057F; Fri, 4 Sep 2026 18:14:07 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id CB09311C78767; Fri, 4 Sep 2026 20:14:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545645; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=B6p7y5wSXRzxoqyJP4VFZj1Zp3M7f088c983QB9BLhQ=; b=Ej778HokGTrRyd40hR6z2i1unsN7rL9iaLm9JmpSksjiYW3sq12s5fHc8S59/SuZ9P/Nif uX2yw0OfrY19ct4n2h4A2dBdpQvfw8pmgwNBQz4ux5nIZ6RbuxeS20QTnGuDyDACcschcS qpzHSCuQ40Js0yMZK7Gwra037PgnjdQzZ7PmELQPH8WT39Gt40ZBj+eifw9k3IRhWNcZXM 9LY9UooPu6aEum4/co/0e3lVfS9p6BzYoG1/IeN92d6HhNnxlDqU4uub7a0rx+dvSbeh17 fy8k0L3sJsEgw7fKAmckiq1iyhq0v2PNfQjH7fsrUByBIPDmCSQLnI2tFaAvyA== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:54 +0200 Subject: [PATCH v5 17/25] mtd: spi-nor: winbond: Prepare introduction of W25QxxRV-M parts Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-17-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision between the JV and RV families. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting The new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Since they share the IDs but not the names, we must hide the names using a fixup. Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/winbond.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index cd20622916b7..1b06d10d0f6b 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -618,6 +618,8 @@ static const struct spi_nor_fixup winbond_fixups[] =3D { .fixups =3D &winbond_nor_multi_die_fixups }, { .id =3D SNOR_ID(0xef, 0x40, 0x22), .match =3D winbond_jv_match, .fixups =3D &winbond_nor_multi_die_fixups }, + { .id =3D SNOR_ID(0xef, 0x70), .match =3D winbond_rv_match, + .fixups =3D &winbond_nor_partname_fixups }, { .id =3D SNOR_ID(0xef, 0x70, 0x21), .match =3D winbond_jv_match, .fixups =3D &winbond_nor_multi_die_fixups }, { .id =3D SNOR_ID(0xef, 0x70, 0x22), .match =3D winbond_jv_match, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 66F27521235; Fri, 4 Sep 2026 18:14:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545653; cv=none; b=XrOAt1si+ydev05/sLpzmYDZCHuovx2QKQx3t/6SzvB9aivdU62Rbbw8j3byJXlLoMyCV/l3Df16ZcUWDV4fbOb4y/csgMgryBHbhYvugD4xYF++jMD9MGAbEZFJUmTX4t2I2xlJ6wieo0oQT3WmyB6ODC6hfdYj6ieRDEurH/Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545653; c=relaxed/simple; bh=JMyNJ+FYFwVdx8NE24/uBSsG4wkTaCNukLvsxoENqds=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rjAklTLv26fX9yuGf48ToyBAWunPqtlX7p1q59lLU3eJ4xp+cYW6Lg5mZS5hV3sIuoltWUYuAMNTy8xLk7JzUlKl35ZqsmNPcZj61veynIInTytlpFKK5mRrpWI0SI9qE+QxDB2A624P1MWTdCg/z3tKNYYwER2wBI3+miC1rOU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=PZbP9JV6; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="PZbP9JV6" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id BF2681A19BE; Fri, 4 Sep 2026 18:14:09 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 92BEE6057F; Fri, 4 Sep 2026 18:14:09 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 5986C11C78705; Fri, 4 Sep 2026 20:14:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545648; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=lWcfzaRbcFAWuXUugz8ocyLvRHCYGnfMdNocLzp7AEM=; b=PZbP9JV68cMgXGQWmWHxBK0NeLzuVpu6ynNZIyEWoGpZelBJidJR9wAGEVjn2Mt+tyHhDb q/rLQzrm/llqRJNBxFeaQbqZ5KLnBpj3tJb2Yw4U76Ss0vXUem6Xz4sl0PMNBV0apBqBRF jy14SzmmegvSLJawjgmzW2c2jb3ADEDrYwCuRgYwyEbITeV2d49kzNnZJp/SR5Hdju8x2d 0vbJJo5N5SrgE3gITV6G+/IuCLaiAfOVIEXpcQizOhMLGBeoNPFJ/Lp5h2bXn/GeG48Joj iknwlmbJjRq+5xosHv34L/H5T1KOt6/E1U/6lrpXzvzUU5hbMuV4v8SlFZrdPw== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:55 +0200 Subject: [PATCH v5 18/25] mtd: spi-nor: winbond: Add support for W25Q32RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-18-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7016 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0100ff00080117800000ffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f9ffffffff0144eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001432010183e314c2e96376337a757a75 f7a2d55c39f66dffe930f8800000000000002c0000000000f6f4ffff0f00 0000060d44bd27ed080d + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 2c0c54d6e360dae30b72615eac5f0faff59463aeb2237d46d08d6cfd77d6c9f6 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x03 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3b mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbb mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6b mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x02 1S-1S-4S opcode 0x32 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 16 00 00 00 size 4.00 MiB write size 1 page size 256 address nbytes 3 flags HAS_SR_TB | HAS_LOCK | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xeb dummy cycles 6 erase 0xd8 program 0x32 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 20 (4.00 KiB) [1] 52 (32.0 KiB) [2] d8 (64.0 KiB) [3] c7 (4.00 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-003fffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003fffff | unlocked | 64 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 15.820716] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_read c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 4194304 (4M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x400000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_read c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003fffff | unlocked | 64 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x400000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_read c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_read c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_read2 c73e2828631d8f745c118e706e4ea7179328e6e03e49cb2d30784eb73ff6167f spi_test d26d11f7de825c1f2397e52307997c9befb07b93e6cd520d15a87d06abef2529 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003fffff | locked | 64 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D4194304 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D64 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 4063232 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003dffff | unlocked | 62 003e0000-003fffff | locked | 2 + flash_lock -u /dev/mtd0 4063232 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003effff | unlocked | 63 003f0000-003fffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-003fffff | unlocked | 62 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-003fffff | unlocked | 63 + all_but_one=3D63 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 63 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-003fffff | locked | 63 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-003fffff | locked | 62 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 63 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003effff | locked | 63 003f0000-003fffff | unlocked | 1 + flash_lock -u /dev/mtd0 4063232 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-003dffff | locked | 62 003e0000-003fffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 1b06d10d0f6b..6b58be6f3e7b 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -366,7 +366,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q32JV-M */ + /* W25Q32JV-M, W25Q32RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x16), .name =3D "w25q32jv", .size =3D SZ_4M, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F6B552121E for ; Fri, 4 Sep 2026 18:14:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545656; cv=none; b=q8lLisDx5AVopXAL4LVUwLpfU/PpeocEumMKwoTISt4Rk9fXzL8lXsTbCvprTDvPuMFENYHt59qveKzD/ruvfSAEXncQ22L7AJjP3BLqTy+wgkEIXKuNX0XWLljqT9hb12gvG5REZRfNh4AakTA4l8IDoLWSBqajqIeXLjX+EXI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545656; c=relaxed/simple; bh=DaL+UNOjNqJMMPrcFF/HsCV9vFip9h65Om5Y+zZmjvs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jwgV+3dYsjU78omuBILVahCBcP0tAk0/sNKwcAQlD9Zol5oc+9ur1MQM1QqNCWNPF1Xmlb4z2xtHDZQhm2jUicnpsGb4Ri0LP8UGplbVDL5mf+C12E7mIwwnY+TzElaQA+hRWq3VW9X1IpMBKAj1YaNTqNMcS1e5cSuy//Cvz9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=KPogXJB+; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="KPogXJB+" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id B5C354E41528; Fri, 4 Sep 2026 18:14:12 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 8225E6057F; Fri, 4 Sep 2026 18:14:12 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id BB12211C787BD; Fri, 4 Sep 2026 20:14:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545651; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=dhakD9DNVLNy+voy8eveaGdNfQdaRDWQEQ3wJNY5bxo=; b=KPogXJB+m8re/2mlgmdy7rfXg4nXdw9Txg98+lm90fN/S8uJsr9DQrebCk54w3m57ctxtT 73nnvOf6eJcwW3b5Il2OyTttcibxDoROYEAJoxxy/rP4u7zfkxmisNm14S81NrMaRkHIbR qaGm7poSZ7q8v11aqpY6vlE6SAzKZAfGCvS1sJNcViUjSryAhnO8Ad1Kv4JYtwF22zcZF4 DkxdbAHlPlUREluL6E+2f2fvFATxwREHCEQ3FHDQnQxqboeze6Ex81ig6H6TMwaf7v3I7E OTMzqZOBXbwmdTJvZETbRCGOdkgtyHSinZuugBwsvxvaLAUUb+JzD6DcD9Ou1A== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:56 +0200 Subject: [PATCH v5 19/25] mtd: spi-nor: winbond: Add support for W25Q64RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-19-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7017 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff0344eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d80000d639a50081d614c3e96376337a757a75 f7a4d55c39de6dffe970f9a50000000000002c00000000006655ffff0f00 0000060d44bd27ed080dffffffffff8a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp ef6c5eb61fa86c6daac85436446b97ca078a46e4cfd4c0fed4c9f9400d79fa86 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 17 00 00 00 size 8.00 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | SOFT_RESET | NO_WP |= HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (8.00 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-007fffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 15.931750] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_read d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 8388608 (8M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_read d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_read d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_read d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_read2 d4a37ad2760e69823409d7e9321471b7f7ed6728d40f7f15329921fbe7393db6 spi_test 154432cc7e89d18c1e4ddb1604dfd2a0038c75aa5521a74808944ce19a320a42 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | locked | 64 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D8388608 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D64 + ss=3D131072 + bps=3D2 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 8126464 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | unlocked | 62 007c0000-007fffff | locked | 2 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | unlocked | 63 007e0000-007fffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | locked | 2 00040000-007fffff | unlocked | 62 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 1 00020000-007fffff | unlocked | 63 + all_but_one=3D126 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 131072 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 1 00020000-007fffff | locked | 63 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | unlocked | 2 00040000-007fffff | locked | 62 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | locked | 63 007e0000-007fffff | unlocked | 1 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | locked | 62 007c0000-007fffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 6b58be6f3e7b..cff6d3f07ed9 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -373,7 +373,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q64JV-M */ + /* W25Q64JV-M, W25Q64RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x17), .name =3D "w25q64jvm", .size =3D SZ_8M, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4887E5221DF for ; Fri, 4 Sep 2026 18:14:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545660; cv=none; b=R8C6GewUYW8NCjD6StfsZOwldP9d8xIpdivBhl+eBo27r/b3M3DjMlrgCfjf17rJ5xS7M7jpiPxU3RwXKvreFbrkrOLk4uFYtiBuFv/XLIpO3FWsnyofYJTZ0F1cOLt5HQQhInd9fJkSb0UhuBhq831Orsany5NBZG+NWIf6TYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545660; c=relaxed/simple; bh=enN/s45gZw8ed0yqPNavz4pacShfqvNaOzLm6CJE400=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OLXIljzQpVWTlVhd50kXNS4/UkxJufkRfg7pFnyqwYmh9kRJVmgvbrCDXbIhBwL1Pd1XOpGu6WKh0D3PlVUPE95K95nyva0uGGlJhd+Qrr2Ucb2INGAnnNhZrHX8zwpPgiVXasiLJ3CgWOeTGlPIOz4myr1CNo+SYrJaFIOKZkg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=mU3yD6v3; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="mU3yD6v3" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id AFEAA4E41522; Fri, 4 Sep 2026 18:14:16 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 8226A6057F; Fri, 4 Sep 2026 18:14:16 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A041111C7931F; Fri, 4 Sep 2026 20:14:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545654; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=kyoN0O4eHIo4PQKOIhlmYFn8gVA0agNvG/fCT5DjybM=; b=mU3yD6v36umok76z32RBJXD3iZOXAHvnxuX2W9JbzPO4FWUQy4AWjQk69Vxut4gIToDFL1 YRRstVK/iX2uZHnua2HN5QVBXrD0RUQf7Ftzio9OndzUeFtDYh43WId2b5MkxAFgMz+VgU QZYyNEBTRVnxZHk3KNJ0JpMTA4f//ln3BxCDqYFm1P2H8p4V5mN9JwXrDicHww3V+5RYVb Kl/E7qcKRnkzFW0U9EPqgGL9SYebHcZC5tW5bL9kMiOkRAF4L1SiWNIoxMREYQ1M3wU4kS regotWcg/Pr3u3ryROT0vFzznJyTTVFDu6WE/Hyvw3UKXZTgOhVgSwoGufcTSg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:57 +0200 Subject: [PATCH v5 20/25] mtd: spi-nor: winbond: Add support for W25Q12RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-20-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). This density wrongly advertizes its size and requires a fixup for that. Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7018 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0100ff00080117800000ffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520f9ffffffff0344eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d80000142a010186e114c1e96376337a757a75 f7a2d55c39f66dffe930f880000000000000ac0000000000f7f5ffff0f00 0000060d44bd27ed080d + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 94b52d6e903a2046e144eab0760384b6932c6fdbfec17eb7336f1778c3898daf /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x03 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3b mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbb mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6b mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xeb mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x02 1S-1S-4S opcode 0x32 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 18 00 00 00 size 16.0 MiB write size 1 page size 256 address nbytes 3 flags HAS_SR_TB | HAS_LOCK | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xeb dummy cycles 6 erase 0xd8 program 0x32 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 20 (4.00 KiB) [1] 52 (32.0 KiB) [2] d8 (64.0 KiB) [3] c7 (16.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-007fffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 28.249430] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_read 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 8388608 (8M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_read 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | unlocked | 64 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x800000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_read 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_read 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_read2 48b1df493c0c35b1c6c8a50880c6e10adcd103c383a7324033cb760d20d9acf0 spi_test df6c52ecc59473c5ed9bd10a0479b52ee248adbf7d032aa7cde35e86acd461ca spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007fffff | locked | 64 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D8388608 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D64 + ss=3D131072 + bps=3D2 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 8126464 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | unlocked | 62 007c0000-007fffff | locked | 2 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | unlocked | 63 007e0000-007fffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 4 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | locked | 2 00040000-007fffff | unlocked | 62 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 1 00020000-007fffff | unlocked | 63 + all_but_one=3D126 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 131072 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 1 00020000-007fffff | locked | 63 + flash_lock -u /dev/mtd0 131072 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0003ffff | unlocked | 2 00040000-007fffff | locked | 62 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 126 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007dffff | locked | 63 007e0000-007fffff | unlocked | 1 + flash_lock -u /dev/mtd0 8126464 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-007bffff | locked | 62 007c0000-007fffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index cff6d3f07ed9..2f2c79710241 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -380,7 +380,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q128JV-M */ + /* W25Q128JV-M, W25Q12RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x18), .name =3D "w25q128jv", .size =3D SZ_16M, @@ -620,6 +620,7 @@ static const struct spi_nor_fixup winbond_fixups[] =3D { .fixups =3D &winbond_nor_multi_die_fixups }, { .id =3D SNOR_ID(0xef, 0x70), .match =3D winbond_rv_match, .fixups =3D &winbond_nor_partname_fixups }, + { .id =3D SNOR_ID(0xef, 0x70, 0x18), .fixups =3D &w25q128_fixups }, { .id =3D SNOR_ID(0xef, 0x70, 0x21), .match =3D winbond_jv_match, .fixups =3D &winbond_nor_multi_die_fixups }, { .id =3D SNOR_ID(0xef, 0x70, 0x22), .match =3D winbond_jv_match, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79FCC51E432; Fri, 4 Sep 2026 18:14:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545662; cv=none; b=qZi7G94g+vlelRGR6krFGSagIPZ11A5ur201GF14BkKBfM7FR8Yg2HwbcXQW9XOSrFw9L7G+R6u/zkQpEB/Fi5RDxLZ0g/vCOWatzUHvfYDlXVxDCa8+QTd3JEi3TDaTPXAx/mPTVmO/gbJBwT+wByWg3V5s7ggrEMVGVs8dnc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545662; c=relaxed/simple; bh=N5DtCcqGFDmud3wVV1CtmYEbqL+tAGEGdXQ9U5vhQo8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PQ+NtgRtm74M6gvj95KpWlP0fLKxbQtuQmpUIE7AhqNcPEUcoW5ANfkY3BfnXYavxUj+ysYmkPllATL58j91zSRiS6Z1WbyuS1q6uZM2qC4kL9AOfMGwAyvkneSS3AWArRVY0NvHrqMrHdbZQKuwJ32hUvCT8c14U7dmM9NuUMg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=pbellka2; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="pbellka2" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id F1E801A19BF; Fri, 4 Sep 2026 18:14:18 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id C5A216057F; Fri, 4 Sep 2026 18:14:18 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 113C011C78158; Fri, 4 Sep 2026 20:14:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545657; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=jwg87BIfX5ZRwJIZVXo7cBlj+dLYYFT+h6ZsJd7dYz0=; b=pbellka2U1BTKXw97um377lAKKDio/2KH7AR0YirY3Y6Xq59tB5M7NkKiZALkgj2ZrTX1h NECgEAYOLV3cnVn8yUvCWQ4mw0DFbUJ8RxGILq7uTHjSKIKsnbvmde2rCRbQBHQz3XQ9Pw U8FkzMEpMN9NEdBJda6zzUQhBngWhMXHHNjMuGwQ9HsE4zb12TcOZa5F6bs4VDDE8QWW3m IDaf/NgMIuZjLzP0bTzu+KMOQPUFSp1L7+HlSijqQAWADsaiDtGibMISoBT6oq3GPWKvkR LgG7TsGTuYYWTSg3nqLicrI8/Zl2VOYtM7ghIO78ll62j4/dRzEOTayqUcJ2iQ== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:58 +0200 Subject: [PATCH v5 21/25] mtd: spi-nor: winbond: Add support for W25Q25RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-21-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7019 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff0f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d80000d639a50081d614cee96376337a757a75 f7a4d55c39f66dffe970f9a50000000000002c0000000000f6f5ffff0f00 0000060d44bd27ed080dffffffffff8a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 56eaf575ae5e825fad7c531694021ca11976c2adc9a4c78144c87edbe6ad7dfd /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 19 00 00 00 size 32.0 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (32.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-01ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01ffffff | unlocked | 512 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 19.151938] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_read 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 33554432 (32M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x2000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_read 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01ffffff | unlocked | 512 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x2000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_read 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_read 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_read2 7990e6e28bde1e97ce3d83c353fbcf0ea1955591d111e63cebbac02c0b7f10d3 spi_test d9dd42514cb65612993217744485b4cd0201c1c28a66d5a03a7acf5e2c9bf419 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01ffffff | locked | 512 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D33554432 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D512 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 33423360 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01fdffff | unlocked | 510 01fe0000-01ffffff | locked | 2 + flash_lock -u /dev/mtd0 33423360 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01feffff | unlocked | 511 01ff0000-01ffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 25165824 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-017fffff | unlocked | 384 01800000-01ffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-01ffffff | unlocked | 510 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-01ffffff | unlocked | 511 + all_but_one=3D511 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 511 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-01ffffff | locked | 511 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-01ffffff | locked | 510 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 511 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01feffff | locked | 511 01ff0000-01ffffff | unlocked | 1 + flash_lock -u /dev/mtd0 33423360 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-01fdffff | locked | 510 01fe0000-01ffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 2f2c79710241..1f8f8c91b1a1 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -387,7 +387,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR= _HAS_CMP, }, { - /* W25Q256JV-M */ + /* W25Q256JV-M, W25Q25RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x19), .name =3D "w25q256jvm", .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAA8251E435; Fri, 4 Sep 2026 18:14:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545665; cv=none; b=WXHc24WWGDq0vMKf55PRfI3evlRZ4+X0JdBRjsZ66LFbzbSs18MboAJtiMU+/rvfdmYedgH15gNPIGBGS/KDdSEersOSaopxpB2m0jHX4NNU2TlpCuoR3X7gDFOh1xoi3rx54T2i+YFqBelaR+ty353+A9xzm4U3MEYQL2CmSRA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545665; c=relaxed/simple; bh=cZ9hgzMXYAh+PAm/VDUbabSx5sQKN/gcTKwZEFlZ3qA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZWIgTKmtQO9NVAd1EA7AU9+gomCmT1YERPglrgwrD//FoZ/Vk7HOzsoe6ShML2aaearkZKlLICKeihgviPDMFn5126/CjFZYSnaXALqWndfqb8Y3FGf1HlIW4u6JqUSuUyWWvaePKCQTLS9Mfk7wsfzGvx28gY8y6w3YiTaQghw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=L9UNYhU2; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="L9UNYhU2" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 547771A19C4; Fri, 4 Sep 2026 18:14:21 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 285C06057F; Fri, 4 Sep 2026 18:14:21 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 080A211C78705; Fri, 4 Sep 2026 20:14:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545659; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=Y+jnPYN/bnm7TsPM6ziEnSaaPIs9OHsyOYkukNkOwm0=; b=L9UNYhU2BFjN9T1X35BD1o/yc+n4/ZYYSpo7/7A/xIPs6fxR35czcccpdrGooA+6eR6Z3a NB7u6s8VwIa3H7kOBDIM5gv5JTjqIXhRxqqZccLBweL3t4i0QnGdntoRfR3TS69QlqHtCQ kDvdw0Uhoin39vMn13wTLjVDIIHR7gyqoFW2HCt6a82mq/QlCtua6pjHrM0G9biYtGmfji pNoW0Yy/YxB22X64QCRoWNyuQ8wOSY2V2YcbQJpSqD+/y8ahsM5TX7VPTDBJNZHHnTx2UA 2QFhOVQKTpmmspu7gWLnN/lIItUABoFALAswoG0UmC9kzAtM16xamAlOi6WyDg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:12:59 +0200 Subject: [PATCH v5 22/25] mtd: spi-nor: winbond: Add support for W25Q51RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-22-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7020 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff1f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001602a60081e214dde96376337a757a75 f7a4d55c39f66dffe970f9a50000000000002c0c000000006655ffff0f00 0000060d44bd27ed080dffffffffff8a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp d74b1b27fa4e5b8fba7db8fcac198bfe5a28c5e17a565d5e694a6b8d21b62104 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 20 00 00 00 size 64.0 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 SR1 read 0x05 SR2 read 0x35 SR1 write 0x01 SR2 write 0x31 QE SR2 bit 1 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (64.0 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-03ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03ffffff | unlocked | 1024 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_read 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 67108864 (64M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x4000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_read 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03ffffff | unlocked | 1024 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x4000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_read 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_read 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_read2 640094386802e8c1ddca74f4f4848140736a1b275dfc5a2cefbd7f6acd0e6727 spi_test 12582dd4eecd173d184b51b0281065e10062901d66d0f6b1709f4240227b81a9 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03ffffff | locked | 1024 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D67108864 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D1024 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 66977792 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03fdffff | unlocked | 1022 03fe0000-03ffffff | locked | 2 + flash_lock -u /dev/mtd0 66977792 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03feffff | unlocked | 1023 03ff0000-03ffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 58720256 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-037fffff | unlocked | 896 03800000-03ffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-03ffffff | unlocked | 1022 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-03ffffff | unlocked | 1023 + all_but_one=3D1023 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 1023 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-03ffffff | locked | 1023 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-03ffffff | locked | 1022 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 1023 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03feffff | locked | 1023 03ff0000-03ffffff | unlocked | 1 + flash_lock -u /dev/mtd0 66977792 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-03fdffff | locked | 1022 03fe0000-03ffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 1f8f8c91b1a1..91d0e67c93b6 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -393,7 +393,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .flags =3D SPI_NOR_QUAD_PP | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, }, { - /* W25Q512JV-M */ + /* W25Q512JV-M, W25Q51RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x20), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27174523782 for ; Fri, 4 Sep 2026 18:14:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545667; cv=none; b=PdVRdzM0RPcetcFS7/V+sCbaE6ntmjQlKV0MaIdPbgmOGEGDg0aNBcy2pzJBB3dOPR1Syp1ZaoCPaOzpiNk3rDrGY32OvmUPlKYX2CBLu2Qb5AF7EJ28Y07qoTFDcOJYXd0oQpe38HBN8EEUzTbD3Kv5rS52lNWkoXVKDG8wKEE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545667; c=relaxed/simple; bh=+Qh+TH/M9fGp81WR9xcCQMBQOCaK4wUjX+DTVwagYM8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gGgMxRDgS8h0JzuLtGDbjrpxzx57TZ3htiabysPOC5a5xht2oVhGF8bTAigdjt1xO1hedwPPTyYR/0/6Ctu0ucgYZ9TIK4lpBdBY0A88Nqu5cznxpMYhTe6JvupwAmMfsmgXc4j/J2JYs5dTblY674Rq4NFAynC9qYzO0YDlFDM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=hVjsOY7r; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="hVjsOY7r" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id B06E51A19C3; Fri, 4 Sep 2026 18:14:23 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 831326057F; Fri, 4 Sep 2026 18:14:23 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 6826211C78767; Fri, 4 Sep 2026 20:14:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545662; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=KOWWHYo2Xh2xm15YJp0bVFc03y51GyDRT3DUUewrBRM=; b=hVjsOY7rlwAAXii5MVyje02ltV5OSH9qVLvWjjTAw4tBjaVefbkvVfU4QkqP6KrCtv+lYO yoA8HYMOasynSKg83fI6k7Jp6Ov403oxTTbtFuEdPhL27+A0Ojy3qXnmjhpo2Hxrln9JrO lcPVMEbiZetkrtfWjqixzgGmFP+eXHYHRuegscXQGgbvt6CXMi2fhxpuiNdSiWIq74d2uT MUuJo5h7pKk0DyP1b0o1/sAjfpNPGP6gom+ul6Nii2sWnbknSFoSa/h3s0WXERpk4cmmY5 /QURQbj1wZei3al/UD/zBwJNwR9SwJmYdHXSuWX3NVPV13EwrWg+D1iTe/azlQ== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:13:00 +0200 Subject: [PATCH v5 23/25] mtd: spi-nor: winbond: Add support for W25Q01RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-23-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7021 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff3f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001602a60081e214dde9e378477a757a75 f7a4d55c39f66dffe970f9a50000000000002c0c000000006655ffff0f00 0000060d44bd27ed080dffffffffff8a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp f0ba26954c84f126916616ac4311057151ea46cae2eda1752709c3a5adfe4b55 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 21 00 00 00 size 128 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (128 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-07ffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | unlocked | 2048 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 19.799786] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_read 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 134217728 (128M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x8000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_read 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | unlocked | 2048 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x8000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_read 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_read 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_read2 89d206670689b1bdd4688313bcc0ea3ac67a9ac055e75fd76220387c9e4fde3e spi_test 792b00a5bf62350ee8f4868980820577046401c3e6f79075ea636034cff7cef2 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07ffffff | locked | 2048 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D134217728 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D2048 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 134086656 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07fdffff | unlocked | 2046 07fe0000-07ffffff | locked | 2 + flash_lock -u /dev/mtd0 134086656 1 + grep -A4 'locked sectors' /sys/kernel/debbg//spi-nr/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07feffff | unlocked | 2047 07ff0000-07ffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 125829120 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-077fffff | unlocked | 1920 07800000-07ffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-07ffffff | unlocked | 2046 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-07ffffff | unlocked | 2047 + all_but_one=3D2047 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 2047 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-07ffffff | locked | 2047 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-07ffffff | locked | 2046 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2047 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07feffff | locked | 2047 07ff0000-07ffffff | unlocked | 1 + flash_lock -u /dev/mtd0 134086656 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-07fdffff | locked | 2046 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 91d0e67c93b6..96791ee019e0 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -398,7 +398,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, }, { - /* W25Q01JV-M */ + /* W25Q01JV-M, W25Q01RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x21), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 01B3D52379F for ; Fri, 4 Sep 2026 18:14:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545670; cv=none; b=j/mopPpXE3VclXQ1Z3kexvOHJdcdu5qCiqw02ehQAiK9qJ05TNuNnwaTTEFemdmNlEaCuTmw46RqaE9vAaYs8LuHXVFiXbEhOINPbP/EH4s4DYBsEPQPtoSy51/q34j+dvjIljjNoGQnJqkfY7GdX7LJyocbNSP+0aOe4icm+X4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545670; c=relaxed/simple; bh=Qt5dNKmtAEIIeC8OX2FuoYzjmnAZnXzUJC9Pd+BdOWk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jh2S1YV9ZvVsieUV3o0fkwQkA58HT2j6NZTaikPClC27VyCHYST6BU+QWgqoMsXOzoBq+UbV7t9drSALAor/3C5y8fhIHODeXArup8DkVDOuOOHBGHzNzYJgaHPaIFGj+habXy2S0XRurXT3xahLJNKZwbLRc8MhDv3QzHldP7w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=mzj5m54z; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="mzj5m54z" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 486484E4152F; Fri, 4 Sep 2026 18:14:26 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 1BC616057F; Fri, 4 Sep 2026 18:14:26 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id BF8F411C787BD; Fri, 4 Sep 2026 20:14:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545664; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=/mH2W1mH4MO7d5TQMgaP1u4gzqysmw2plzAR/LInlHQ=; b=mzj5m54zn771KxHJRY7FWD9HLxbi1h7tSXzYVMZZWdf3NgbBUCG/n1sbpOTUXiMMy+Vf05 QVRuD/Vmy34GDeYbwEXow0xeT9tSQtstTQOSudPF11MrN1dt13oQ+vJ0zZEIrbr9Ep139/ WLtuR4Nj/Uj9cgDfoUtBQH77sJNEXUYAMgf1AidKGXAIeRsx2Uehjlx66BDjRBzzuVK6tc 1JWneCgjtBGYlTz+EQ3vqbYMef32rTfZ95HLjr0ayQJkJzVqCFmpPlaa5AbLtmJNjnHmZ/ 4foJmDEBayFo0+4TPf7Z9Ap09lfbrv/io8Se0kUNd5Io9CVeO2efTw+M7rux4Q== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:13:01 +0200 Subject: [PATCH v5 24/25] mtd: spi-nor: winbond: Add support for W25Q02RV-M Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-24-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 There is an ID collision with the chip of same density from the JV family. Both chips are very similar in practice, it is mostly a matter of electrical differences (mostly power consumption being lower). As a significant difference, RV chips identify themselves as supporting the new SFDP (rev F) field which forces an alternate write SR2 opcode (0x31). Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Signed-off-by: Miquel Raynal --- + cat /sys/bus/spi/devices/spi0.0/spi-nor/jedec_id ef7022 + cat /sys/bus/spi/devices/spi0.0/spi-nor/manufacturer winbond + xxd -p /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 534644500a0101ff00080117800000ff84010102e00000ffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff7f44eb086b083b42bbfeffffffffff 0000ffff44eb0c200f5210d800001602a60081e214dde9e378477a757a75 f7a4d55c39f66dffe970f9a50000000000002c0c000000006655ffff0f00 0000060d44bd27ed080dffffffffff8a00fe21ffdcff + sha256sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp fe929abb1ba38dd6a8668200051298a8140bfeb56bd6d58f56b86b074a150f12 /sys/bus/= spi/devices/spi0.0/spi-nor/sfdp + cat /sys/kernel/debug/spi-nor/spi0.0/capabilities Supported read modes by the flash 1S-1S-1S opcode 0x13 mode cycles 0 dummy cycles 0 1S-1S-2S opcode 0x3c mode cycles 0 dummy cycles 8 1S-2S-2S opcode 0xbc mode cycles 2 dummy cycles 2 1S-1S-4S opcode 0x6c mode cycles 0 dummy cycles 8 1S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 4S-4S-4S opcode 0xec mode cycles 2 dummy cycles 4 Supported page program modes by the flash 1S-1S-1S opcode 0x12 1S-1S-4S opcode 0x34 + cat /sys/kernel/debug/spi-nor/spi0.0/params name (null) id ef 70 22 00 00 00 size 256 MiB write size 1 page size 256 address nbytes 4 flags HAS_SR_TB | 4B_OPCODES | HAS_4BAIT | HAS_LOCK | HAS_SR_TB_BIT6 | HAS= _4BIT_BP | SOFT_RESET | NO_WP | HAS_SR2_CMP_BIT6 opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 8D extension repeat protocols read 1S-4S-4S write 1S-1S-4S register 1S-1S-1S erase commands 21 (4.00 KiB) [1] dc (64.0 KiB) [3] c7 (256 MiB) sector map region (in hex) | erase mask | overlaid ------------------+------------+--------- 00000000-0fffffff | [ 3] | no locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0fffffff | unlocked | 4096 + dd 'if=3D/dev/urandom' 'of=3D./spi_test' 'bs=3D1M' 'count=3D2' [ 11.527038] random: crng init done 2+0 records in 2+0 records out + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + hexdump spi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0200000 + sha256sum spi_read 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_read 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_test + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 4bda3a28f4ffe603c0ec1258c0034d65a1a0d35ab7bd523a834608adabf03cc5 spi_read 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_test + mtd_debug info /dev/mtd0 mtd.type =3D MTD_NORFLASH mtd.flags =3D MTD_CAP_NORFLASH mtd.size =3D 268435456 (256M) mtd.erasesize =3D 65536 (64K) mtd.writesize =3D 1 mtd.oobsize =3D 0 regions =3D 0 + alias 'show_sectors=3Dgrep -A4 "locked sectors" /sys/kernel/debug/spi-nor= /spi0.0/params' + flash_lock -u /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x10000000 Lock status: unlocked Return code: 0 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug write /dev/mtd0 0 2097152 spi_test Copied 2097152 bytes from spi_test to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_read 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_test + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0fffffff | unlocked | 4096 + flash_lock -l /dev/mtd0 + flash_lock -i /dev/mtd0 Device: /dev/mtd0 Start: 0 Len: 0x10000000 Lock status: locked Return code: 1 + mtd_debug erase /dev/mtd0 0 2097152 Erased 2097152 bytes from address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read Copied 2097152 bytes from address 0x00000000 in flash to spi_read + sha256sum spi_read spi_test 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_read 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_test + dd 'if=3D/dev/urandom' 'of=3D./spi_test2' 'bs=3D1M' 'count=3D2' 2+0 records in 2+0 records out + mtd_debug write /dev/mtd0 0 2097152 spi_test2 Copied 2097152 bytes from spi_test2 to address 0x00000000 in flash + mtd_debug read /dev/mtd0 0 2097152 spi_read2 Copied 2097152 bytes from address 0x00000000 in flash to spi_read2 + sha256sum spi_read spi_read2 spi_test spi_test2 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_read 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_read2 32e1a8def4cf674413ff0b7a2738e704f03f7bddcaf7ee2d320ab83aa7bf813e spi_test 4b1329df073cd497567d8cb6878aa20af6af71df98cc7c445d31a69eaf0d69f1 spi_test2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0fffffff | locked | 4096 + flash_lock -u /dev/mtd0 + cat /sys/class/mtd/mtd0/size + size=3D268435456 + cat /sys/class/mtd/mtd0/erasesize + bs=3D65536 + grep unlocked /sys/kernel/debug/spi-nor/spi0.0/params + sed -e 's/.*unlocked | //' + nsectors=3D4096 + ss=3D65536 + bps=3D1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 268304384 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffdffff | unlocked | 4094 0ffe0000-0fffffff | locked | 2 + flash_lock -u /dev/mtd0 268304384 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffeffff | unlocked | 4095 0fff0000-0fffffff | locked | 1 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 260046848 128 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0f7fffff | unlocked | 3968 0f800000-0fffffff | locked | 128 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 2 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | locked | 2 00020000-0fffffff | unlocked | 4094 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | locked | 1 00010000-0fffffff | unlocked | 4095 + all_but_one=3D4095 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 65536 4095 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0000ffff | unlocked | 1 00010000-0fffffff | locked | 4095 + flash_lock -u /dev/mtd0 65536 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0001ffff | unlocked | 2 00020000-0fffffff | locked | 4094 + flash_lock -u /dev/mtd0 + flash_lock -l /dev/mtd0 0 4095 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffeffff | locked | 4095 0fff0000-0fffffff | unlocked | 1 + flash_lock -u /dev/mtd0 268304384 1 + grep -A4 'locked sectors' /sys/kernel/debug/spi-nor/spi0.0/params locked sectors region (in hex) | status | #sectors ------------------+----------+--------- 00000000-0ffdffff | locked | 4094 0ffe0000-0fffffff | unlocked | 2 --- drivers/mtd/spi-nor/winbond.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 96791ee019e0..f6321c1dc7dc 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -403,7 +403,7 @@ static const struct flash_info winbond_nor_parts[] =3D { .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, }, { - /* W25Q02JV-M */ + /* W25Q02JV-M, W25Q02RV-M */ .id =3D SNOR_ID(0xef, 0x70, 0x22), .flags =3D SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_HAS_CMP, --=20 2.54.0 From nobody Sat Sep 26 03:12:50 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B0E55237A6; Fri, 4 Sep 2026 18:14:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545671; cv=none; b=V+QptS8YzP22PlT0TmIKYJU81/Z2Ix4u79qSlYaEISL0ju04NtWgMPajW9qwu15lmBej307Nc7Yayrf19eU88K0AUJ1yw4xB0qFbZaZKPLIdLNcxCM4N0XiyXOfS033FELg4mIBViXyruHvFCy+NPybqoTtgDK5FxlIeN2slwzQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788545671; c=relaxed/simple; bh=cCJhHuXkOjQp1Eqv6VprY7vuc10xchl2ZZlRu8bksOU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=q8PhRu6CenugT83IdMgNvwGaL/KKBwuIvxlxP7sJyzh3BkL5rrmGm9Vnw1Sw34o7sR3SkKWGwOj7T7V673gGgYMmCPPFPuNtUELldy8YJ+nE1dWewrvETF++Vg2njcPpBgsu3T/Yv9EoQamZ0v3+TPaS0fna62t0jEvzkPjnzTI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=CPUXp8RC; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="CPUXp8RC" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id DF2CB1A19C3; Fri, 4 Sep 2026 18:14:28 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id B313A6057F; Fri, 4 Sep 2026 18:14:28 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 45B7911C78158; Fri, 4 Sep 2026 20:14:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1788545667; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=xJa2SIgs5+/YUcOMPI/QW/gbwXsr/EhtwgH6qw1Zg80=; b=CPUXp8RC5qfQo249zMudJN7keL5nvy8sE2OR/YfEjvXVC/RheoImipXihndzmzPSlxUzot BvjfPZJ8suY4I/fSromVo6MKYDmeCS3RMN7z4dgEVrMIJT2JTPfWMFe5E7nMUmiZOlz7lU neO1OiEEWrskuPSOCZoI01gY82O3yYWP/yDdoO5DXO8aetx3WshWiml3X0aabR8GlezrCw Qa87RnYFdPM2J54/oSn1CfscPErQpXYzUVOjTxz3viko8iynYkNtaBgKg3rKIWG7qGElFJ bHxopfqRmIBqQgzQXORj7gAj3K8u2SnaDdmj4oRt/4txrmgK8s4j9BajVW1xLg== From: Miquel Raynal Date: Fri, 04 Sep 2026 20:13:02 +0200 Subject: [PATCH v5 25/25] mtd: spi-nor: debugfs: Expose SR opcodes and QE mask Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-25-2909a45fe4fa@bootlin.com> References: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> In-Reply-To: <20260904-winbond-v7-1-spi-nor-rv-addition-v5-0-2909a45fe4fa@bootlin.com> To: Pratyush Yadav , Michael Walle , Takahiro Kuwano , Richard Weinberger , Vignesh Raghavendra , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Jonathan Corbet , Shuah Khan , Randy Dunlap Cc: Steam Lin , Hsin-Yi Wang , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Miquel Raynal X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Expose Status Register opcodes based on the flash capabilities discovered while parsing the SFDP QER field. Value '0' indicates an absence of opcode (non supported), we do not print anything in that case. The QE bit is also displayed. Example on a W25Q02JV-M: $ grep opcodes -A10 /sys/kernel/debug/spi-nor/spi0.0/params opcodes read 0xec dummy cycles 6 erase 0xdc program 0x34 SR1 read 0x05 SR2 read 0x35 SR1+SR2 write 0x01 QE SR2 bit 1 8D extension none Tested-by: Takahiro Kuwano Signed-off-by: Miquel Raynal --- drivers/mtd/spi-nor/debugfs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index 5c738786145f..3f8d586a7622 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -104,6 +104,21 @@ static int spi_nor_params_show(struct seq_file *s, voi= d *data) seq_printf(s, " dummy cycles\t%u\n", nor->read_dummy); seq_printf(s, " erase\t\t0x%02x\n", nor->erase_opcode); seq_printf(s, " program\t0x%02x\n", nor->program_opcode); + seq_printf(s, " SR1 read\t0x%02x\n", params->opcodes.read_sr1); + if (params->opcodes.read_sr2) + seq_printf(s, " SR2 read\t0x%02x\n", params->opcodes.read_sr2); + if (params->opcodes.write_sr1) + seq_printf(s, " SR1 write\t0x%02x\n", params->opcodes.write_sr1); + if (params->opcodes.write_sr2) + seq_printf(s, " SR2 write\t0x%02x\n", params->opcodes.write_sr2); + if (params->opcodes.write_sr1_and_sr2) + seq_printf(s, " SR1+SR2 write\t0x%02x\n", + params->opcodes.write_sr1_and_sr2); + + if (params->qe_mask[0] || params->qe_mask[1]) + seq_printf(s, " QE\t\tSR%d bit %d\n", + params->qe_mask[0] ? 1 : 2, + ffs(params->qe_mask[0] | params->qe_mask[1]) - 1); =20 switch (params->cmd_ext_type) { case SPI_NOR_EXT_NONE: --=20 2.54.0