From nobody Mon Feb 9 18:48:50 2026 Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) (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 42FF04C80 for ; Tue, 24 Dec 2024 16:47:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735058879; cv=none; b=p8NzjLrLQXFHORhm+Z+fN32kQxVNfpyxAN5Ak8lpLmT9b3iLhY7wcrsboJNu+/Ax5NmBAOd0v4JmmA1kkAxvAgliyMn28iNfSm867xHD5FYq7Q9GeuClT5JvwCrjwjnPTQs9ulpNc61QLFgHNhvO9bv4WgI5ubG+M1HuzmzXXn8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735058879; c=relaxed/simple; bh=j8SIV76+nrpDWpvuaihYoQCzKmVQ4rFsH5witIVLQpM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aXBpTG30JjmLoq2pr5xBasONdUxZHhnVEdxT1M7dPk9pospbZGmDrlPhoQDOAZ9qn0CVZl9MuxfTbr0dI2ll0n4r5FFg6CqKKlRNc96M9v2bvY85Hjc4g0QMH4+w378XdVp/npYPndpKvtGjeheEb2gLcrOgkrU7mZyXdUslkXo= 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=izuvoJ1V; arc=none smtp.client-ip=217.70.183.197 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="izuvoJ1V" Received: by mail.gandi.net (Postfix) with ESMTPSA id 4A9D91C0006; Tue, 24 Dec 2024 16:47:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1735058875; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RPUNU8k3CaKZFk028633f4TgCsXKqufS1tewP4nLaeU=; b=izuvoJ1VUVREJxOtgpIoGhW7Z2BbQA2pqLt5NAlpFYQCnfwM4OIYePQEFq6An/rhuYjpCc VkxJqmg4zVvIk/5kj2jsHRg4GJG2p5jISe6rKxfaj/Dln7Pvh39W/TzTv1ri9piYz1It7R Xqcjzkwu6rqHvR7SJhoELcB3qWSHcQfacp2Y+oWLKvfhMkSJZ50MIsxxt4B3C+fWBAjwaD bVc9Ghob2k1arp7Cqedku+lrTnnbWLIjjDhHqRXLIrNiGdFFYlphOfaTvYvt0Cy5ChlEDt MTGgWe2KOp7bMzu0EY2do24QnwVGBvG+PnW1AdW1HuRq/MiWSHpm2XWHTOUZKA== From: Miquel Raynal Date: Tue, 24 Dec 2024 17:47:41 +0100 Subject: [PATCH 1/2] mtd: spi-nor: winbond: Add support for w25q01jv 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: <20241224-winbond-6-12-rc1-nor-volatile-bit-v1-1-f7c4dff66182@bootlin.com> References: <20241224-winbond-6-12-rc1-nor-volatile-bit-v1-0-f7c4dff66182@bootlin.com> In-Reply-To: <20241224-winbond-6-12-rc1-nor-volatile-bit-v1-0-f7c4dff66182@bootlin.com> To: Tudor Ambarus , Pratyush Yadav , Michael Walle , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra Cc: Thomas Petazzoni , Steam Lin , linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15-dev X-GND-Sasl: miquel.raynal@bootlin.com Add support for Winbond w25q01jv spi-nor chip. This chip is internally made of two dies with linear addressing capabilities to make it transparent to the user that two dies were used. There is one drawback however, the read status operation is racy as the status bit only gives the active die status and not the status of the other die. For commands affecting the two dies, it means if another command is sent too fast after the first die has returned a valid status (deviation can be up to 200us), the chip will get corrupted/in an unstable state. This chip hence requires a better status register read. There are three solutions here: - Either we wait about 200us after getting a first status ready feedback, to cover possible internal deviations. - Or we always check all internal dies (which takes about 30us per die). This second option being always faster and also being totally safe, we implement a specific hook for the status register read. flash_speed benchmarks show no difference with this implementation, compared to the regular status read core function, the difference being part of the natural deviation with this benchmark: > Without the fixup $ flash_speed /dev/mtd0 -c100 -d eraseblock write speed is 442 KiB/s eraseblock read speed is 1606 KiB/s page write speed is 439 KiB/s page read speed is 1520 KiB/s 2 page write speed is 441 KiB/s 2 page read speed is 1562 KiB/s erase speed is 68 KiB/s > With the fixup $ flash_speed /dev/mtd0 -c100 -d eraseblock write speed is 428 KiB/s eraseblock read speed is 1626 KiB/s page write speed is 426 KiB/s page read speed is 1538 KiB/s 2 page write speed is 426 KiB/s 2 page read speed is 1574 KiB/s erase speed is 66 KiB/s As there are very few situations where this can actually happen, a status register write being the most likely one, another possibility might have been to use volatile writes instead of non-volatile writes, as most of the deviation comes from the action of writing the bit. But this would overlook other possible actions where both dies can be used at the same time like a chip erase (or any erase over the die boundary in general). This last approach would have the least impact but because it does not feel like it is totally safe to use and because the impact of the second solution presented above is also negligible, we keep this second approach for now (which can be further tuned later if it appears to be too impacting in the end). However, the fixup, whatever which one we pick, must be applied on multi-die chips, which hence must be properly flagged. The SFDP tables implemented give a lot of information but the die details are part of an optional table that is not implemented, hence we use a post parsing fixup hook to set the params->n_dice value manually. Link: https://www.winbond.com/resource-files/W25Q01JV%20SPI%20RevE%20030420= 24%20Plus.pdf Signed-off-by: Miquel Raynal --- Here is the basic test procedure output: $ cat /sys/bus/spi/devices/spi0.0/spi-nor/partname w25q01jv $ 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 53464450060101ff00060110800000ff84000102d00000ff03000102f000 00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff3f44eb086b083b42bbfeffffffffff 0000ffff40eb0c200f5210d800003602a60082ea14e2e96376337a757a75 f7a2d55c19f74dffe970f9a5ffffffffffffffffffffffffffffffffff0a f0ff21ffdcff $ md5sum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp a7b9dbf76e99a33db99e557b6676588a /sys/bus/spi/devices/spi0.0/spi-nor/sfdp $ dd if=3D/dev/urandom of=3D./qspi_test bs=3D1M count=3D1 1+0 records in 1+0 records out $ mtd_debug write /dev/mtd0 0 1048576 qspi_test Copied 1048576 bytes from qspi_test to address 0x00000000 in flash $ mtd_debug erase /dev/mtd0 0 1048576 Erased 1048576 bytes from address 0x00000000 in flash $ mtd_debug read /dev/mtd0 0 1048576 qspi_read Copied 1048576 bytes from address 0x00000000 in flash to qspi_read $ hexdump qspi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0100000 $ mtd_debug write /dev/mtd0 0 1048576 qspi_test Copied 1048576 bytes from qspi_test to address 0x00000000 in flash $ mtd_debug read /dev/mtd0 0 1048576 qspi_read Copied 1048576 bytes from address 0x00000000 in flash to qspi_read $ sha1sum qspi_test qspi_read becf3097c0bbff0dd6f204ffe5bf575e6c43f792 qspi_test becf3097c0bbff0dd6f204ffe5bf575e6c43f792 qspi_read --- drivers/mtd/spi-nor/winbond.c | 82 +++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 82 insertions(+) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 8d0a00d69e1233988876a15479d73c5fe899c542..4691e7a27ba1d70c75932c4e6b6= 0fe36102138be 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -10,6 +10,7 @@ =20 #define WINBOND_NOR_OP_RDEAR 0xc8 /* Read Extended Address Register */ #define WINBOND_NOR_OP_WREAR 0xc5 /* Write Extended Address Register */ +#define WINBOND_NOR_OP_SELDIE 0xc2 /* Select active die */ =20 #define WINBOND_NOR_WREAR_OP(buf) \ SPI_MEM_OP(SPI_MEM_OP_CMD(WINBOND_NOR_OP_WREAR, 0), \ @@ -17,6 +18,12 @@ SPI_MEM_OP_NO_DUMMY, \ SPI_MEM_OP_DATA_OUT(1, buf, 0)) =20 +#define WINBOND_NOR_SELDIE_OP(buf) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(WINBOND_NOR_OP_SELDIE, 0), \ + SPI_MEM_OP_NO_ADDR, \ + SPI_MEM_OP_NO_DUMMY, \ + SPI_MEM_OP_DATA_OUT(1, buf, 0)) + static int w25q128_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, @@ -66,6 +73,26 @@ static const struct spi_nor_fixups w25q256_fixups =3D { .post_bfpt =3D w25q256_post_bfpt_fixups, }; =20 +static int +w25q0xjv_post_bfpt_fixups(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + const struct sfdp_bfpt *bfpt) +{ + /* + * SFDP supports dice numbers, but this information is only available in + * optional additional tables which are not provided by these chips. + * Dice number has an impact though, because these devices need extra + * care when reading the busy bit. + */ + nor->params->n_dice =3D nor->params->size / SZ_64M; + + return 0; +} + +static const struct spi_nor_fixups w25q0xjv_fixups =3D { + .post_bfpt =3D w25q0xjv_post_bfpt_fixups, +}; + static const struct flash_info winbond_nor_parts[] =3D { { .id =3D SNOR_ID(0xef, 0x30, 0x10), @@ -146,6 +173,11 @@ static const struct flash_info winbond_nor_parts[] =3D= { .name =3D "w25q512jvq", .size =3D SZ_64M, .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, + }, { + .id =3D SNOR_ID(0xef, 0x40, 0x21), + .name =3D "w25q01jv", + .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, + .fixups =3D &w25q0xjv_fixups, }, { .id =3D SNOR_ID(0xef, 0x50, 0x12), .name =3D "w25q20bw", @@ -289,6 +321,37 @@ static int winbond_nor_write_ear(struct spi_nor *nor, = u8 ear) return ret; } =20 +/** + * winbond_nor_select_die() - Set active die. + * @nor: pointer to 'struct spi_nor'. + * @die: die to set active. + * + * Return: 0 on success, -errno otherwise. + */ +static int winbond_nor_select_die(struct spi_nor *nor, u8 die) +{ + int ret; + + nor->bouncebuf[0] =3D die; + + if (nor->spimem) { + struct spi_mem_op op =3D WINBOND_NOR_SELDIE_OP(nor->bouncebuf); + + 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, + WINBOND_NOR_OP_SELDIE, + nor->bouncebuf, 1); + } + + if (ret) + dev_dbg(nor->dev, "error %d selecting die %d\n", ret, die); + + return ret; +} + /** * winbond_nor_set_4byte_addr_mode() - Set 4-byte address mode for Winbond * flashes. @@ -322,6 +385,22 @@ static int winbond_nor_set_4byte_addr_mode(struct spi_= nor *nor, bool enable) return spi_nor_write_disable(nor); } =20 +static int winbond_multi_die_ready(struct spi_nor *nor) +{ + int ret, i; + + for (i =3D 0; i < nor->params->n_dice; i++) { + ret =3D winbond_nor_select_die(nor, i); + if (ret) + return ret; + + if (!spi_nor_sr_ready(nor)) + return 0; + } + + return 1; +} + static const struct spi_nor_otp_ops winbond_nor_otp_ops =3D { .read =3D spi_nor_otp_read_secr, .write =3D spi_nor_otp_write_secr, @@ -334,6 +413,9 @@ static int winbond_nor_late_init(struct spi_nor *nor) { struct spi_nor_flash_parameter *params =3D nor->params; =20 + if (params->n_dice > 1) + params->ready =3D winbond_multi_die_ready; + if (params->otp.org) params->otp.ops =3D &winbond_nor_otp_ops; =20 --=20 2.47.0 From nobody Mon Feb 9 18:48:50 2026 Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) (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 48FF41FF611 for ; Tue, 24 Dec 2024 16:47:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.197 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735058880; cv=none; b=PJXwzIn9R9H2aDuKYlWneMLu2nhdi6lkwUBfWiJ43WD8m8iXnh0hM5IoaGXiyJhMK+o2g4K4djoPYilrC1FEqYrqq1+v8OJPcdxw3bJUdIhEXJZpwL4V32FCML0y4SHrdg6W/nxgvvp/9Azp8/EW6SYfnoAVK+U9ZA2I7HF9QO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735058880; c=relaxed/simple; bh=Hj2BAxJyvEQc2vEsqxV0COh1eHVZ+ssG0Mu39crHAX0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uaT02hClmbu1QvxAM8R5anfykNYcThAzTrWLnaVa7gbOz7sDdY62O8gPYRnBX/g3w4xBHp/ASJ9wl3HAY/Umjgx8DE6aEvzSfoRv/2lWGFimH5r7YyehwPbWsS+XT/MBz4qcMfkW4vFv68W98Bj3P/wVpo2rGobCNTHVJIp4AVc= 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=aLeZuKGU; arc=none smtp.client-ip=217.70.183.197 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="aLeZuKGU" Received: by mail.gandi.net (Postfix) with ESMTPSA id 91F0E1C0005; Tue, 24 Dec 2024 16:47:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1735058876; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pNhPd8gY0LdJIIaXA25OzrOgCAUaztPc20vfkmYeTLo=; b=aLeZuKGUgccITaWqHrups2bWyFO6ycxeP8y9eBcehx0fz6U5DtDOaDXL9pk9HScKRBR48X Uvpexu265wQ0u7O2kR9p8zr6W2vWSHDigOt4QV1FsK2qodiE5HhPE7aPTiG7CVjrlq8LY7 lciNxci0c53QtUUKHRBbrtg27TB4DQ1mfH51auUWMrRO5B59hED/2mrhvesSSjRZhrY+es iZ6zEe+K8awp6kHaiupuob6PWqmX3GM0FUpytZV6g925j2qP0i1BP438ZeJZUQqJopKuVs yCRbTjoRThsJaF+SCQwPf5zVbLw+hASxBdhSZk1BJvzBIRjW97Tg9DlSRPt3zw== From: Miquel Raynal Date: Tue, 24 Dec 2024 17:47:42 +0100 Subject: [PATCH 2/2] mtd: spi-nor: winbond: Add support for w25q02jv 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: <20241224-winbond-6-12-rc1-nor-volatile-bit-v1-2-f7c4dff66182@bootlin.com> References: <20241224-winbond-6-12-rc1-nor-volatile-bit-v1-0-f7c4dff66182@bootlin.com> In-Reply-To: <20241224-winbond-6-12-rc1-nor-volatile-bit-v1-0-f7c4dff66182@bootlin.com> To: Tudor Ambarus , Pratyush Yadav , Michael Walle , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra Cc: Thomas Petazzoni , Steam Lin , linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15-dev X-GND-Sasl: miquel.raynal@bootlin.com Add support for Winbond w25q02jv spi-nor chip which shares most of w25q01jv's specificities as, this time, the chip is made of 4 different dies. Link: https://www.winbond.com/resource-files/W25Q02JV_DTR%20RevD%2007092024= %20Plus.pdf Signed-off-by: Miquel Raynal --- Here is the basic test procedure output: $ cat /sys/bus/spi/devices/spi0.0/spi-nor/partname w25q02jv $ 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 53464450060101ff00060110800000ff84000102d00000ff03000102f000 00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffe520fbffffffff7f44eb086b083b42bbfeffffffffff 0000ffff40eb0c200f5210d800003602a60082ea14e2e96376337a757a75 f7a2d55c19f74dffe970f9a5ffffffffffffffffffffffffffffffffff0a f0ff21ffdcff $ md5suum /sys/bus/spi/devices/spi0.0/spi-nor/sfdp 3e7da68579120c32a12517d2b6634c3c /sys/bus/spi/devices/spi0.0/spi-nor/sfdp $ dd if=3D/dev/urandom of=3D./qspi_test bs=3D1M count=3D1 1+0 records in 1+0 records out $ mtd_debug write /dev/mtd0 0 1048576 qspi_test Copied 1048576 bytes from qspi_test to address 0x00000000 in flash $ mtd_debug erase /dev/mtd0 0 1048576 Erased 1048576 bytes from address 0x00000000 in flash $ mtd_debug read /dev/mtd0 0 1048576 qspi_read Copied 1048576 bytes from address 0x00000000 in flash to qspi_read $ hexdump qspi_read 0000000 ffff ffff ffff ffff ffff ffff ffff ffff * 0100000 $ mtd_debug write /dev/mtd0 0 1048576 qspi_test Copied 1048576 bytes from qspi_test to address 0x00000000 in flash $ mtd_debug read /dev/mtd0 0 1048576 qspi_read Copied 1048576 bytes from address 0x00000000 in flash to qspi_read $ sha1sum qspi_test qspi_read c662ae4e6b1268e23d5a5e930995213d2e4044cc qspi_test c662ae4e6b1268e23d5a5e930995213d2e4044cc qspi_read --- drivers/mtd/spi-nor/winbond.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c index 4691e7a27ba1d70c75932c4e6b60fe36102138be..888367a8ee9967b5d7c7886dd2c= 6a1024f659609 100644 --- a/drivers/mtd/spi-nor/winbond.c +++ b/drivers/mtd/spi-nor/winbond.c @@ -253,6 +253,11 @@ static const struct flash_info winbond_nor_parts[] =3D= { }, { .id =3D SNOR_ID(0xef, 0x70, 0x19), .name =3D "w25q256jvm", + }, { + .id =3D SNOR_ID(0xef, 0x70, 0x22), + .name =3D "w25q02jv", + .no_sfdp_flags =3D SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, + .fixups =3D &w25q0xjv_fixups, }, { .id =3D SNOR_ID(0xef, 0x71, 0x19), .name =3D "w25m512jv", --=20 2.47.0