From nobody Thu Apr 2 20:22:17 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 7738E3A1E7B; Thu, 26 Mar 2026 16:26: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=1774542372; cv=none; b=V58p1EYxredgHztUfpb+R45VX51ejd/G8d+tV6uqh7r7OmcTEBps59jacx0CZEQj1QlSHotxdQPBWdSa04YvPDdm92V4kuY+ZJLlzxhW2OmrpzzuHSwEuNZzers/BbBjYpz3GdkguAa+FQl9JYSMmE5bJK2BkfURR3+Am0ufpKw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542372; c=relaxed/simple; bh=bCLryakrulMqkUe87l2Z2KjmcWbzIqTOOUOh3rjsiTk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FkaFnvMZxz7F/zlxPGD/ADgi26l47xYfhA+pTwOQdTtb6nj7FfBNez/UPc3DlxZleRhCu3o0rwuwCxyl1ISJAb2PD4hipFqXI/z+xNJch+KBaA1qTlOcBt8xMmc7d7NL6SCHlapunbjCwog3pKtskvwcH7H47LCHc+JCpQQG8g8= 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=IXFbR8p6; 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="IXFbR8p6" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id C2EBC4E4280D; Thu, 26 Mar 2026 16:26:08 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 98B90601FA; Thu, 26 Mar 2026 16:26:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id EF69910450C89; Thu, 26 Mar 2026 17:26:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542367; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=QHp/XpnDc6VCjq7Z0fA22iB0i5XtlmN2AieaCNd4Ovs=; b=IXFbR8p6lsJT/2f6E3hDXOp7rvLkQdRT63ruqh/UP9hGiIBruK7rTY1bsyi2UK9A2zAFQX iEFYEOrDZ2e4P9wAal/136ejBloxyx5cQXlp62khWj6gyOhNl6ef0tbxVYA/b97P4RtHFc omhzZZVanMUzBeeruhIhKZzHe5dQHZjrC0WMgolWSXV7Buu9oWraSlmHm6TYXijPraaPTz MC/ao3fMtnzduuP9HU7aAJW+ot4v4mgTyk52f056ttWYMYng6ITUx60PFyDnU3z7TJGmv2 Wa7bj+Iu9QOiBEpXDilMLrb8FkQNOMe//So9L8wMcVqkABE7UQKiYrMagH17Kw== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:48 +0100 Subject: [PATCH v2 01/11] mtd: spinand: Drop a too strong limitation 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: <20260326-winbond-v6-18-rc1-cont-read-v2-1-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Since continuous reads may sometimes not be able to go past an erase block boundary, it has been decided not to attempt longer reads and if the user request is bigger, it will be split across eraseblocks. As these request will anyway be handled correctly, there is no reason to filter out cases where we would go over a target or a die, so drop this limitation which had a side effect: any request to read more than the content of an eraseblock would simply not benefit from the continuous read feature. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/core.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 66c90419f6d5..fba3cc213c88 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -878,6 +878,12 @@ static int spinand_mtd_continuous_page_read(struct mtd= _info *mtd, loff_t from, * Each data read must be a multiple of 4-bytes and full pages should be = read; * otherwise, the data output might get out of sequence from one read com= mand * to another. + * + * Continuous reads never cross LUN boundaries. Some devices don't + * support crossing planes boundaries. Some devices don't even support + * crossing blocks boundaries. The common case being to read through UBI, + * we will very rarely read two consequent blocks or more, so let's only = enable + * continuous reads when reading within the same erase block. */ nanddev_io_for_each_block(nand, NAND_PAGE_READ, from, ops, &iter) { ret =3D spinand_select_target(spinand, iter.req.pos.target); @@ -968,19 +974,6 @@ static bool spinand_use_cont_read(struct mtd_info *mtd= , loff_t from, nanddev_offs_to_pos(nand, from, &start_pos); nanddev_offs_to_pos(nand, from + ops->len - 1, &end_pos); =20 - /* - * Continuous reads never cross LUN boundaries. Some devices don't - * support crossing planes boundaries. Some devices don't even support - * crossing blocks boundaries. The common case being to read through UBI, - * we will very rarely read two consequent blocks or more, so it is safer - * and easier (can be improved) to only enable continuous reads when - * reading within the same erase block. - */ - if (start_pos.target !=3D end_pos.target || - start_pos.plane !=3D end_pos.plane || - start_pos.eraseblock !=3D end_pos.eraseblock) - return false; - return start_pos.page < end_pos.page; } =20 --=20 2.51.1 From nobody Thu Apr 2 20:22:17 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 0A2B34014AD; Thu, 26 Mar 2026 16:26:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542373; cv=none; b=LWHu9lkdZsGFUDMVqXT5BuCdLTkAlLyJtQWlPiy4zbcB2tgXXqNctN7DAforAjHhR+gPDUYW2Uj84gHAb6W/Yt+CmNXF/hJ6FQx5T7nfch1NaBawrOZtjTak9WUbpt7Cj23qSW/AJHXyXBD1gyWjYXENO5sOYNxkeSBXSk1tzeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542373; c=relaxed/simple; bh=1qAwgYBYxcVwcDIE2uE5OIZ8/YPcuSRMYTt2Fey1oDg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NAwnUg+524lL6Q+M6U+C1xv7I7IVKlIwpI1zQYCO2dwKWAT02w7z0blW3MJr/OryZ86lgcosHwbyGJNF4AzNWBnGN2tkujgNAZg4Zlgh6Y9nidODOH8+QuKBQnbAkoJ6BFTY76ncJDChnPr/XbAB7VuB/o/NZFuBAfGWyofJi0k= 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=rQsdjbtr; arc=none smtp.client-ip=185.171.202.116 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="rQsdjbtr" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id B3C01C566BF; Thu, 26 Mar 2026 16:26:38 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 689C9601FA; Thu, 26 Mar 2026 16:26:10 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 3A2DF10450C96; Thu, 26 Mar 2026 17:26:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542369; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=DPHFbgTjzei/1jBDgO0a2BCQqxzdoh8f4pF7F/hFt2Y=; b=rQsdjbtrg89dCgLudpF3emrB1tcz8lpYZ8tbtHlMK9iSNj7HxqMCYAF6OI+JGDpv//MhtV PYHiG8rZR28gVgX2VjRD/dt0Ykgcdvjsm6EHqP66CaEQpAHvON1XT3HjEZjRdQwSbvCaR3 dcO249WK0IGH9sZRYSVTOAPSKzYWOArpY2i9CZecfpb++aQyP3PgPLLolW88SkJRy3wewU v7pJuIpKQatvr9g9LQqVBsRfpV7W29oObOSACAFvhtb2eVsUU+PLisEn9645ExS+xTAMsz oKNhpTSY/QLCgdhARX3lEZO8+fyQr7UAg89HIN9+gEfCdaFnL753QDPG1fKoVQ== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:49 +0100 Subject: [PATCH v2 02/11] mtd: spinand: Expose spinand_op_is_odtr() 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: <20260326-winbond-v6-18-rc1-cont-read-v2-2-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 This helper is going to be needed in a vendor driver, so expose it. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/core.c | 2 +- include/linux/mtd/spinand.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index fba3cc213c88..1c3ac9ad650e 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -1400,7 +1400,7 @@ static void spinand_manufacturer_cleanup(struct spina= nd_device *spinand) return spinand->manufacturer->ops->cleanup(spinand); } =20 -static bool spinand_op_is_odtr(const struct spi_mem_op *op) +bool spinand_op_is_odtr(const struct spi_mem_op *op) { return op->cmd.dtr && op->cmd.buswidth =3D=3D 8; } diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 6a024cf1c53a..29ce5827032a 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -861,6 +861,8 @@ static inline void spinand_set_of_node(struct spinand_d= evice *spinand, nanddev_set_of_node(&spinand->base, np); } =20 +bool spinand_op_is_odtr(const struct spi_mem_op *op); + int spinand_match_and_init(struct spinand_device *spinand, const struct spinand_info *table, unsigned int table_size, --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 0FDF940FDAF for ; Thu, 26 Mar 2026 16:26:17 +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=1774542379; cv=none; b=CsfOcnXY7u/XBggXPehzIToVvdAoyqvxVGrGmLzguzsWvMjyU09DHfu0JlJv7Ropb2oy9COSkl44zRrCflMIP50uowkPcY0IqzUzsJdjcBGMV3rVKCj/ZWjdd6RrXijlgT/tMcTdh9nelTDUbLGLrUhHEsTJXKKnasF9B6mkhqM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542379; c=relaxed/simple; bh=bZ6BNWvdAQm3cDYqyQDwx0kuZTglGhe3G7YXvwdSTlg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nhpuf1ELWRkkEQwZUcKdEPmeCAZUuN3vtGfw87HuMyMOI115vJTdZwB3YPEvbUvitux1C1iB5PbVesXwLaVPe5fLx8k85S6YKGSEYkWiZF5iTRilTT1Bj+4Pk/ML/aQ2DgzfCD3iFr15nOwjUnax5TV69BNnlzFexpW/ucNLD+c= 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=Of4KHQSA; 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="Of4KHQSA" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id C0ADC1A3008; Thu, 26 Mar 2026 16:26:11 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 8EE1C601FA; Thu, 26 Mar 2026 16:26:11 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id DECB810450C99; Thu, 26 Mar 2026 17:26:09 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542370; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=rlTKENBwUOxRSRFDk4mW7jT5HzuysuTleMW111bj1mo=; b=Of4KHQSA+1zvTKT2x+KYSyjNtVJCsB6+DUdi7HQkfsgkkMtfu0LcfffKZWUeuNZQ1DwbZi zTB36Y271KDhHHeIW89XbzebSpEG08XpFJD4Vm5/Svemzbfp9zIFAAll6TN/14C5OAtILE UmchmGAcsBU4C1Qrptfn8x6Dv2owWWEc/ZcauIMuKs+jTfpxD3gCJeMvn2IpwRm3vROZe0 iCCiAR4iUVEZJTfcGF1Kem/DB4HqIsB99Yei/F40uusDRO4EEwY1GunePX83O6lGgzDYyA MHl7I4cKrKTEhQbSVdS1wfJj/ioW3YEbcXedTJsCGkeFco6aPnraD065CpOkAA== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:50 +0100 Subject: [PATCH v2 03/11] mtd: spinand: Drop ECC dirmaps 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: <20260326-winbond-v6-18-rc1-cont-read-v2-3-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Direct mappings are very static concepts, which allow us to reuse a template to perform reads or writes in a very efficient manner after a single initialization. With the introduction of pipelined ECC engines for SPI controllers, the need to differentiate between an operation with and without correction has arised. The chosen solution at that time has been to create new direct mappings for these operations, jumping from 2 to 4 dirmaps per target. Enabling ECC was done by choosing the correct dirmap. Today, we need to further parametrize dirmaps. With the goal to enable continuous reads on a wider range of devices, we will need more flexibility regarding the read from cache operation template to pick at run time, for instance to use shorter "continuous read from cache" variants. We could create other direct mappings, but it would increase the matrix by a power of two, bringing the theoretical number of dirmaps to 8 (read/write, ecc, shorter read variants) per target. This grow is not sustainable, so let's change how dirmaps work - a little bit. Operations already carry an ECC parameter, use it to indicate whether error correction is required or not. In practice this change happens only at the core level, SPI controller drivers do not care about the direct mapping structure in this case, they just pick whatever is in the template as a base. As a result, we allow the core to dynamically change the content of the templates. He who can do more can do less, so during the checking steps, make sure to enable the ECC requirement just for the time of the checks. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/core.c | 52 +++++++++++++++++------------------------= ---- include/linux/mtd/spinand.h | 2 -- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 1c3ac9ad650e..663f5d6a6bd7 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -487,10 +487,13 @@ static int spinand_read_from_cache_op(struct spinand_= device *spinand, } } =20 - if (req->mode =3D=3D MTD_OPS_RAW) - rdesc =3D spinand->dirmaps[req->pos.plane].rdesc; + rdesc =3D spinand->dirmaps[req->pos.plane].rdesc; + + if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED && + req->mode !=3D MTD_OPS_RAW) + rdesc->info.op_tmpl.data.ecc =3D true; else - rdesc =3D spinand->dirmaps[req->pos.plane].rdesc_ecc; + rdesc->info.op_tmpl.data.ecc =3D false; =20 if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT) column |=3D req->pos.plane << fls(nanddev_page_size(nand)); @@ -579,10 +582,13 @@ static int spinand_write_to_cache_op(struct spinand_d= evice *spinand, req->ooblen); } =20 - if (req->mode =3D=3D MTD_OPS_RAW) - wdesc =3D spinand->dirmaps[req->pos.plane].wdesc; + wdesc =3D spinand->dirmaps[req->pos.plane].wdesc; + + if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED && + req->mode !=3D MTD_OPS_RAW) + wdesc->info.op_tmpl.data.ecc =3D true; else - wdesc =3D spinand->dirmaps[req->pos.plane].wdesc_ecc; + wdesc->info.op_tmpl.data.ecc =3D false; =20 if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT) column |=3D req->pos.plane << fls(nanddev_page_size(nand)); @@ -1231,12 +1237,17 @@ static int spinand_create_dirmap(struct spinand_dev= ice *spinand, struct nand_device *nand =3D spinand_to_nand(spinand); struct spi_mem_dirmap_info info =3D { 0 }; struct spi_mem_dirmap_desc *desc; + bool enable_ecc =3D false; + + if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED) + enable_ecc =3D true; =20 /* The plane number is passed in MSB just above the column address */ info.offset =3D plane << fls(nand->memorg.pagesize); =20 + /* Write descriptor */ info.length =3D nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); - info.op_tmpl =3D *spinand->op_templates->update_cache; + info.op_tmpl.data.ecc =3D enable_ecc; desc =3D devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, spinand->spimem, &info); if (IS_ERR(desc)) @@ -1244,38 +1255,15 @@ static int spinand_create_dirmap(struct spinand_dev= ice *spinand, =20 spinand->dirmaps[plane].wdesc =3D desc; =20 + /* Read descriptor */ info.op_tmpl =3D *spinand->op_templates->read_cache; + info.op_tmpl.data.ecc =3D enable_ecc; desc =3D spinand_create_rdesc(spinand, &info); if (IS_ERR(desc)) return PTR_ERR(desc); =20 spinand->dirmaps[plane].rdesc =3D desc; =20 - if (nand->ecc.engine->integration !=3D NAND_ECC_ENGINE_INTEGRATION_PIPELI= NED) { - spinand->dirmaps[plane].wdesc_ecc =3D spinand->dirmaps[plane].wdesc; - spinand->dirmaps[plane].rdesc_ecc =3D spinand->dirmaps[plane].rdesc; - - return 0; - } - - info.length =3D nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); - info.op_tmpl =3D *spinand->op_templates->update_cache; - info.op_tmpl.data.ecc =3D true; - desc =3D devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, - spinand->spimem, &info); - if (IS_ERR(desc)) - return PTR_ERR(desc); - - spinand->dirmaps[plane].wdesc_ecc =3D desc; - - info.op_tmpl =3D *spinand->op_templates->read_cache; - info.op_tmpl.data.ecc =3D true; - desc =3D spinand_create_rdesc(spinand, &info); - if (IS_ERR(desc)) - return PTR_ERR(desc); - - spinand->dirmaps[plane].rdesc_ecc =3D desc; - return 0; } =20 diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 29ce5827032a..bbf17c346887 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -683,8 +683,6 @@ struct spinand_info { struct spinand_dirmap { struct spi_mem_dirmap_desc *wdesc; struct spi_mem_dirmap_desc *rdesc; - struct spi_mem_dirmap_desc *wdesc_ecc; - struct spi_mem_dirmap_desc *rdesc_ecc; }; =20 /** --=20 2.51.1 From nobody Thu Apr 2 20:22:18 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 183E240B6F6 for ; Thu, 26 Mar 2026 16:26:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542375; cv=none; b=KiR+7VI+WA9tJHGU0qakoN39HCzz2QDm0bTfh4Mdy4+Zaho+HYq0hbq+GAJQ5gchQFJ1zWwf+4lic4OfbPytirD7oWAHs9UEJy0xM8cs18THVJ6CBPHnDJXhNZpMl0QmD5OHoJ3nhTRFUD+BEigRBtkHio2HtyhYw7gU5d6twYQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542375; c=relaxed/simple; bh=680RajdrfFQHYk34GhPzZobTqjn51SOaRR2nKdw15W4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Qy7Qf+HvLEcHtlwz67Hr2045ztG4vIDlMuBBuK+pJrRmvnwd97yy4CyIJrg1W3wKlkhBbesNkfj2Bscf6y6pMYjbsi5bHMTkruBS4lsA66Je2+fAChjNMZK8PN8iVKSL3ruR+yZI0D18eO085kyuRGRC+U/6KnwdgVHhmpE+rqY= 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=M2lKDKd9; arc=none smtp.client-ip=185.171.202.116 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="M2lKDKd9" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 11D79C5506D; Thu, 26 Mar 2026 16:26:41 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id C396F601FA; Thu, 26 Mar 2026 16:26:12 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 279B110450C89; Thu, 26 Mar 2026 17:26:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542372; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=No2FU9QfdRqbWVypforHQbPWeUdzW3YtFHj8aG5zOTE=; b=M2lKDKd9D0WXooDNyS9sGpXtV/vLkVc76lcRrVgNzczHEKneXifP+Fb0FBsYL6IceU0I50 afvLqxyX7tp+SxxJZqY88MG14+9ZYePcd5EX7X0n8xBDE1PYGj2YPN2Qxi69Pc/DU99PpP lZZcKGVpZPXHxZzmA9JJmHU1wburAcNKOlZi2wpR29T1cHYrVfi6u8k8ELXA5pDogYaU15 t7yQkYWRvgJliWkhvo9cwKxf9Gkdb6ukrXzTNIKxx6Dcezn23a73qyjLU36J1/bStEEleD sfH2+U3dB+J1IaTAyXY9gomnUNG2tHdLBmiG9gsO7lwM3NR+c7nIV8kIRWctVw== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:51 +0100 Subject: [PATCH v2 04/11] spi: spi-mem: Transform the read operation template 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: <20260326-winbond-v6-18-rc1-cont-read-v2-4-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 As of now, we only use a single operation template when creating SPI memory direct mappings. With the idea to extend this possibility to 2, rename the template to reflect that we are currently setting the "primary" operation, and create a pointer in the same structure to point to it. From a user point of view, the op_tmpl name remains but becomes a pointer, leading to minor changes in both the SPI NAND and SPI NOR cores. There is no functional change. Acked-by: Mark Brown Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/core.c | 15 ++++++++------- drivers/mtd/spi-nor/core.c | 22 ++++++++++++---------- drivers/spi/spi-mem.c | 15 ++++++++------- include/linux/spi/spi-mem.h | 3 ++- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 663f5d6a6bd7..a66510747b31 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -491,9 +491,9 @@ static int spinand_read_from_cache_op(struct spinand_de= vice *spinand, =20 if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED && req->mode !=3D MTD_OPS_RAW) - rdesc->info.op_tmpl.data.ecc =3D true; + rdesc->info.op_tmpl->data.ecc =3D true; else - rdesc->info.op_tmpl.data.ecc =3D false; + rdesc->info.op_tmpl->data.ecc =3D false; =20 if (spinand->flags & SPINAND_HAS_READ_PLANE_SELECT_BIT) column |=3D req->pos.plane << fls(nanddev_page_size(nand)); @@ -586,9 +586,9 @@ static int spinand_write_to_cache_op(struct spinand_dev= ice *spinand, =20 if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED && req->mode !=3D MTD_OPS_RAW) - wdesc->info.op_tmpl.data.ecc =3D true; + wdesc->info.op_tmpl->data.ecc =3D true; else - wdesc->info.op_tmpl.data.ecc =3D false; + wdesc->info.op_tmpl->data.ecc =3D false; =20 if (spinand->flags & SPINAND_HAS_PROG_PLANE_SELECT_BIT) column |=3D req->pos.plane << fls(nanddev_page_size(nand)); @@ -1247,7 +1247,8 @@ static int spinand_create_dirmap(struct spinand_devic= e *spinand, =20 /* Write descriptor */ info.length =3D nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); - info.op_tmpl.data.ecc =3D enable_ecc; + info.primary_op_tmpl =3D *spinand->op_templates->update_cache; + info.primary_op_tmpl.data.ecc =3D enable_ecc; desc =3D devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev, spinand->spimem, &info); if (IS_ERR(desc)) @@ -1256,8 +1257,8 @@ static int spinand_create_dirmap(struct spinand_devic= e *spinand, spinand->dirmaps[plane].wdesc =3D desc; =20 /* Read descriptor */ - info.op_tmpl =3D *spinand->op_templates->read_cache; - info.op_tmpl.data.ecc =3D enable_ecc; + info.primary_op_tmpl =3D *spinand->op_templates->read_cache; + info.primary_op_tmpl.data.ecc =3D enable_ecc; desc =3D spinand_create_rdesc(spinand, &info); if (IS_ERR(desc)) return PTR_ERR(desc); diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 8ffeb41c3e08..84b98d6b12cd 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -3641,14 +3641,15 @@ EXPORT_SYMBOL_GPL(spi_nor_scan); static int spi_nor_create_read_dirmap(struct spi_nor *nor) { struct spi_mem_dirmap_info info =3D { - .op_tmpl =3D SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0), - SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0), - SPI_MEM_OP_DUMMY(nor->read_dummy, 0), - SPI_MEM_OP_DATA_IN(0, NULL, 0)), + .op_tmpl =3D &info.primary_op_tmpl, + .primary_op_tmpl =3D SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0), + SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0), + SPI_MEM_OP_DUMMY(nor->read_dummy, 0), + SPI_MEM_OP_DATA_IN(0, NULL, 0)), .offset =3D 0, .length =3D nor->params->size, }; - struct spi_mem_op *op =3D &info.op_tmpl; + struct spi_mem_op *op =3D info.op_tmpl; =20 spi_nor_spimem_setup_op(nor, op, nor->read_proto); =20 @@ -3672,14 +3673,15 @@ static int spi_nor_create_read_dirmap(struct spi_no= r *nor) static int spi_nor_create_write_dirmap(struct spi_nor *nor) { struct spi_mem_dirmap_info info =3D { - .op_tmpl =3D SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 0), - SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0), - SPI_MEM_OP_NO_DUMMY, - SPI_MEM_OP_DATA_OUT(0, NULL, 0)), + .op_tmpl =3D &info.primary_op_tmpl, + .primary_op_tmpl =3D SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 0), + SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 0)), .offset =3D 0, .length =3D nor->params->size, }; - struct spi_mem_op *op =3D &info.op_tmpl; + struct spi_mem_op *op =3D info.op_tmpl; =20 if (nor->program_opcode =3D=3D SPINOR_OP_AAI_WP && nor->sst_write_second) op->addr.nbytes =3D 0; diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index a09371a075d2..e2eaa1ba4ff6 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -647,7 +647,7 @@ EXPORT_SYMBOL_GPL(spi_mem_calc_op_duration); static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf) { - struct spi_mem_op op =3D desc->info.op_tmpl; + struct spi_mem_op op =3D *desc->info.op_tmpl; int ret; =20 op.addr.val =3D desc->info.offset + offs; @@ -667,7 +667,7 @@ static ssize_t spi_mem_no_dirmap_read(struct spi_mem_di= rmap_desc *desc, static ssize_t spi_mem_no_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, const void *buf) { - struct spi_mem_op op =3D desc->info.op_tmpl; + struct spi_mem_op op =3D *desc->info.op_tmpl; int ret; =20 op.addr.val =3D desc->info.offset + offs; @@ -706,11 +706,11 @@ spi_mem_dirmap_create(struct spi_mem *mem, int ret =3D -ENOTSUPP; =20 /* Make sure the number of address cycles is between 1 and 8 bytes. */ - if (!info->op_tmpl.addr.nbytes || info->op_tmpl.addr.nbytes > 8) + if (!info->primary_op_tmpl.addr.nbytes || info->primary_op_tmpl.addr.nbyt= es > 8) return ERR_PTR(-EINVAL); =20 /* data.dir should either be SPI_MEM_DATA_IN or SPI_MEM_DATA_OUT. */ - if (info->op_tmpl.data.dir =3D=3D SPI_MEM_NO_DATA) + if (info->primary_op_tmpl.data.dir =3D=3D SPI_MEM_NO_DATA) return ERR_PTR(-EINVAL); =20 desc =3D kzalloc_obj(*desc); @@ -719,6 +719,7 @@ spi_mem_dirmap_create(struct spi_mem *mem, =20 desc->mem =3D mem; desc->info =3D *info; + desc->info.op_tmpl =3D &desc->info.primary_op_tmpl; if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create) { ret =3D spi_mem_access_start(mem); if (ret) { @@ -733,7 +734,7 @@ spi_mem_dirmap_create(struct spi_mem *mem, =20 if (ret) { desc->nodirmap =3D true; - if (!spi_mem_supports_op(desc->mem, &desc->info.op_tmpl)) + if (!spi_mem_supports_op(desc->mem, &desc->info.primary_op_tmpl)) ret =3D -EOPNOTSUPP; else ret =3D 0; @@ -857,7 +858,7 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc = *desc, struct spi_controller *ctlr =3D desc->mem->spi->controller; ssize_t ret; =20 - if (desc->info.op_tmpl.data.dir !=3D SPI_MEM_DATA_IN) + if (desc->info.op_tmpl->data.dir !=3D SPI_MEM_DATA_IN) return -EINVAL; =20 if (!len) @@ -903,7 +904,7 @@ ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc= *desc, struct spi_controller *ctlr =3D desc->mem->spi->controller; ssize_t ret; =20 - if (desc->info.op_tmpl.data.dir !=3D SPI_MEM_DATA_OUT) + if (desc->info.op_tmpl->data.dir !=3D SPI_MEM_DATA_OUT) return -EINVAL; =20 if (!len) diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 5774e554c0f0..3cba7fe4bed5 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -225,7 +225,8 @@ struct spi_mem_op { * direction is directly encoded in the ->op_tmpl.data.dir field. */ struct spi_mem_dirmap_info { - struct spi_mem_op op_tmpl; + struct spi_mem_op *op_tmpl; + struct spi_mem_op primary_op_tmpl; u64 offset; u64 length; }; --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 8949840FD80 for ; Thu, 26 Mar 2026 16:26:15 +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=1774542377; cv=none; b=BVkJRbLy8DZ6Lv8cv39R7CqVqYOCch9lLUixlQu4LirVYgSh9JI+u7JIPmvzgtWWd6zEDmUVGElJejlcwNX7P7nECLosd8FJVnhDkIfxEQYryMeNM7ZtDZaJ/+PWk2NCSuz8PP4H0dPFllEdkZSZaAa4vi0/RGFKwJEjgrW3foc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542377; c=relaxed/simple; bh=bt9cNy4PTjGQSzX5sD2HfXzmDUDdOzPGF/Gog5lLLy8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JeWEC86XgV7PYXmXPFF8svjDTTuALGYd3GzUMhXU3hRTLEoReiGmc9vOEbItJRQNIk0IQtvbcLpEmTA+RXFJ3W2cTzj4mYFlMMDcw7wiP4mjKj4disqlvwpHoV69dhF/oFuHUxKOO0oNcajCdBsncsxvdg6XF9/sADHzxw9O4pM= 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=I/QLYXw9; 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="I/QLYXw9" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 428051A3003; Thu, 26 Mar 2026 16:26:14 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 10BD2601FA; Thu, 26 Mar 2026 16:26:14 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 6784310450C96; Thu, 26 Mar 2026 17:26:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542373; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=AP5EDvNSDOA4mcH2wjjTrtd89tS9FG178G3LqqbkZ1Y=; b=I/QLYXw94NxpfiQ3i07ghpBYmjFR65mBcb2bSgGRkLT8NmTV4awILLREQcVwzt1PZVMrvV TZj3wCkZDcxfM8knSa2UFLliOx2/o6ZrUWutvLmuhCYXqNvqnz/6x64c1XqqxERRPfbCQB NWJOpus8tSl+l2eLgSo17ryVhAB2uk2BUN/Zx7NhXNjqxAVMxIayo8Lnn8x5IJVuFJPF0Z jvdHlB1Z95tZGwifXAeZ056R6XXtp3m/s4K+9QPgSglP2Qr5tAeUMx2J60aSPETUoT6oFY fb4ZFmbjYW/WqLCa/MjXPGtaAWaCrA6UQBAStC5plHZ0Fg/OpiqgZ2Ts+EOTzw== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:52 +0100 Subject: [PATCH v2 05/11] spi: spi-mem: Create a secondary read operation 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: <20260326-winbond-v6-18-rc1-cont-read-v2-5-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 In some situations, direct mappings may need to use different operation templates. For instance, when enabling continuous reads, Winbond SPI NANDs no longer expect address cycles because they would be ignoring them otherwise. Hence, right after the command opcode, they start counting dummy cycles, followed by the data cycles as usual. This breaks the assumptions of "reads from cache" always being done identically once the best variant has been picked up, across the lifetime of the system. In order to support this feature, we must give direct mapping more than a single operation template to use, in order to switch to using secondary operations upon request by the upper layer. Create the concept of optional secondary operation template, which may or may not be fulfilled by the SPI NAND and SPI NOR cores. If the underlying SPI controller does not leverage any kind of direct mapping acceleration, the feature has no impact and can be freely used. Otherwise, the controller driver needs to opt-in for using this feature, if supported. The condition checked to know whether a secondary operation has been provided or not is to look for a non zero opcode to limit the creation of extra variables. In practice, the opcode 0x00 exist, but is not related to any cache related operation. Acked-by: Mark Brown Signed-off-by: Miquel Raynal --- The choice of defining two variables named primary and secondary instead of using an array of templates is on purpose, to simplify the reading. I find less obvious the use of an array here but this is personal taste. --- drivers/spi/spi-mem.c | 17 +++++++++++++++++ include/linux/spi/spi-mem.h | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index e2eaa1ba4ff6..f64eda9bbd9f 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -713,6 +713,23 @@ spi_mem_dirmap_create(struct spi_mem *mem, if (info->primary_op_tmpl.data.dir =3D=3D SPI_MEM_NO_DATA) return ERR_PTR(-EINVAL); =20 + /* Apply similar constraints to the secondary template */ + if (info->secondary_op_tmpl.cmd.opcode) { + if (!info->secondary_op_tmpl.addr.nbytes || + info->secondary_op_tmpl.addr.nbytes > 8) + return ERR_PTR(-EINVAL); + + if (info->secondary_op_tmpl.data.dir =3D=3D SPI_MEM_NO_DATA) + return ERR_PTR(-EINVAL); + + if (!spi_mem_supports_op(mem, &info->secondary_op_tmpl)) + return ERR_PTR(-EOPNOTSUPP); + + if (ctlr->mem_ops && ctlr->mem_ops->dirmap_create && + !spi_mem_controller_is_capable(ctlr, secondary_op_tmpl)) + return ERR_PTR(-EOPNOTSUPP); + } + desc =3D kzalloc_obj(*desc); if (!desc) return ERR_PTR(-ENOMEM); diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 3cba7fe4bed5..bd2a73d46980 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -215,6 +215,8 @@ struct spi_mem_op { * struct spi_mem_dirmap_info - Direct mapping information * @op_tmpl: operation template that should be used by the direct mapping = when * the memory device is accessed + * @secondary_op_tmpl: secondary template, may be used as an alternative t= o the + * primary template (decided by the upper layer) * @offset: absolute offset this direct mapping is pointing to * @length: length in byte of this direct mapping * @@ -227,6 +229,7 @@ struct spi_mem_op { struct spi_mem_dirmap_info { struct spi_mem_op *op_tmpl; struct spi_mem_op primary_op_tmpl; + struct spi_mem_op secondary_op_tmpl; u64 offset; u64 length; }; @@ -370,12 +373,14 @@ struct spi_controller_mem_ops { * @swap16: Supports swapping bytes on a 16 bit boundary when configured in * Octal DTR * @per_op_freq: Supports per operation frequency switching + * @secondary_op_tmpl: Supports leveraging a secondary memory operation te= mplate */ struct spi_controller_mem_caps { bool dtr; bool ecc; bool swap16; bool per_op_freq; + bool secondary_op_tmpl; }; =20 #define spi_mem_controller_is_capable(ctlr, cap) \ --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 BDFB14035CD for ; Thu, 26 Mar 2026 16:26:16 +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=1774542378; cv=none; b=qQDIU8fv/PWjBWIDQHy3zji03SysCfY3hR/kPOAlTuBc2ukkre83vu7H2rIy4cdgqFWqKVCYnsWX/oFwFtMl76C2DaHzj17l3u2zzM8zKhA4AaUU27QeH2snd15gY9jM7mPaR1Q9rlQJq/2zMF8jlcCoGQsL1vwREI5OejKYeCQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542378; c=relaxed/simple; bh=TccMusl6o+BjgyLnvQLGHUHiygf8wYGhTl2JaQXdtAI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IMCLB3fLwJcWNEzDZNFmLjn8FeSg1/wgRPCwbdW6eCBHl5bpTZntVZJnrP8wvDw0459R1ZEN39HfzOTaKlCDXNM7raW2HRrYrQuT/Rs+OjJu7zpfIBzhMM8EumKwuWi6UiEPC263rVLSXaBEx28XHgXNZAkpwsLKDe4Px/M9nzQ= 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=FX+aXyR+; 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="FX+aXyR+" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 6769C1A300A; Thu, 26 Mar 2026 16:26:15 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 370DB601FA; Thu, 26 Mar 2026 16:26:15 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A616F10450C95; Thu, 26 Mar 2026 17:26:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542374; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=lFv1r9faEQTu1UkMy2vWIxsC6tbdpaaG5r+kI87RNaQ=; b=FX+aXyR+ZQsx+lELxkC4W095Bv8MkKG/9OTCbji+dUaqS65mJiWgCk0ASLmRNqcL3iwEzS T2ZkfcTlE5B/JcSuQ3YOvob6hCeUYSlNCe0g9NkIUk9nq1VonjwevpGMQzQ1x13yOg5t0b 1C0uypUPLqEAxwHNkz2Kjh90/pwE14rGCyAOJ2rfhIh6GyUMUbRxBJHXw1UlonDort14bT 6bBpVV5o8lDaRaKJEfZRTFvXZDVLyE4u+WX7Ar5D2mPzXFbM5e0iYnyRlF8ePvjSTGctTm ns/IF97kyBQ1dHiCKbQ2hBKfoCZoBbvw4BWtPWoR0niCRSq1OmLBkth9JDsUjw== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:53 +0100 Subject: [PATCH v2 06/11] mtd: spinand: Use secondary ops for continuous reads 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: <20260326-winbond-v6-18-rc1-cont-read-v2-6-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 In case a chip supports continuous reads, but uses a slightly different cache operation for these, it may provide a secondary operation template which will be used only during continuous cache read operations. From a vendor driver point of view, enabling this feature implies providing a new set of templates for these continuous read operations. The core will automatically pick the fastest variant, depending on the hardware capabilities. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/core.c | 61 +++++++++++++++++++++++++++++++++++++++++= +++- include/linux/mtd/spinand.h | 12 +++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index a66510747b31..45c3afb9cceb 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -489,6 +489,11 @@ static int spinand_read_from_cache_op(struct spinand_d= evice *spinand, =20 rdesc =3D spinand->dirmaps[req->pos.plane].rdesc; =20 + if (spinand->op_templates->cont_read_cache && req->continuous) + rdesc->info.op_tmpl =3D &rdesc->info.secondary_op_tmpl; + else + rdesc->info.op_tmpl =3D &rdesc->info.primary_op_tmpl; + if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED && req->mode !=3D MTD_OPS_RAW) rdesc->info.op_tmpl->data.ecc =3D true; @@ -1221,6 +1226,7 @@ static struct spi_mem_dirmap_desc *spinand_create_rde= sc( * its spi controller, use regular reading */ spinand->cont_read_possible =3D false; + memset(&info->secondary_op_tmpl, 0, sizeof(info->secondary_op_tmpl)); =20 info->length =3D nanddev_page_size(nand) + nanddev_per_page_oobsize(nand); @@ -1237,11 +1243,24 @@ static int spinand_create_dirmap(struct spinand_dev= ice *spinand, struct nand_device *nand =3D spinand_to_nand(spinand); struct spi_mem_dirmap_info info =3D { 0 }; struct spi_mem_dirmap_desc *desc; - bool enable_ecc =3D false; + bool enable_ecc =3D false, secondary_op =3D false; =20 if (nand->ecc.engine->integration =3D=3D NAND_ECC_ENGINE_INTEGRATION_PIPE= LINED) enable_ecc =3D true; =20 + if (spinand->cont_read_possible && spinand->op_templates->cont_read_cache) + secondary_op =3D true; + + /* + * Continuous read implies that only the main data is retrieved, backed + * by an on-die ECC engine. It is not possible to use a pipelind ECC + * engine with continuous read. + */ + if (enable_ecc && secondary_op) { + secondary_op =3D false; + spinand->cont_read_possible =3D false; + } + /* The plane number is passed in MSB just above the column address */ info.offset =3D plane << fls(nand->memorg.pagesize); =20 @@ -1259,6 +1278,10 @@ static int spinand_create_dirmap(struct spinand_devi= ce *spinand, /* Read descriptor */ info.primary_op_tmpl =3D *spinand->op_templates->read_cache; info.primary_op_tmpl.data.ecc =3D enable_ecc; + if (secondary_op) { + info.secondary_op_tmpl =3D *spinand->op_templates->cont_read_cache; + info.secondary_op_tmpl.data.ecc =3D enable_ecc; + } desc =3D spinand_create_rdesc(spinand, &info); if (IS_ERR(desc)) return PTR_ERR(desc); @@ -1607,6 +1630,33 @@ int spinand_match_and_init(struct spinand_device *sp= inand, if (ret) return ret; =20 + if (info->op_variants.cont_read_cache) { + op =3D spinand_select_op_variant(spinand, SSDR, + info->op_variants.cont_read_cache); + if (op) { + const struct spi_mem_op *read_op; + + read_op =3D spinand->ssdr_op_templates.read_cache; + + /* + * Sometimes the fastest continuous read variant may not + * be supported. In this case, prefer to use the fastest + * read from cache variant and disable continuous reads. + */ + if (read_op->cmd.buswidth > op->cmd.buswidth || + (read_op->cmd.dtr && !op->cmd.dtr) || + read_op->addr.buswidth > op->addr.buswidth || + (read_op->addr.dtr && !op->addr.dtr) || + read_op->data.buswidth > op->data.buswidth || + (read_op->data.dtr && !op->data.dtr)) + spinand->cont_read_possible =3D false; + else + spinand->ssdr_op_templates.cont_read_cache =3D op; + } else { + spinand->cont_read_possible =3D false; + } + } + /* I/O variants selection with octo-spi DDR commands (optional) */ =20 ret =3D spinand_init_odtr_instruction_set(spinand); @@ -1629,6 +1679,15 @@ int spinand_match_and_init(struct spinand_device *sp= inand, info->op_variants.update_cache); spinand->odtr_op_templates.update_cache =3D op; =20 + if (info->op_variants.cont_read_cache) { + op =3D spinand_select_op_variant(spinand, ODTR, + info->op_variants.cont_read_cache); + if (op) + spinand->odtr_op_templates.cont_read_cache =3D op; + else + spinand->cont_read_possible =3D false; + } + return 0; } =20 diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index bbf17c346887..aab17e2c8ac9 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -575,6 +575,7 @@ enum spinand_bus_interface { * @op_variants.read_cache: variants of the read-cache operation * @op_variants.write_cache: variants of the write-cache operation * @op_variants.update_cache: variants of the update-cache operation + * @op_variants.cont_read_cache: variants of the continuous read-cache ope= ration * @vendor_ops: vendor specific operations * @select_target: function used to select a target/die. Required only for * multi-die chips @@ -599,6 +600,7 @@ struct spinand_info { const struct spinand_op_variants *read_cache; const struct spinand_op_variants *write_cache; const struct spinand_op_variants *update_cache; + const struct spinand_op_variants *cont_read_cache; } op_variants; const struct spinand_op_variants *vendor_ops; int (*select_target)(struct spinand_device *spinand, @@ -628,6 +630,14 @@ struct spinand_info { .update_cache =3D __update, \ } =20 +#define SPINAND_INFO_OP_VARIANTS_WITH_CONT(__read, __write, __update, __co= nt_read) \ + { \ + .read_cache =3D __read, \ + .write_cache =3D __write, \ + .update_cache =3D __update, \ + .cont_read_cache =3D __cont_read, \ + } + #define SPINAND_INFO_VENDOR_OPS(__ops) \ .vendor_ops =3D __ops =20 @@ -699,6 +709,7 @@ struct spinand_dirmap { * @read_cache: read cache op template * @write_cache: write cache op template * @update_cache: update cache op template + * @cont_read_cache: continuous read cache op template (optional) */ struct spinand_mem_ops { struct spi_mem_op reset; @@ -713,6 +724,7 @@ struct spinand_mem_ops { const struct spi_mem_op *read_cache; const struct spi_mem_op *write_cache; const struct spi_mem_op *update_cache; + const struct spi_mem_op *cont_read_cache; }; =20 /** --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 0FD4040FDAE; Thu, 26 Mar 2026 16:26:17 +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=1774542379; cv=none; b=R+v7WhmGgPGlXosdDUw13zDHDV7xa5EXZykvRo9apReQj7XwVjmzXhBm5CCx7rnpe+CQfDv4ZUiR3fRwWP4OHZcXqAcmpFVD5Y9zvpsrz5d/zoSd/LF9PNCijlysGraPkoTut+bUrS0bjb4t7bLihUYzb2+CH5JNVKEIbHG8gvw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542379; c=relaxed/simple; bh=Grm0KcDW/hQfrvEz2RQvA5lbZXv8oM4hPqNEBK0bOiw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kVxWYXfAu60TXN835ccxwHqMwHyG0GDO8keZErri5fVNaUEVfxLsybpH8lnup1NERHVjyQyZ4YC+Nliq+H9qShlzj/94PIaZnkZim6iJJDcyzfSwmUlodELB9zlYhxEzrQVYACGrtYTKauqfrA+QXhu3MiCSzcJMakCKEDj6LHk= 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=x66BYHyk; 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="x66BYHyk" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id ABB711A3007; Thu, 26 Mar 2026 16:26:16 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 8323C601FA; Thu, 26 Mar 2026 16:26:16 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id CD72110450C99; Thu, 26 Mar 2026 17:26:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542375; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=nEL/yI+e8WdFT08VKvUrxQ/al4bbADvOFCoIasm5Z3s=; b=x66BYHykGGaeaMJDbt6p+YMwsMgZLR/cujhiEC211mF0PgQ2BEuWIvAGjpAr3Ug9ZMUUfe LEm+BQTS8wur+F88ZZOjXviBIuwo91NWW0Doe6yiZz+zjJVe5Wm7ji3KMtstmwudNXPSGN yWeFcwCetCJqXQ6/SzISqMajg571JmkKIlpmwc49a0ov9bCLUUBP6g3fL9wTG0OXx14jXK EjSXd4Qj7cNMW4EhJmHnH+QdBOdE4gKrfk3i3uKM/kcydhmZvwfcRMsTlUAWiXCJ2gzRIu mqxUsl0oCuW1YMFa3Xms7nzVec4Wu4xKM28k6LjLvEyJhBiKKTsRa+iOIVSBeQ== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:54 +0100 Subject: [PATCH v2 07/11] mtd: spinand: winbond: Ensure chips are ordered by density 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: <20260326-winbond-v6-18-rc1-cont-read-v2-7-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 All W35N0xJW chips have been added in a row, move the definition of the 2 and 4 Gb variants so their respective locations in the table. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/winbond.c | 44 +++++++++++++++++++++-----------------= ---- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index ad22774096e6..f4d4ffaa1f62 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -511,28 +511,6 @@ static const struct spinand_info winbond_spinand_table= [] =3D { SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), - SPINAND_INFO("W35N02JW", /* 1.8V */ - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x22), - NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 2, 1), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, - &update_cache_octal_variants), - 0, - SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), - SPINAND_INFO("W35N04JW", /* 1.8V */ - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23), - NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, - &update_cache_octal_variants), - 0, - SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), /* 2G-bit densities */ SPINAND_INFO("W25M02GV", /* 2x1G-bit 3.3V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), @@ -573,6 +551,17 @@ static const struct spinand_info winbond_spinand_table= [] =3D { &update_cache_variants), 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W35N02JW", /* 1.8V */ + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x22), + NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 2, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, + &write_cache_octal_variants, + &update_cache_octal_variants), + 0, + SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), + SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), + SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), /* 4G-bit densities */ SPINAND_INFO("W25N04KV", /* 3.3V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), @@ -592,6 +581,17 @@ static const struct spinand_info winbond_spinand_table= [] =3D { &update_cache_variants), 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W35N04JW", /* 1.8V */ + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23), + NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, + &write_cache_octal_variants, + &update_cache_octal_variants), + 0, + SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), + SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), + SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), }; =20 static int winbond_spinand_init(struct spinand_device *spinand) --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 70091410D0F; Thu, 26 Mar 2026 16:26: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=1774542381; cv=none; b=dejHWir+HpO/a4dSXSpUfn0HlTCQL7OrlMYhFoLFp12LMmFguwZnVAF2GZudLeeQKhzDexcZVUL5qIqLP9u+P8X2zyvd3Pv+ie89JKndyO6NW/Xxk0fBVHJ0rg7vFFU+wd1AolxqIEcsMZHkcdQe569mYKTcm5vC32jlDdSE0Ik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542381; c=relaxed/simple; bh=geNcZkmQdts04Ek+iWKEAnl5CGLFHQgUTBMBXinM0JE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BBXnbt15UxeCGbh5BFSIeAEjZKf2ZkKOpyZ+A0rrPp/twrp5nFSWaMGkRrKmedmLvokQ0DtbzWcr60Sspz77UZwKjPNOIRyInpu16BCQvZ0aVBOLZPNCDlAUiiQagJsOHiSs1/sysO5/LxSlXCKeuIQEnCj263w5dis3JjxVdJY= 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=ISDYqAUz; 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="ISDYqAUz" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 1CFEC4E4280E; Thu, 26 Mar 2026 16:26:18 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id E0B6A601FA; Thu, 26 Mar 2026 16:26:17 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 2C73010450C97; Thu, 26 Mar 2026 17:26:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542377; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=PjiqCAer8dc/ymhlc49FengV+fEKdf1NUEYJuqvysio=; b=ISDYqAUzCXiSKEhOwaeLxZH24u8R+ua5npYysPiz5lqHCdowOZE/2+KsxVlaJ5Kgc5sSJm 2bTIorlHLN9YtOWR1sVmtZ4NQ8lb2dxtMpIPyhNInWr0Z2cvpFfLENHRwMS00MyBNLM/6Z NjQ3zQ4aoYdV8yEtL/+Wk9Imb9EQZ1G79T+2RnZIwpz4yreFBpZL6TBjRjZykv96gamMZ1 uJpOjJH4J9+9tDIDDbUs5QW3NoPL8GW8Si/OMM1DvgWk2q9DeOKIPMgzCBqXQrNk22eEkW Gba1X5zZAsRv8+zsE2tjs+avLmrs8oD7axbGUz+03CHEfK9TdkBT8nu27EMNcw== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:55 +0100 Subject: [PATCH v2 08/11] mtd: spinand: winbond: Add support for continuous reads on W35NxxJW 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: <20260326-winbond-v6-18-rc1-cont-read-v2-8-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 W35N{01,02,04}JW support being read continuously under certain circumstances. A bit must be set in their configuration register, and a specific read from cache operation, a bit shorter than usual because it no longer requires the address cycles, must be used for the occasion. Setting the "enable" bit is already supported by the core, aside from the subtlety of making sure the HFREQ bit is also set in octal DTR mode above 90MHz. However, handling two different read from cache templates involves creating a list of read from cache variants adapted the continuous reads, ie. without address cycles. Unfortunately, these operations, despite being very close to their original read from cache cousins, are often unsupported by smart SPI controller drivers because reading from cache historically allowed changing the offset at which the host would start by providing a 2-byte column address. In order to prevent issues with this, it has been decided to implement these variants with a single "ignored" address byte (respectively two in the octal DTR case), further reducing the amount of dummy cycles needed before the first bit of data. Enabling continuous reads has a side effect: the ECC status register now may also return the value b11, which means that more than 1 uncorrectable error happened during the read. This non standard behaviour requires to re-implement, almost identically the "get ECC" helper from the core, with just an extra case for this value (it is prefixed "w25w35nxxjw" because all these chips have the same behaviour). Speed gain is substantial, see below. The flash_speed -C benchmark has been run on a TI AM62A7 LP SK with CPU power management disabled, mounted with a W35N01JW chip. 1S-8S-8S: 1 page read speed is 15058 KiB/s 2 page read speed is 15058 KiB/s 3 page read speed is 16800 KiB/s 4 page read speed is 17066 KiB/s 5 page read speed is 18461 KiB/s 6 page read speed is 18461 KiB/s 7 page read speed is 19384 KiB/s 8 page read speed is 19692 KiB/s 9 page read speed is 19384 KiB/s 10 page read speed is 20000 KiB/s 11 page read speed is 20000 KiB/s 12 page read speed is 20000 KiB/s 13 page read speed is 20800 KiB/s 14 page read speed is 20363 KiB/s 15 page read speed is 20000 KiB/s 16 page read speed is 19692 KiB/s 32 page read speed is 19692 KiB/s 64 page read speed is 19692 KiB/s 8D-8D-8D: 1 page read speed is 23272 KiB/s 2 page read speed is 23272 KiB/s 3 page read speed is 28000 KiB/s 4 page read speed is 32000 KiB/s 5 page read speed is 34285 KiB/s 6 page read speed is 34285 KiB/s 7 page read speed is 36000 KiB/s 8 page read speed is 36571 KiB/s 9 page read speed is 36000 KiB/s 10 page read speed is 34285 KiB/s 11 page read speed is 36666 KiB/s 12 page read speed is 40000 KiB/s 13 page read speed is 41600 KiB/s 14 page read speed is 37333 KiB/s 15 page read speed is 40000 KiB/s 16 page read speed is 36571 KiB/s 32 page read speed is 42666 KiB/s 64 page read speed is 42666 KiB/s Signed-off-by: Miquel Raynal --- Not all configurations have been tested/validated yet. --- drivers/mtd/nand/spi/winbond.c | 126 ++++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 111 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index f4d4ffaa1f62..6c11f59a9f8d 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -15,9 +15,11 @@ =20 #define SPINAND_MFR_WINBOND 0xEF =20 +#define WINBOND_CFG_HFREQ BIT(0) #define WINBOND_CFG_BUF_READ BIT(3) =20 #define W25N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4) +#define W25W35NXXJW_STATUS_ECC_MULT_UNCOR (3 << 4) =20 #define W25N0XJW_SR4 0xD0 #define W25N0XJW_SR4_HS BIT(2) @@ -29,6 +31,49 @@ #define W35N01JW_VCR_IO_MODE_OCTAL_DDR 0xC7 #define W35N01JW_VCR_DUMMY_CLOCK_REG 0x01 =20 +/* + * Winbond chips ignore the address bytes during continuous reads, and + * because the dummy cycles are enough they indicate dropping the + * address cycles from the continuous read from cache variants. This is + * very poorly supported by SPI controller drivers which are "wired" to + * always at least provide the column. Keep using address cycles, but + * reduce the number of dummy cycles accordingly. + */ +#define WINBOND_CONT_READ_FROM_CACHE_FAST_1S_1S_1S_OP(ndummy, buf, len, fr= eq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x0b, 1), \ + SPI_MEM_OP_ADDR(1, 0, 1), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_1S_8S_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x8b, 1), \ + SPI_MEM_OP_ADDR(1, 0, 1), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_1D_8D_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x9d, 1), \ + SPI_MEM_DTR_OP_ADDR(1, 0, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy - 1, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_8S_8S_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xcb, 1), \ + SPI_MEM_OP_ADDR(1, 0, 8), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 8), \ + SPI_MEM_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_8D_8D_8D_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x9d, 8), \ + SPI_MEM_DTR_OP_ADDR(2, 0, 8), \ + SPI_MEM_DTR_OP_DUMMY(ndummy - 2, 8), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 8), \ + SPI_MEM_OP_MAX_FREQ(freq)) + /* * "X2" in the core is equivalent to "dual output" in the datasheets, * "X4" in the core is equivalent to "quad output" in the datasheets. @@ -49,6 +94,19 @@ static SPINAND_OP_VARIANTS(read_cache_octal_variants, SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0), SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0)); =20 +static SPINAND_OP_VARIANTS(cont_read_cache_octal_variants, + WINBOND_CONT_READ_FROM_CACHE_8D_8D_8D_OP(24, NULL, 0, 120 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_8D_8D_8D_OP(16, NULL, 0, 86 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_1D_8D_OP(3, NULL, 0, 120 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_1D_8D_OP(2, NULL, 0, 105 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_8S_8S_OP(20, NULL, 0, 0), + WINBOND_CONT_READ_FROM_CACHE_1S_8S_8S_OP(16, NULL, 0, 162 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_8S_8S_OP(12, NULL, 0, 124 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_8S_8S_OP(8, NULL, 0, 86 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_1S_8S_OP(2, NULL, 0, 0), + WINBOND_CONT_READ_FROM_CACHE_1S_1S_8S_OP(1, NULL, 0, 133 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_FAST_1S_1S_1S_OP(1, NULL, 0, 0)); + static SPINAND_OP_VARIANTS(write_cache_octal_variants, SPINAND_PROG_LOAD_8D_8D_8D_OP(true, 0, NULL, 0), SPINAND_PROG_LOAD_1S_8S_8S_OP(true, 0, NULL, 0), @@ -326,6 +384,26 @@ static int w25n02kv_ecc_get_status(struct spinand_devi= ce *spinand, return -EINVAL; } =20 +static int w25w35nxxjw_ecc_get_status(struct spinand_device *spinand, u8 s= tatus) +{ + switch (status & STATUS_ECC_MASK) { + case STATUS_ECC_NO_BITFLIPS: + return 0; + + case STATUS_ECC_HAS_BITFLIPS: + return 1; + + case STATUS_ECC_UNCOR_ERROR: + case W25W35NXXJW_STATUS_ECC_MULT_UNCOR: + return -EBADMSG; + + default: + break; + } + + return -EINVAL; +} + static int w25n0xjw_hs_cfg(struct spinand_device *spinand, enum spinand_bus_interface iface) { @@ -451,6 +529,18 @@ static int w35n0xjw_vcr_cfg(struct spinand_device *spi= nand, return 0; } =20 +static int w35n0xjw_set_cont_read(struct spinand_device *spinand, bool ena= ble) +{ + const struct spi_mem_op *cont_op =3D spinand->op_templates->cont_read_cac= he; + u8 mask =3D enable ? 0 : WINBOND_CFG_BUF_READ; + + if (cont_op && enable && spinand_op_is_odtr(cont_op) && + cont_op->max_freq >=3D 90 * HZ_PER_MHZ) + mask |=3D WINBOND_CFG_HFREQ; + + return spinand_upd_cfg(spinand, WINBOND_CFG_BUF_READ | WINBOND_CFG_HFREQ,= mask); +} + static const struct spinand_info winbond_spinand_table[] =3D { /* 512M-bit densities */ SPINAND_INFO("W25N512GW", /* 1.8V */ @@ -504,13 +594,15 @@ static const struct spinand_info winbond_spinand_tabl= e[] =3D { SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdc, 0x21), NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 1, 1), NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, - &update_cache_octal_variants), + SPINAND_INFO_OP_VARIANTS_WITH_CONT(&read_cache_octal_variants, + &write_cache_octal_variants, + &update_cache_octal_variants, + &cont_read_cache_octal_variants), 0, SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), + SPINAND_ECCINFO(&w35n01jw_ooblayout, w25w35nxxjw_ecc_get_status), + SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg), + SPINAND_CONT_READ(w35n0xjw_set_cont_read)), /* 2G-bit densities */ SPINAND_INFO("W25M02GV", /* 2x1G-bit 3.3V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21), @@ -555,13 +647,15 @@ static const struct spinand_info winbond_spinand_tabl= e[] =3D { SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x22), NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 2, 1), NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, - &update_cache_octal_variants), + SPINAND_INFO_OP_VARIANTS_WITH_CONT(&read_cache_octal_variants, + &write_cache_octal_variants, + &update_cache_octal_variants, + &cont_read_cache_octal_variants), 0, SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), + SPINAND_ECCINFO(&w35n01jw_ooblayout, w25w35nxxjw_ecc_get_status), + SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg), + SPINAND_CONT_READ(w35n0xjw_set_cont_read)), /* 4G-bit densities */ SPINAND_INFO("W25N04KV", /* 3.3V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), @@ -585,13 +679,15 @@ static const struct spinand_info winbond_spinand_tabl= e[] =3D { SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23), NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1), NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, - &update_cache_octal_variants), + SPINAND_INFO_OP_VARIANTS_WITH_CONT(&read_cache_octal_variants, + &write_cache_octal_variants, + &update_cache_octal_variants, + &cont_read_cache_octal_variants), 0, SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops), - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)), + SPINAND_ECCINFO(&w35n01jw_ooblayout, w25w35nxxjw_ecc_get_status), + SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg), + SPINAND_CONT_READ(w35n0xjw_set_cont_read)), }; =20 static int winbond_spinand_init(struct spinand_device *spinand) --=20 2.51.1 From nobody Thu Apr 2 20:22:18 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 80855401485; Thu, 26 Mar 2026 16:26:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542382; cv=none; b=HlGicK2OJJOzkAKnH2G39NYBbs2YQZkXOl6SyPxMrhcommDirzBBWSMQSH32fz7v7XMtzloXQAErYaqRGO7rNW4vbBsxkcVkAbc6qpOAsHr/CL55+aRF2PeqylHpRX6ztaC6MBj3RpTQb+H5LtoKXLaBgFcE6/NL4EpPuAyygSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542382; c=relaxed/simple; bh=2g7luQ8WyYG84yO4kuKurLDAbZpyWfXDWPQGiMCYGfA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nuEs2vIKjUiSoAPT76mKrdp0tEA00FyCJHQ8VGwk3nDkU0asx0SF3tOuJf3wumbzDY1FvU1rseW1Gh2IuiPgdFOwcr94mQAZYteL7qFx9r1+tW2Qq8hI7XuRbbqyMMzHWS2JZmzZ0HzD4956mcfEA9mfDxr4AVaZ9BBW+LWJun4= 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=etKO1z83; arc=none smtp.client-ip=185.171.202.116 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="etKO1z83" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 80937C5505C; Thu, 26 Mar 2026 16:26:47 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 3DC75601FA; Thu, 26 Mar 2026 16:26:19 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 7D8C610450A93; Thu, 26 Mar 2026 17:26:17 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542378; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=TkcWUC0TtSzdMpvi2JDSmyuOip9Q86RjX9UadZNkZZw=; b=etKO1z83O24QvsAEPlHabgdI9VwxmeiZBfLLuPWSRVyIj2setEbXdQoLPOf6zIY+Ca96yM weGeBCIcwnyhaxeuV0/zSiliLu74YIACRZNvhw3Nc7HQojJOp4QrIbQHIVu2G1hZ+rPHod RQYraShXfrtjNCzrN6CCR5tGA7eMGbflcyY5SrACfaJkjWpWK/dV6GqLZ67YKEKZTUxGaD jAY7HXDNu1kl7ERMH4SwuXenemK0+SjJo+3o6hlPqf/ZG35ONbMxJo9YICwEE3IhH4iB4D SeFSmb1qhw+3vdtyJzsd/5xfCPFVY3S3L4DrFI7XOfJJrV/r1uJkXWWm89+CVQ== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:56 +0100 Subject: [PATCH v2 09/11] mtd: spinand: winbond: Create a helper to write the HS bit 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: <20260326-winbond-v6-18-rc1-cont-read-v2-9-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 Updating the HS bit is not complex but implies reading, setting/clearing a bit and writing. Clean a bit this section by moving this logic in its own helper. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/winbond.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 6c11f59a9f8d..b30a343a6672 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -404,13 +404,28 @@ static int w25w35nxxjw_ecc_get_status(struct spinand_= device *spinand, u8 status) return -EINVAL; } =20 +static int w25n0xjw_set_sr4_hs(struct spinand_device *spinand, bool enable) +{ + int ret; + u8 sr4; + + ret =3D spinand_read_reg_op(spinand, W25N0XJW_SR4, &sr4); + if (ret) + return ret; + + if (enable) + sr4 |=3D W25N0XJW_SR4_HS; + else + sr4 &=3D ~W25N0XJW_SR4_HS; + + return spinand_write_reg_op(spinand, W25N0XJW_SR4, sr4); +} + static int w25n0xjw_hs_cfg(struct spinand_device *spinand, enum spinand_bus_interface iface) { const struct spi_mem_op *op; bool hs; - u8 sr4; - int ret; =20 if (iface !=3D SSDR) return -EOPNOTSUPP; @@ -429,20 +444,7 @@ static int w25n0xjw_hs_cfg(struct spinand_device *spin= and, else hs =3D true; =20 - ret =3D spinand_read_reg_op(spinand, W25N0XJW_SR4, &sr4); - if (ret) - return ret; - - if (hs) - sr4 |=3D W25N0XJW_SR4_HS; - else - sr4 &=3D ~W25N0XJW_SR4_HS; - - ret =3D spinand_write_reg_op(spinand, W25N0XJW_SR4, sr4); - if (ret) - return ret; - - return 0; + return w25n0xjw_set_sr4_hs(spinand, hs); } =20 static int w35n0xjw_write_vcr(struct spinand_device *spinand, u8 reg, u8 v= al) --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 2CAA9411631; Thu, 26 Mar 2026 16:26:21 +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=1774542383; cv=none; b=jLqsdJpfJayj9MfzEWcC/lh+1oJieNOgo3kb13DUgAWZykgvfGhH9wpokIvN7c5HNUMgd5vvDv9iRmMKlceX5wF7zIyu1DzYuReLJUaPoadjoE91hm2+85Mo1Le9LrrwAc6i11hZ821w9ysojTNeeXh2IBP9axYr2IrIzK7pZiA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542383; c=relaxed/simple; bh=SmX64hBc0VvAMQmLzdKqKpg2jUqj8tgh7ljKLZKQBMw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=M+yrCyLby6G0TJMsnGT3+tH3+Uh1Z/UaV6EqtzYYkHf6CaogHxwlEQlpOOJOj7D8XizV3uF20APB8NDDQfwML2ypo2H9W0+iVQlnSKrPlkCMB3MIfuySdN2pEoSbbBfw4E0gbYIshkrzHWEUk4z70Jg1sTUXwAZd3fwGTAkG0sw= 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=yNpQjZDO; 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="yNpQjZDO" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id A818D1A3007; Thu, 26 Mar 2026 16:26:20 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 774A2601FA; Thu, 26 Mar 2026 16:26:20 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D215010450CA0; Thu, 26 Mar 2026 17:26:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542379; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=yGIuJpVwWLTfF36jwuLLhNiOA2wGXHIPXa0FAwaadKw=; b=yNpQjZDO1vFDiEPq3WhKYtssiq5FUYuxDMYyFlOkvjHTEEr3eVYwlFgQA90asN7MzpS7ca I5qTCr1d0YD3DYmEEwPlxlGLHD5VsZtRDQDTKux8LYVzlsWphM0i9LNe29B6b5uMg5JWsR 6KUdnok2MS3Wgn5VQ/8QnHvKQOMxkldRFDEtXvT9oWIhMoNg7Q2C/ZLsVjBuGPhFFzruO5 wmEsxdINcjKnYZn5OfppjKkMJOazVlL0JdNWnyH0en46LdnbDOi5fPqZr6SEG7mDwM1paf Z7Vcei3R36l7OzdWj8HVRVg+5DipF009szLRf9L2V+nXIT/Jaj3FhAYbxFU/5A== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:57 +0100 Subject: [PATCH v2 10/11] mtd: spinand: winbond: Create a helper to detect the need for the HS bit 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: <20260326-winbond-v6-18-rc1-cont-read-v2-10-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 The logic is not complex but might be reused to cleanup a bit the section by moving it to a dedicated helper. Signed-off-by: Miquel Raynal --- drivers/mtd/nand/spi/winbond.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index b30a343a6672..ffbcd25b0366 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -421,30 +421,33 @@ static int w25n0xjw_set_sr4_hs(struct spinand_device = *spinand, bool enable) return spinand_write_reg_op(spinand, W25N0XJW_SR4, sr4); } =20 +/* + * SDR dual and quad I/O operations over 104MHz require the HS bit to + * enable a few more dummy cycles. + */ +static bool w25n0xjw_op_needs_hs(const struct spi_mem_op *op) +{ + if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) + return false; + else if (op->cmd.buswidth !=3D 1 || op->addr.buswidth =3D=3D 1) + return false; + else if (op->max_freq && op->max_freq <=3D 104 * HZ_PER_MHZ) + return false; + + return true; +} + static int w25n0xjw_hs_cfg(struct spinand_device *spinand, enum spinand_bus_interface iface) { const struct spi_mem_op *op; - bool hs; =20 if (iface !=3D SSDR) return -EOPNOTSUPP; =20 - /* - * SDR dual and quad I/O operations over 104MHz require the HS bit to - * enable a few more dummy cycles. - */ op =3D spinand->op_templates->read_cache; - if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) - hs =3D false; - else if (op->cmd.buswidth !=3D 1 || op->addr.buswidth =3D=3D 1) - hs =3D false; - else if (op->max_freq && op->max_freq <=3D 104 * HZ_PER_MHZ) - hs =3D false; - else - hs =3D true; =20 - return w25n0xjw_set_sr4_hs(spinand, hs); + return w25n0xjw_set_sr4_hs(spinand, w25n0xjw_op_needs_hs(op)); } =20 static int w35n0xjw_write_vcr(struct spinand_device *spinand, u8 reg, u8 v= al) --=20 2.51.1 From nobody Thu Apr 2 20:22:18 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 4A0A841322C; Thu, 26 Mar 2026 16:26: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=1774542385; cv=none; b=dP3XuYS8MUCNpqJ9OLucLOkc2tPVjmPxgE0FzvV1padhL/bug1VwNWpXoVGC0Y7lxgdQN44HeiQjNpJhnTMvjLkU/SJK1CyM/TyvCdZi0xteG6WuiXZVjlmCboRBwizhVZvWmqD8wZt8220i87ARF0EaKXUihZw+zTHSdwwh79k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774542385; c=relaxed/simple; bh=M1ntLlCWhzjy8C7gxJAHialXQjlZCxpLAcgs08u3NHU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FL0OhicNB7wMRIQ4C9GKMH0tuWA1GIHncWu0MRhSaB6S0Bg74CYsczjK396YG/X7FiBLYlGNUyd8XR+J9pV6vReVVVJJIipi/QUUWPCtlmINyLy6xFjMpn3LgPu6GbbdKpiCHTMlFoG3pN5f4t9WcttUVSAlLqh10kn0xqGi9jY= 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=nFDeEX9z; 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="nFDeEX9z" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id C1C8F4E42811; Thu, 26 Mar 2026 16:26:21 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 986FC601FA; Thu, 26 Mar 2026 16:26:21 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 1500210450CCF; Thu, 26 Mar 2026 17:26:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1774542380; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=QKSWbtT276rh3GXk7MyAFfEVHSYY6wW4cC/KAKHNk0w=; b=nFDeEX9zfBMXR330X5Dp7K8Sc3t9rlgwruKl7w9bLGftH6cBMTd6GQj6GJArCBgLFEdm/h rziAKZ6zse3izXAjBh6aJQwPGTTni+WllDVXksq+PSQ5pjjrlks6Uy/b26b+bVnh4N1PeG ztCEcyC6JqoEig6IgzhGSZExDzJPk9SpoeHh7cazwkwQiHf9Kiroj0AV+UrPznow9Rn59a jPEe8o7yLHSt77XiFDvnRjz6Rgb8sNTPW21SBTBdIvzvvY5qM3QtNmyro3BL82ejAgFQck 2cqtr1Qv0mxrLi6PSc8g9lFxAFZ08sOuMxQ52crXPN/hMdXUenGkWn8K1hjSNg== From: Miquel Raynal Date: Thu, 26 Mar 2026 17:25:58 +0100 Subject: [PATCH v2 11/11] mtd: spinand: winbond: Add support for continuous reads on W25NxxJW 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: <20260326-winbond-v6-18-rc1-cont-read-v2-11-643de97a68a3@bootlin.com> References: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> In-Reply-To: <20260326-winbond-v6-18-rc1-cont-read-v2-0-643de97a68a3@bootlin.com> To: Mark Brown , Richard Weinberger , Vignesh Raghavendra , Michael Walle , Miquel Raynal Cc: Pratyush Yadav , Thomas Petazzoni , Steam Lin , Santhosh Kumar K , linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org X-Mailer: b4 0.14.3 X-Last-TLS-Session-Version: TLSv1.3 As for the W35NxxJW family, add support for W25N{01,02}JW continuous read support. Similar operations require to be done, such as setting a specific bit in a configuration register, and providing a set of read variants without the address cycles. As read from cache variants are badly supported by SPI memory controllers, we create a new set of read from cache templates with a fake address cycle and just enough dummy cycles. There are two unsupported configurations (which would require 4.5 dummy bytes), so we just do not provide them. The same extra value in the ECC is possible as with the W35NxxJW family, so we reference the same helper to retrieve the ECC status. Signed-off-by: Miquel Raynal --- All variants have been validated on a Nuvoton MA35D1 platform. --- drivers/mtd/nand/spi/winbond.c | 108 +++++++++++++++++++++++++++++++++++++= ---- 1 file changed, 98 insertions(+), 10 deletions(-) diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index ffbcd25b0366..578f702528ee 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -46,6 +46,62 @@ SPI_MEM_OP_DATA_IN(len, buf, 1), \ SPI_MEM_OP_MAX_FREQ(freq)) =20 +#define WINBOND_CONT_READ_FROM_CACHE_1S_1D_1D_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x0d, 1), \ + SPI_MEM_DTR_OP_ADDR(2, 0, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 1), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_1S_2S_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1), \ + SPI_MEM_OP_ADDR(1, 0, 1), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_2S_2S_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ + SPI_MEM_OP_ADDR(1, 0, 2), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 2), \ + SPI_MEM_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_2D_2D_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xbd, 1), \ + SPI_MEM_DTR_OP_ADDR(1, 0, 2), \ + SPI_MEM_DTR_OP_DUMMY(ndummy - 1, 2), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 2), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_1S_4S_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1), \ + SPI_MEM_OP_ADDR(1, 0, 1), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 1), \ + SPI_MEM_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_1D_4D_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0x6d, 1), \ + SPI_MEM_DTR_OP_ADDR(1, 0, 1), \ + SPI_MEM_DTR_OP_DUMMY(ndummy - 1, 1), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_4S_4S_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ + SPI_MEM_OP_ADDR(1, 0, 4), \ + SPI_MEM_OP_DUMMY(ndummy - 1, 4), \ + SPI_MEM_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + +#define WINBOND_CONT_READ_FROM_CACHE_1S_4D_4D_OP(ndummy, buf, len, freq) \ + SPI_MEM_OP(SPI_MEM_OP_CMD(0xed, 1), \ + SPI_MEM_DTR_OP_ADDR(1, 0, 4), \ + SPI_MEM_DTR_OP_DUMMY(ndummy - 1, 4), \ + SPI_MEM_DTR_OP_DATA_IN(len, buf, 4), \ + SPI_MEM_OP_MAX_FREQ(freq)) + #define WINBOND_CONT_READ_FROM_CACHE_1S_1S_8S_OP(ndummy, buf, len, freq) \ SPI_MEM_OP(SPI_MEM_OP_CMD(0x8b, 1), \ SPI_MEM_OP_ADDR(1, 0, 1), \ @@ -133,6 +189,20 @@ static SPINAND_OP_VARIANTS(read_cache_dual_quad_dtr_va= riants, SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0), SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 54 * HZ_PER_MHZ)= ); =20 +static SPINAND_OP_VARIANTS(cont_read_cache_dual_quad_dtr_variants, + WINBOND_CONT_READ_FROM_CACHE_1S_4D_4D_OP(11, NULL, 0, 80 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_1D_4D_OP(5, NULL, 0, 80 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_4S_4S_OP(7, NULL, 0, 0), + WINBOND_CONT_READ_FROM_CACHE_1S_4S_4S_OP(6, NULL, 0, 104 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_1S_4S_OP(4, NULL, 0, 0), + WINBOND_CONT_READ_FROM_CACHE_1S_2D_2D_OP(6, NULL, 0, 80 * HZ_PER_MHZ), + /* The 1S_1D_2D variant would require 4.5 dummy bytes, this is not possi= ble */ + WINBOND_CONT_READ_FROM_CACHE_1S_2S_2S_OP(5, NULL, 0, 0), + WINBOND_CONT_READ_FROM_CACHE_1S_2S_2S_OP(4, NULL, 0, 104 * HZ_PER_MHZ), + WINBOND_CONT_READ_FROM_CACHE_1S_1S_2S_OP(4, NULL, 0, 0), + /* The 1S_1D_1D variant would require 4.5 dummy bytes, this is not possi= ble */ + WINBOND_CONT_READ_FROM_CACHE_FAST_1S_1S_1S_OP(4, NULL, 0, 0)); + static SPINAND_OP_VARIANTS(read_cache_variants, SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0, 0), SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0), @@ -445,11 +515,25 @@ static int w25n0xjw_hs_cfg(struct spinand_device *spi= nand, if (iface !=3D SSDR) return -EOPNOTSUPP; =20 + /* + * At this stage, we do not yet know the continuous read template, nor + * if there is going to be one. Let's assume the continuous read + * template will be selected with the same heuristics as the buffered + * read variant, as there cannot be a HS configuration mismatch between + * them. + */ op =3D spinand->op_templates->read_cache; =20 return w25n0xjw_set_sr4_hs(spinand, w25n0xjw_op_needs_hs(op)); } =20 +static int w25n0xjw_set_cont_read(struct spinand_device *spinand, bool ena= ble) +{ + u8 mask =3D enable ? 0 : WINBOND_CFG_BUF_READ; + + return spinand_upd_cfg(spinand, WINBOND_CFG_BUF_READ, mask); +} + static int w35n0xjw_write_vcr(struct spinand_device *spinand, u8 reg, u8 v= al) { struct spi_mem_op op =3D SPINAND_OP(spinand, winbond_write_vcr, @@ -580,12 +664,14 @@ static const struct spinand_info winbond_spinand_tabl= e[] =3D { SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbc, 0x21), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_dual_quad_dtr_variants, - &write_cache_variants, - &update_cache_variants), + SPINAND_INFO_OP_VARIANTS_WITH_CONT(&read_cache_dual_quad_dtr_varian= ts, + &write_cache_variants, + &update_cache_variants, + &cont_read_cache_dual_quad_dtr_variants), SPINAND_HAS_QE_BIT, - SPINAND_ECCINFO(&w25n01jw_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)), + SPINAND_ECCINFO(&w25n01jw_ooblayout, w25w35nxxjw_ecc_get_status), + SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg), + SPINAND_CONT_READ(w25n0xjw_set_cont_read)), SPINAND_INFO("W25N01KV", /* 3.3V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21), NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1), @@ -624,12 +710,14 @@ static const struct spinand_info winbond_spinand_tabl= e[] =3D { SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xbf, 0x22), NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 2, 1), NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_dual_quad_dtr_variants, - &write_cache_variants, - &update_cache_variants), + SPINAND_INFO_OP_VARIANTS_WITH_CONT(&read_cache_dual_quad_dtr_varian= ts, + &write_cache_variants, + &update_cache_variants, + &cont_read_cache_dual_quad_dtr_variants), SPINAND_HAS_QE_BIT, - SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), - SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)), + SPINAND_ECCINFO(&w25m02gv_ooblayout, w25w35nxxjw_ecc_get_status), + SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg), + SPINAND_CONT_READ(w25n0xjw_set_cont_read)), SPINAND_INFO("W25N02KV", /* 3.3V */ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), --=20 2.51.1