From nobody Sun Apr 5 13:24:56 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 56A091A9FB7 for ; Tue, 17 Mar 2026 14:24:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757494; cv=none; b=tA1EWNIxQ+qGCqU6Gr3YDTb1a3rpZVXvr20vzA9jFaMbTZuDwhJOn2UBGnXXDP2T1ex13hqMRT4PwDvsn8Bn/NGZLUKALAY3AEy6dPxao7mBXHB8VG1wwWt7Ws7GWvuJa7QXp3yZ7KCR0OC0f95j32WLIxMP5rQ4wPxC7bcM2zs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757494; c=relaxed/simple; bh=82jHg/C84we0ggMOiWeHcRKzXN+cdC4vj8XTNcKMh+Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Qm7xftp5Nk9skBgNEecfGhnFfXWpP5dYPlXuEI1zm3IRBmiSdaqaHRLx1tBEjIm+33++7t1tnjj1DdrRoDjfGYcTFCYagkqAwaXCxnrE3eMtiHsIpNFP5md5IHXEue/Jr5BmI5h1BuORBTsZIC0kSPAZ0xFSNk3iY44d06GvXRA= 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=Wseylebr; 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="Wseylebr" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 00B1E4E42656; Tue, 17 Mar 2026 14:24:52 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id C8FFE5FC9A; Tue, 17 Mar 2026 14:24:51 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E11D7104505FB; Tue, 17 Mar 2026 15:24:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757491; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=1fl+dYL251xXhtusEZ7b8g0kjCughX2VCuIW1qgsL2Q=; b=WseylebrZ8OgCzJNFztlPs25EauF7UnbXMoCwCAXTdAhRWD/i1MJTbLQrPV1tdXufR8tVW oyA06yE0NnU4U62RqsGMuFf0HsLf4MXSsRT7sxBYhGQXz9Gxouode6wEQtIXvgEFPb+xvg AdpNlYJqv6Qa7cDnYiSv6+jhj8k7tl9l7XPPEXdoWhh3VjgjG56kJSEBkwOYCk47LrsHzX T83aV+1B//hI98Fjyvx1Fc/sCT1aVkmpMt0nQe9PS4v4zqrpc6QswdeD7Zd6Iuc0lStGjl DviFp9sCciEyNy7tL5X+TFoptfWVmUATqhsOhB3oCqM+BTASnKLuPk+k96goPQ== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 1/9] mtd: rawnand: sunxi: sunxi_nand_ooblayout_free code clarification Date: Tue, 17 Mar 2026 15:24:29 +0100 Message-ID: <20260317142437.580204-2-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The available length is really USER_DATA_LEN - 2 instead of just 2 (the user data length minus the BBM length) USER_DATA_LEN being 4, that doesn't change anything now, but if USER_DATA_LEN changes, it will. Signed-off-by: Richard Genoud Reviewed-by: Chen-Yu Tsai --- drivers/mtd/nand/raw/sunxi_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index e66adfcca7cd..915f1240546f 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1755,12 +1755,12 @@ static int sunxi_nand_ooblayout_free(struct mtd_inf= o *mtd, int section, =20 /* * The first 2 bytes are used for BB markers, hence we - * only have 2 bytes available in the first user data + * only have USER_DATA_SZ - 2 bytes available in the first user data * section. */ if (!section && ecc->engine_type =3D=3D NAND_ECC_ENGINE_TYPE_ON_HOST) { oobregion->offset =3D 2; - oobregion->length =3D 2; + oobregion->length =3D USER_DATA_SZ - 2; =20 return 0; } From nobody Sun Apr 5 13:24:56 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 ED5F23E5588 for ; Tue, 17 Mar 2026 14:25:08 +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=1773757510; cv=none; b=VRCna+7shmR95G80y5xb+/079KA16Q+4K50vz68ADkLoJwqZzcHcH9OWCXMr9ZwO/sE4E08Tn4mhuqC0FaWfaCEtcsfM3ceHQORH4ej2/CwP7vB1SJxocQiyWG8K8Hx3+CiHrvJcWoTJj6ISvjEgjI92ty2zWoPr47byGYisi9I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757510; c=relaxed/simple; bh=DJAzBHsTjBw4oM+pSBR4bqr3HXDHu7NQIDcmq6+PG/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=S9PoD0aQRkEVBeNbL3uKxVgK85z/MIUjZNFnLJCYoc25H2lWtCtlarDluUpp+mPUMfr6i2gzHBv8MPm9Evytb1eyTKQV6UdVJWYyYM5uf0V1MgraCNMuJuh7mXDe4elk87+/PBEKYycbZcn8lFG7vc6UQvwgVtC8yEbD+39FDB0= 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=ykjH+AOn; 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="ykjH+AOn" Received: from smtpout-01.galae.net (unknown [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 5C658C55071; Tue, 17 Mar 2026 14:25:28 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4C6E85FC9A; Tue, 17 Mar 2026 14:24:54 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 88C56104505FC; Tue, 17 Mar 2026 15:24:51 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757493; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=cDyw0VT/gRD0S6ZYgJzuggHzvkdYaJdJvFIQKhQJvv0=; b=ykjH+AOnDg0Ovh6NMWJk9k7DZ654ToPDcrq+hyh1JORlcjPV2LoEMIc3w0foci1lA9pDVB HII+BNkTM3RV6/I447xNxK5lrgaYlNF9RBmIIzD0WZEu3iDZLYVAEBYFkuvFSkLERy/1Q5 /rxyx3ComX+XAJ+H0usyV7J4RW6z5AF9Yz5MWUVsxex71ad0K+0LY0t9lXFpX28ztN6RhV rwI9/D87m7E50FmmM8Y4n1/OiawVR/MkoaTMnNtBRYS8FBKJKF4k3q9ae+TN6YPoePhs4C h1na2Qa2d51Rbbi3BLSGMyNvSoCW8g9FR9PW6/fxFva7YHH1AuIsQgrMx2sjJQ== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 2/9] mtd: rawnand: sunxi: fix sunxi_nfc_hw_ecc_read_extra_oob Date: Tue, 17 Mar 2026 15:24:30 +0100 Message-ID: <20260317142437.580204-3-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" When dumping the OOB, the bytes at the end where actually copied from the beginning of the OOB instead of current_offset. That leads to something like: OOB: ff ff ff ff ff ff ff ff ea 19 00 3a 83 db aa 8d OOB: 99 09 c8 9a 90 36 35 7d aa 15 13 07 3d 97 b2 a4 OOB: a8 bb 19 b3 07 e9 f6 25 52 d7 1a 23 e2 7e 0a e4 OOB: 52 8a 09 d2 1a 86 3d cf b4 99 43 13 d3 90 33 0b OOB: ff ff ff ff ff ff ff ff ea 19 00 3a 83 db aa 8d OOB: 99 09 c8 9a 90 36 35 7d aa 15 13 07 3d 97 b2 a4 OOB: a8 bb 19 b3 07 e9 f6 25 52 d7 1a 23 e2 7e 0a e4 OOB: 52 8a 09 d2 1a 86 3d cf b4 99 43 13 d3 90 33 0b instead of: OOB: ff ff ff ff ff ff ff ff ea 19 00 3a 83 db aa 8d OOB: 99 09 c8 9a 90 36 35 7d aa 15 13 07 3d 97 b2 a4 OOB: a8 bb 19 b3 07 e9 f6 25 52 d7 1a 23 e2 7e 0a e4 OOB: 52 8a 09 d2 1a 86 3d cf b4 99 43 13 d3 90 33 0b OOB: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff OOB: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff OOB: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff OOB: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff (example with BCH16, user data [8,0], no scrambling) *cur_off (offset from the beginning of the page) was compared to offset (offset from the beginning of the OOB), and then, the nand_change_read_column_op() sets the current position to the beginning of the OOB instead of OOB+offset Fixes: 15d6f118285f ("mtd: rawnand: sunxi: Stop supporting ECC_HW_SYNDROME = mode") Reviewed-by: Jernej Skrabec Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 915f1240546f..8af449e548d4 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1048,9 +1048,9 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct na= nd_chip *nand, if (len <=3D 0) return; =20 - if (!cur_off || *cur_off !=3D offset) - nand_change_read_column_op(nand, mtd->writesize, NULL, 0, - false); + if (!cur_off || *cur_off !=3D (offset + mtd->writesize)) + nand_change_read_column_op(nand, mtd->writesize + offset, + NULL, 0, false); =20 if (!randomize) sunxi_nfc_read_buf(nand, oob + offset, len); From nobody Sun Apr 5 13:24:56 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 AD9633E51C3 for ; Tue, 17 Mar 2026 14:24:58 +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=1773757500; cv=none; b=AoS97fStFqM5q4N8eVLdyyMv+uQbpA9CnRK/wgk42fV+3aWKis88J4APOF8PmRnc1yN9/BL7PO+2Eqv2+OWEJt9CeMfV35s8y4VSFyWDoHZ9JuMGv6gjpF2apYd5K67UU9oNFDMt8sPRPRMvB08p5lcwhCItMeO32+/Pu4Og+6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757500; c=relaxed/simple; bh=PfgOsCXsl+pi0ZCorfCOChRkbkY4k6Fg0GJsyOQPHjc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KY7Rdjd6aRMLidkIou9AOA7MTkmRk7lnHez4Z1z/xtkrhurLaWLzgZBtR6ZeaqpYAQRxLEr0eBOFeeY3SDT8uOHPYfCTGadJV3aG8dqL3rP2J+h7mIRUdkidJegMu7wCGwDR7dul1nPKmSMPHiy16CMDVlpRRvYR0/A0itztdGc= 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=K3/5L3zu; 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="K3/5L3zu" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 6372E4E42655; Tue, 17 Mar 2026 14:24:57 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 37DC460050; Tue, 17 Mar 2026 14:24:57 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E1AB2104505F7; Tue, 17 Mar 2026 15:24:53 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757496; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=hyGXXt1Kxrs7+JS0CPjoJ6kFefA2UlshIdyS4e4XdHM=; b=K3/5L3zuZao6Ge5V8jOYelFyN7L/stSmAEZnshFq4TcgvtDznajZPAwD588Uv3+Fj+YuXe e8zMYywjSAPLSkATBHnzo8l7B0dZZJXvEjDZsUAX7LLnCcEAxArLFHfa9VnspdXAoOuFZC 7sJpR5tT2EFGXjqDBY5x8JIhAKs+M6XOQn8jj4ZZ79WXAiFAFnYnUfy850yvsW+iDzSzj7 9bvFk6xlF6I/AG4EOZp0ErP7Lh0h8u5YamrdehQmSFgExN7BtjaTH1k/J47bl0lC4lWpBi FkbBR6TXp+Ipc4LZgCDZbEEbimWPm/6xl8RsaRrK6uiSNCyfoRiW0ft1psBy2Q== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 3/9] mtd: rawnand: sunxi: do not count BBM bytes twice Date: Tue, 17 Mar 2026 15:24:31 +0100 Message-ID: <20260317142437.580204-4-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" BBM is already part of USER_DATA section, so we should not remove it twice This was working ok because we are on the safe size, advertising that there was 2 bytes less available than in reality. But we can't change old platforms, since it may lead to a different ECC strength, so, introduce a legacy flag for old platforms, and switch the new platforms to the correct count. Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 8af449e548d4..d126dc18ef27 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -275,6 +275,8 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(str= uct nand_chip *nand) * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks * @has_ecc_clk: If the controller needs an ECC clock. * @has_mbus_clk: If the controller needs a mbus clock. + * @legacy_max_strength:If the maximize strength function was off by 2 byt= es + * NB: this should not be used in new controllers * @reg_io_data: I/O data register * @reg_ecc_err_cnt: ECC error counter register * @reg_user_data: User data register @@ -304,6 +306,7 @@ struct sunxi_nfc_caps { bool has_ecc_block_512; bool has_ecc_clk; bool has_mbus_clk; + bool legacy_max_strength; unsigned int reg_io_data; unsigned int reg_ecc_err_cnt; unsigned int reg_user_data; @@ -1805,10 +1808,22 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_= chip *nand, ecc->size =3D 1024; nsectors =3D mtd->writesize / ecc->size; =20 - /* Reserve 2 bytes for the BBM */ - bytes =3D (mtd->oobsize - 2) / nsectors; + /* + * The 2 BBM bytes should not be removed from the grand total, + * because they are part of the USER_DATA_SZ. + * But we can't modify that for older platform since it may + * result in a stronger ECC at the end, and break the + * compatibility. + */ + if (nfc->caps->legacy_max_strength) + bytes =3D (mtd->oobsize - 2) / nsectors; + else + bytes =3D mtd->oobsize / nsectors; =20 - /* 4 non-ECC bytes are added before each ECC bytes section */ + /* + * USER_DATA_SZ non-ECC bytes are added before each ECC bytes + * section, they contain the 2 BBM bytes + */ bytes -=3D USER_DATA_SZ; =20 /* and bytes has to be even. */ @@ -2373,6 +2388,7 @@ static const u8 sunxi_user_data_len_h6[] =3D { =20 static const struct sunxi_nfc_caps sunxi_nfc_a10_caps =3D { .has_ecc_block_512 =3D true, + .legacy_max_strength =3D true, .reg_io_data =3D NFC_REG_A10_IO_DATA, .reg_ecc_err_cnt =3D NFC_REG_A10_ECC_ERR_CNT, .reg_user_data =3D NFC_REG_A10_USER_DATA, @@ -2394,6 +2410,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps= =3D { static const struct sunxi_nfc_caps sunxi_nfc_a23_caps =3D { .has_mdma =3D true, .has_ecc_block_512 =3D true, + .legacy_max_strength =3D true, .reg_io_data =3D NFC_REG_A23_IO_DATA, .reg_ecc_err_cnt =3D NFC_REG_A10_ECC_ERR_CNT, .reg_user_data =3D NFC_REG_A10_USER_DATA, From nobody Sun Apr 5 13:24:56 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 EFAC03E5565 for ; Tue, 17 Mar 2026 14:25:00 +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=1773757502; cv=none; b=OJElY50fqO9HXN/fOG7LZVeKv61NStFY0z/8DguMs11aT07QVm8smg1BaqVDwcW6/q/TJxE0RwoewDSP+Qw8rsC8QaesHw4lwQX7WS5kouOIkFfS5CLnTT7czPzR8NLpPqlCttNi2CFyFZ3bZifHu6sSqVulB8C/wvwy4aVLl/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757502; c=relaxed/simple; bh=KbWkE0xerrbCBpcn8lkbOUzzTCyNgP404+chNGHcVv8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BvuaMwrFJG/zMqzuXToeJT6IaGjDq5b4ElB87FP8aHeMFRpBWCzyUbTAIP8Lwr2fZi0MflX0NHuOL6yfyUeNIni9/27Z+s3Mnfm6thlLzk66Su49w+/cRd5OCJKtgn59crggbok/ZVsuxgnSJWxg3DwhGJ+Lf3WWKlZIkaKpNg8= 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=ecr3GlS4; 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="ecr3GlS4" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id A02294E42661; Tue, 17 Mar 2026 14:24:59 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 75D20600E0; Tue, 17 Mar 2026 14:24:59 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 8B5C9104505FB; Tue, 17 Mar 2026 15:24:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757498; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=1UvyLJ/S/s7R/v2QWzX78RjV1H2TGB5loF5BsnWForU=; b=ecr3GlS4/ntkiBjCJBb9m+h5WGJVAxxTNLuU8QAhV8xcC9rfeAezpCJlr7MA4h5Z6ADpqf +EhCwD4PMorXlnpQLKKCgSmA6zX9UF2j0BfF9qigE/Os8+CRX/R1CfiA6oKsF7NF7XZfWU IF5SaikLhM346ci+aeARFkcwaHkA7XyubhqWMiVDroL7Nhs74a37DDJGkejWIX1srrw34F SNrvT+ipdb8wxGDGAAoBAwwI6Q8PWB5vYUBISa5pcQ0aBG1KrHfYpiJcCNXTScpqDWP638 oukvNKTXe5NQmB321x2NCOylZifjtVANlV7n8hJIL+WLkyWb/ChbWLpQcIaytg== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 4/9] mtd: rawnand: sunxi: replace hard coded value by a define - take2 Date: Tue, 17 Mar 2026 15:24:32 +0100 Message-ID: <20260317142437.580204-5-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" The user data length (4) has been replaced almost all over the file, but 2 places were forgotten. The user data is placed before the ECC, for each step. So, in sunxi_nfc_hw_ecc_read_extra_oob(), the offset of the user data in OOB is indeed ((ecc->bytes + USER_DATA_SZ) * ecc->steps); And in sunxi_nand_ooblayout_ecc(), the offset of the ECC chunk in OOB is the same offset plus the current user data size: section * (ecc->bytes + USER_DATA_SZ) + USER_DATA_SZ; Reviewed-by: Jernej Skrabec Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index d126dc18ef27..0b0b5349f446 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1045,7 +1045,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct na= nd_chip *nand, { struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int offset =3D ((ecc->bytes + 4) * ecc->steps); + int offset =3D ((ecc->bytes + USER_DATA_SZ) * ecc->steps); int len =3D mtd->oobsize - offset; =20 if (len <=3D 0) @@ -1741,7 +1741,7 @@ static int sunxi_nand_ooblayout_ecc(struct mtd_info *= mtd, int section, if (section >=3D ecc->steps) return -ERANGE; =20 - oobregion->offset =3D section * (ecc->bytes + USER_DATA_SZ) + 4; + oobregion->offset =3D section * (ecc->bytes + USER_DATA_SZ) + USER_DATA_S= Z; oobregion->length =3D ecc->bytes; =20 return 0; From nobody Sun Apr 5 13:24:56 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 C630B3E5ED1 for ; Tue, 17 Mar 2026 14:25:03 +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=1773757505; cv=none; b=EsI3GN9zuYwxLp2vLoD3Vz98lpLxMh6y6NtKHD73thP5mT5O2sRFvRPiQjnngt2j0RB+TdAGZiIRntkOEvPbKDBsVp9kNJeF3nGvBNr5ic0Sf7LHD3+s6POrD3ZuNQ/RHj1RNz2/8BpWgCdNmxjJTE7TTZ1dSOg7jk7RISt/DDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757505; c=relaxed/simple; bh=km9AhpD/mNN+0fmPbHeVsdDabV1MBVqAwKiGu795+aE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tl9yE0mBZG2KHf/DDOHX4yScLV844SwONuIaue3zYLNnQTnTL3zg45uGMxwpHrPCBIU4kr7lqBLivI2DsuObFIT98g5HZOIdQ/Uim2yW9UumIT5d7iEyZHAuB5yDTFRSG19G2wmTqX8QrQWf/hHvU0bEc3DmMyfhVw1k4h7nkDs= 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=bUHliGVS; 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="bUHliGVS" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 2DC451A2DF9; Tue, 17 Mar 2026 14:25:02 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id F07B1600E3; Tue, 17 Mar 2026 14:25:01 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 02A65104505FC; Tue, 17 Mar 2026 15:24:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757501; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=E9Emq20plq+XttwibzPiXgRgGpuD/bC1Ox5X5v41wYY=; b=bUHliGVSH0oSN8FNRlC8Bkn6KrZSPAfyb5lkLV/rZFRO9FMsDH2Wje4zvUKA0zLvK5daNl O/RxZ8GfMyS4lwKihMkdikbjE2o9Wduc4gM4yPOn4NBLEEo3K+ouE5NvEoILBVjtGLie7K G548RosVZC1f6IyWHtmXMbbx+YtNLUJ5y1qgl3YtTYD1hc7KhiFPw9/2msiS/Mk7+lP4cY lNwpaEbLvBIO0X6FXJFuex8msrG5WLJvchfLSEPhhyIAtLACUXc+cQY08aiw6QVNxF3eho gAhTc9srfLBTFtN41rkpadwnKDJVorv4JDkfIRbZqaYkaaqa77272UVJm7Itvw== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 5/9] mtd: rawnand: sunxi: make the code more self-explanatory Date: Tue, 17 Mar 2026 15:24:33 +0100 Message-ID: <20260317142437.580204-6-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" In sunxi_nfc_hw_ecc_{read,write}_chunk(), the ECC step was forced to 0, the reason is not trivial to get when reading the code. The explanation is that, from the NAND flash controller perspective, we are indeed at step 0 for user data length and ECC errors. Just add a const value with an explanation to clarify things. Acked-by: Jernej Skrabec Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 0b0b5349f446..ca701c75cec5 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -963,6 +963,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip= *nand, u32 pattern_found; bool erased; int ret; + /* From the controller point of view, we are at step 0 */ + const int nfc_step =3D 0; =20 if (*cur_off !=3D data_off) nand_change_read_column_op(nand, data_off, NULL, 0, false); @@ -977,7 +979,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip= *nand, return ret; =20 sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); + sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, nfc_step); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -993,10 +995,9 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chi= p *nand, pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); =20 - ret =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, 0, - readl(nfc->regs + NFC_REG_ECC_ST), - pattern_found, - &erased); + ret =3D sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, + nfc_step, readl(nfc->regs + NFC_REG_ECC_ST), + pattern_found, &erased); if (erased) return 1; =20 @@ -1029,7 +1030,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_ch= ip *nand, sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + USER_DATA_SZ, true, page); =20 - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, 0, + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, bbm, page); } } @@ -1207,6 +1208,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret; + /* From the controller point of view, we are at step 0 */ + const int nfc_step =3D 0; =20 if (data_off !=3D *cur_off) nand_change_write_column_op(nand, data_off, NULL, 0, false); @@ -1223,8 +1226,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); - sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page); + sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, nfc_step); + sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR | NFC_ECC_OP, From nobody Sun Apr 5 13:24:56 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 ED55D3E5585 for ; Tue, 17 Mar 2026 14:25:08 +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=1773757510; cv=none; b=GkizCG4StVMHVISEXHw1Nu5u2MWXKhvPXd5xinAAmioqtyn7RHiQ+gLAmRBmnY0ffNyTuwYMqZvMSdbJpvuwx3FByniKPFOMDpCZbiu9H8qBbsi9rVRaa4m8qcNGRbNwVtClJpfFe5qmwnFFItM/1Xf1QgTeZFkQwzdYm+m/W+M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757510; c=relaxed/simple; bh=PXRtz+AFNFXElofgABMOKjBnpOePYgWHcwo2ttPHwwY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WmCaKbomZF7AjQ/nLTSg9FK2vE3FIByCsIp0Fbf41XE9tWJflNdPuz3UP56A3pZD+03daG9IIFGHksjTbxzIPs4hj1iUynph+v2BFMMk8BlPpabURJrL4ZrBfktQ1JxCujbEyTEg2UrP1D+d8wQFmVRZCHREXD+iC1vpAexp8q4= 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=gETtDY/m; 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="gETtDY/m" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 772D1C55072; Tue, 17 Mar 2026 14:25:31 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4E4F56011D; Tue, 17 Mar 2026 14:25:04 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 675B2104505F7; Tue, 17 Mar 2026 15:25:01 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757503; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=ReYpIf5P0XqKNE/IqjBubHIkClDeft9UJw8AXo2Da0U=; b=gETtDY/marSGyoN7R6wguIOTQdEILbeMlwFAMgdMgnsxBV3tArklCOogLBtKk1d8gFG8qm Jm0hoXCLv1wDqkE4rnYteBz9rwh4QSEeZdlc/tlyT1tgyPAyhCvMpDbqcajMI5GH42xwkQ BcNcyMEa+9kgBoolJJtiJAskjmxfKaqwPE0d7+90oV8jqa2EYTC7GuIJNrL/D/bGpVMLPw OR2WBpAlayVzF2k08/4+JKLztAY7StppFTnwNsnW9T63uy7d6hDU0z4n80lgFYNE3EUVrw 2Hh+ToLUEcP61DMjD/Vhm5nCN9VCoQWsuSsFW58FX7aLbprLC+AwAWZgI7r98g== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 6/9] mtd: rawnand: sunxi: remove dead code Date: Tue, 17 Mar 2026 15:24:34 +0100 Message-ID: <20260317142437.580204-7-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" sunxi_nand_ooblayout_free() is only used in a code path where engine_type =3D=3D NAND_ECC_ENGINE_TYPE_ON_HOST So the other cases can be removed. Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index ca701c75cec5..68e22ce451db 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1756,7 +1756,11 @@ static int sunxi_nand_ooblayout_free(struct mtd_info= *mtd, int section, struct nand_chip *nand =3D mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc =3D &nand->ecc; =20 - if (section > ecc->steps) + /* + * The controller does not provide access to OOB bytes + * past the end of the ECC data. + */ + if (section >=3D ecc->steps) return -ERANGE; =20 /* @@ -1764,26 +1768,15 @@ static int sunxi_nand_ooblayout_free(struct mtd_inf= o *mtd, int section, * only have USER_DATA_SZ - 2 bytes available in the first user data * section. */ - if (!section && ecc->engine_type =3D=3D NAND_ECC_ENGINE_TYPE_ON_HOST) { + if (section =3D=3D 0) { oobregion->offset =3D 2; oobregion->length =3D USER_DATA_SZ - 2; =20 return 0; } =20 - /* - * The controller does not provide access to OOB bytes - * past the end of the ECC data. - */ - if (section =3D=3D ecc->steps && ecc->engine_type =3D=3D NAND_ECC_ENGINE_= TYPE_ON_HOST) - return -ERANGE; - oobregion->offset =3D section * (ecc->bytes + USER_DATA_SZ); - - if (section < ecc->steps) - oobregion->length =3D USER_DATA_SZ; - else - oobregion->length =3D mtd->oobsize - oobregion->offset; + oobregion->length =3D USER_DATA_SZ; =20 return 0; } From nobody Sun Apr 5 13:24:56 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 2B2103E558B for ; Tue, 17 Mar 2026 14:25:09 +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=1773757510; cv=none; b=VUUV3LSMJcIkWHMFlj4+sro2pQGa+lhjtjeT3DVeN703nZx4SwBzc39btbp95qlbf+ThCWHZYUFWBddXnOL34ozgKT/4CqGHWChHSM72ZPezRq0TfYF8aR/V72/Zcq9SvKazTbI3zrwudenVMt4RurzbAZBtrXG1p5AZ9bDa3bs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757510; c=relaxed/simple; bh=g1woTV3yEkdeDkwDBcPQrTzOVh7GVhnMMb7gi8gjbQ4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cdhydkl42mAdoOC1TqpEIw0LjcFeZxILfHDfh1edtWrJYAlLAXnR2ky5K6qCBeiJacXmCIdMGDlF8Bri4pGRmRrdSVYrXN5r1hKmIRzSNYHJMwH4G4R3Hm9ELf+60epHD2dHhJzn35llIulkFqzoTaGJNfsHBTMDFHbzUuNSYPc= 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=CqbAPns7; 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="CqbAPns7" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 80476C55075; Tue, 17 Mar 2026 14:25:31 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 98A995FC9A; Tue, 17 Mar 2026 14:25:06 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id DF9E2104505FE; Tue, 17 Mar 2026 15:25:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757505; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=BrbsAztv/q276b/C/c8lHnbUQV+pP9AxyLo2fJhBj9o=; b=CqbAPns7a/XjfdhNap2qLpTfQR0xrIEVOs9+SBHo3llrTb21rceKCQsb2U/Qg2ynuRy+UB L2/BAgYnXm7qZqHkw6XT9KEezsc+8mEpTFuFS6YlV2X9dQOEEK9IrVm1po3RIpAZecEtP7 KFnk1s35aY5dJN7PRhJCMHXqwYZv5J86ypdKU4Io7fP1ovNwUuKfLtTeGE1xD52tS0tHvy ce/KJyh37G6Sli1PXGFkoGyN70vKrH4fqJmrquh60PFWT/FFp9B0vmmXy28zCeSczQnsA1 hOM2wAm1sgkJmHOICF4MDaRp7DP8wh1orrmUJaGDNN1lmY+Xwu7hITNcFLAZNw== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 7/9] mtd: rawnand: sunxi: change error prone variable name Date: Tue, 17 Mar 2026 15:24:35 +0100 Message-ID: <20260317142437.580204-8-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" In sunxi_nand_hw_ecc_ctrl_init(), i is used as a loop index variable and at the same time as the value used to set ECC mode in ECC control register. To prevent it from being re-used as a loop variable, let's change the naming to ecc_mode. No functional change. Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 68e22ce451db..81e491be3563 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -1796,6 +1796,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_ch= ip *nand, struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_device *nanddev =3D mtd_to_nanddev(mtd); int nsectors; + int ecc_mode; int i; =20 if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) { @@ -1849,18 +1850,18 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_= chip *nand, } =20 /* Add ECC info retrieval from DT */ - for (i =3D 0; i < nfc->caps->nstrengths; i++) { - if (ecc->strength <=3D strengths[i]) { + for (ecc_mode =3D 0; ecc_mode < nfc->caps->nstrengths; ecc_mode++) { + if (ecc->strength <=3D strengths[ecc_mode]) { /* * Update ecc->strength value with the actual strength * that will be used by the ECC engine. */ - ecc->strength =3D strengths[i]; + ecc->strength =3D strengths[ecc_mode]; break; } } =20 - if (i >=3D nfc->caps->nstrengths) { + if (ecc_mode >=3D nfc->caps->nstrengths) { dev_err(nfc->dev, "unsupported strength\n"); return -ENOTSUPP; } @@ -1896,7 +1897,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_ch= ip *nand, ecc->read_oob_raw =3D nand_read_oob_std; ecc->write_oob_raw =3D nand_write_oob_std; =20 - sunxi_nand->ecc.ecc_ctl =3D NFC_ECC_MODE(nfc, i) | NFC_ECC_EXCEPTION | + sunxi_nand->ecc.ecc_ctl =3D NFC_ECC_MODE(nfc, ecc_mode) | NFC_ECC_EXCEPTI= ON | NFC_ECC_PIPELINE | NFC_ECC_EN; =20 if (ecc->size =3D=3D 512) { From nobody Sun Apr 5 13:24:56 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 747D93E5EFF for ; Tue, 17 Mar 2026 14:25:10 +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=1773757511; cv=none; b=VJ0VAPAFrqmPdba5ZEqpA6TsfU6BWvLA+0+mHCT4C6WnYV4ChmxnGqSI5K2nQ0bVJ5sSkxBIeKMHzGH45f9oy4AXI0wkAkAArh8ONLLjdlIxYpsipEv3gbZl9zO04dS58rfbQ/1ugG5U12LZFSii2hgB39XHKcmSRyFbnhS4xZU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757511; c=relaxed/simple; bh=8f2rZDecSgEpsgaXJZ/HMYPdON77L+FyDpsWFX4ZRys=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Okzfx0Q+i3Gq4GfzahtDMKa2wzmE05CE0kLhSsK2FBotdjgMkkDV/hl3yQfLB18qC015Hj66hRDC6nul2ryEEOUhcLmNCylaFE3ZT1hDoAVKCp9lvADf6Awyj1xWKyVcAn/tDbxGWzDWegrg1P0ssp1m7wmvejyCL5rzWuVqkNM= 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=xyTOn8Iv; 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="xyTOn8Iv" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 16A9EC55076; Tue, 17 Mar 2026 14:25:33 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 071435FC9A; Tue, 17 Mar 2026 14:25:09 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 1FEE7104505F9; Tue, 17 Mar 2026 15:25:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757508; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=X7VQhh/JhXPu5QGrk0qvjueePPB/glmqNU70q+jezU4=; b=xyTOn8IvIlhEGY/bUbA+/zRDLkFqn/mY/Ad8sb3AZUPABlwwMFyAmtMY7SUvbW+jc2qUpZ qxREUJv6tjB8xR6Ltkow1J/05VD2ddosGJAaGkE8sDv3ZUDFAvWzpk5dOnA3zdv98qPwuy hgIHCxQbdSE7rnMNc6ykEV81gTvw6fsuutA8t/8sjPzq2Zc8mb3s4pUlog1yo62sptE11F fVRGVO3Ls+ectEH9ik6q1N3jVAHNC8lZwTLLBL1rcF/BbTJTmIqGeAmqqtnUh47N156u9z IaLhG+3yXotxq4RFYgdl4Ztu8l2I1yMz55e+rtcsQp4oZ6Pol+f5jPBj5+90nQ== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 8/9] mtd: rawnand: sunxi: fix typos in comments Date: Tue, 17 Mar 2026 15:24:36 +0100 Message-ID: <20260317142437.580204-9-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" Fix lenghts -> lengths and chuncks -> chunks Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 81e491be3563..3d2580d39e70 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -272,7 +272,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(str= uct nand_chip *nand) * * @has_mdma: Use mbus dma mode, otherwise general dma * through MBUS on A23/A33 needs extra configuration. - * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks + * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chunks * @has_ecc_clk: If the controller needs an ECC clock. * @has_mbus_clk: If the controller needs a mbus clock. * @legacy_max_strength:If the maximize strength function was off by 2 byt= es @@ -294,7 +294,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(str= uct nand_chip *nand) * @nstrengths: Size of @ecc_strengths * @max_ecc_steps: Maximum supported steps for ECC, this is also the * number of user data registers - * @user_data_len_tab: Table of lenghts supported by USER_DATA_LEN regist= er + * @user_data_len_tab: Table of lengths supported by USER_DATA_LEN regist= er * The table index is the value to set in NFC_USER_DATA_LEN * registers, and the corresponding value is the number of * bytes to write From nobody Sun Apr 5 13:24:56 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 4DDC13E7142 for ; Tue, 17 Mar 2026 14:25:13 +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=1773757515; cv=none; b=HbzdPdpJ8sKXQHIK6cw3y967p+7gjq3bJyRMbThkbkMrEcuSlwnjHMCkEg1KOZNjL/Ms4htYBUUAXrzywEsloEMfrl4Ly26t6ktfyFj/kXu1wYw7yK/Y4LRQCjxw9cB9W9eraovfMWBTyFhNLny93yUqOrR5sC315BBL9o66UVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773757515; c=relaxed/simple; bh=e/EC7uhBMg46w4RgVECb7Y2cJdigel5GDEukQpMkRGY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kVl2I9GYIPEXwQeSj6iXj5Qw+9qDxB69WmxhDn0ilyFZpyLDQYRyb2gyghMuvENjb49zc7zRCek2lVa1CFhcJp5+6legt6sF92dAAHQUrMbsbgBsa6f+ptfnBv3n7in8Joeoqkk7DhEVgZLBo9fGqmQ51iJplzULX65BfilK9MM= 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=uzugZXaz; 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="uzugZXaz" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 0A1ED4E42655; Tue, 17 Mar 2026 14:25:12 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id D428A5FC9A; Tue, 17 Mar 2026 14:25:11 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 7CFCC104505FF; Tue, 17 Mar 2026 15:25:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1773757510; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=SdGL0v851iMAfKHdLoaD/OZ4A1ToHP3079kGC0oRrE8=; b=uzugZXazrccAQaFo5vzX9JhFnOmCv++y7NuK+u2eAqeSN82UTMzimrjBsdEU0IP3WU4jpm AXVp+Mt1NKG/6WRW4tp9cdV6ytMBr4R7RgNNHmTAQkhyjWW6pxLkZBmwfsid+ECJbPYBox shsbMfQz84kAMo648QTwBt01s0/onzdtDeZk3+wJ94Dl5TNwiXZ/WvmDUCGtlx7YcDT3AS wUKxfRWGumSgpJwpX3iuNEDiJUn0LYKy+r0XrSqW2P9Dk13hLo5YSykZZ4KLPFCyiRBbG/ oB0YVKSMe/km08X2KXwReicznwU5JINLcRf+wwizNP+TrRMOBBU65oiFQHpZ1A== From: Richard Genoud To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland Cc: Wentao Liang , Maxime Ripard , Boris Brezillon , Thomas Petazzoni , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Richard Genoud Subject: [PATCH v3 9/9] mtd: rawnand: sunxi: introduce maximize variable user data length Date: Tue, 17 Mar 2026 15:24:37 +0100 Message-ID: <20260317142437.580204-10-richard.genoud@bootlin.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260317142437.580204-1-richard.genoud@bootlin.com> References: <20260317142437.580204-1-richard.genoud@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Content-Type: text/plain; charset="utf-8" In Allwinner SoCs, user data can be added in OOB before each ECC data. For older SoCs like A10, the user data size was the size of a register (4 bytes) and was mandatory before each ECC step. So, the A10 OOB Layout is: [4Bytes USER_DATA_STEP0] [ECC_STEP0 bytes] [4bytes USER_DATA_STEP1] [ECC_STEP1 bytes] ... NB: the BBM is stored at the beginning of the USER_DATA_STEP0. Now, for H6/H616 NAND flash controller, this user data can have a different size for each step. So, we are maximizing the user data length to use as many OOB bytes as possible. Fixes: 88fd4e4deae8 ("mtd: rawnand: sunxi: Add support for H616 nand contro= ller") Signed-off-by: Richard Genoud --- drivers/mtd/nand/raw/sunxi_nand.c | 321 ++++++++++++++++++++++++------ 1 file changed, 257 insertions(+), 64 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi= _nand.c index 3d2580d39e70..02647565c8ba 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -209,9 +209,8 @@ =20 /* * On A10/A23, this is the size of the NDFC User Data Register, containing= the - * mandatory user data bytes following the ECC for each ECC step. + * mandatory user data bytes preceding the ECC for each ECC step. * Thus, for each ECC step, we need the ECC bytes + USER_DATA_SZ. - * Those bits are currently unsused, and kept as default value 0xffffffff. * * On H6/H616, this size became configurable, from 0 bytes to 32, via the * USER_DATA_LEN registers. @@ -249,6 +248,7 @@ struct sunxi_nand_hw_ecc { * @timing_ctl: TIMING_CTL register value for this NAND chip * @nsels: number of CS lines required by the NAND chip * @sels: array of CS lines descriptions + * @user_data_bytes: array of user data lengths for all ECC steps */ struct sunxi_nand_chip { struct list_head node; @@ -257,6 +257,7 @@ struct sunxi_nand_chip { unsigned long clk_rate; u32 timing_cfg; u32 timing_ctl; + u8 *user_data_bytes; int nsels; struct sunxi_nand_chip_sel sels[] __counted_by(nsels); }; @@ -823,12 +824,50 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8= *buf) return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } =20 -static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8= *oob, - int step, bool bbm, int page) +static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int s= tep) { - struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + if (!sunxi_nand->user_data_bytes) + return USER_DATA_SZ; =20 - sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)= ), oob); + return sunxi_nand->user_data_bytes[step]; +} + +static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8= *oob, + int step, bool bbm, int page, + unsigned int user_data_sz) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + u32 user_data; + + if (!nfc->caps->reg_user_data_len) { + /* + * For A10, the user data for step n is in the nth + * REG_USER_DATA + */ + user_data =3D readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); + sunxi_nfc_user_data_to_buf(user_data, oob); + } else { + /* + * For H6 NAND controller, the user data for all steps is + * contained in 32 user data registers, but not at a specific + * offset for each step, they are just concatenated. + */ + unsigned int user_data_off =3D 0; + unsigned int reg_off; + u8 *ptr =3D oob; + unsigned int i; + + for (i =3D 0; i < step; i++) + user_data_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + user_data_off /=3D 4; + for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { + reg_off =3D NFC_REG_USER_DATA(nfc, user_data_off + i); + user_data =3D readl(nfc->regs + reg_off); + sunxi_nfc_user_data_to_buf(user_data, ptr); + } + } =20 /* De-randomize the Bad Block Marker. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) @@ -887,17 +926,46 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struc= t nand_chip *nand, bool bbm, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); - u8 user_data[USER_DATA_SZ]; + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); + u8 *user_data =3D NULL; =20 /* Randomize the Bad Block Marker. */ if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { - memcpy(user_data, oob, sizeof(user_data)); + user_data =3D kmalloc(user_data_sz, GFP_KERNEL); + memcpy(user_data, oob, user_data_sz); sunxi_nfc_randomize_bbm(nand, page, user_data); oob =3D user_data; } =20 - writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(nfc, step)); + if (!nfc->caps->reg_user_data_len) { + /* + * For A10, the user data for step n is in the nth + * REG_USER_DATA + */ + writel(sunxi_nfc_buf_to_user_data(oob), + nfc->regs + NFC_REG_USER_DATA(nfc, step)); + } else { + /* + * For H6 NAND controller, the user data for all steps is + * contained in 32 user data registers, but not at a specific + * offset for each step, they are just concatenated. + */ + unsigned int user_data_off =3D 0; + const u8 *ptr =3D oob; + unsigned int i; + + for (i =3D 0; i < step; i++) + user_data_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + user_data_off /=3D 4; + for (i =3D 0; i < user_data_sz / 4; i++, ptr +=3D 4) { + writel(sunxi_nfc_buf_to_user_data(ptr), + nfc->regs + NFC_REG_USER_DATA(nfc, user_data_off + i)); + } + } + + kfree(user_data); } =20 static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, @@ -918,6 +986,8 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *n= and, u8 *data, u8 *oob, bool *erased) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; u32 tmp; =20 @@ -940,7 +1010,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *= nand, u8 *data, u8 *oob, memset(data, pattern, ecc->size); =20 if (oob) - memset(oob, pattern, ecc->bytes + USER_DATA_SZ); + memset(oob, pattern, ecc->bytes + user_data_sz); =20 return 0; } @@ -955,12 +1025,15 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_c= hip *nand, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - bool bbm, bool oob_required, int page) + int step, bool oob_required, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int raw_mode =3D 0; u32 pattern_found; + bool bbm =3D !step; bool erased; int ret; /* From the controller point of view, we are at step 0 */ @@ -978,8 +1051,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chi= p *nand, if (ret) return ret; =20 - sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, nfc_step); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -990,7 +1062,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chi= p *nand, if (ret) return ret; =20 - *cur_off =3D oob_off + ecc->bytes + USER_DATA_SZ; + *cur_off =3D oob_off + ecc->bytes + user_data_sz; =20 pattern_found =3D readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found =3D field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); @@ -1014,10 +1086,10 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, ecc->size); =20 nand_change_read_column_op(nand, oob_off, oob, - ecc->bytes + USER_DATA_SZ, false); + ecc->bytes + user_data_sz, false); =20 ret =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + USER_DATA_SZ, + ecc->bytes + user_data_sz, NULL, 0, ecc->strength); if (ret >=3D 0) raw_mode =3D 1; @@ -1027,11 +1099,11 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, if (oob_required) { nand_change_read_column_op(nand, oob_off, NULL, 0, false); - sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + USER_DATA_SZ, + sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + user_data_sz, true, page); =20 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, - bbm, page); + bbm, page, user_data_sz); } } =20 @@ -1040,13 +1112,42 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_= chip *nand, return raw_mode; } =20 +/* + * Returns the offset of the OOB for each step. + * (it includes the user data before the ECC data.) + */ +static int sunxi_get_oob_offset(struct sunxi_nand_chip *sunxi_nand, + struct nand_ecc_ctrl *ecc, int step) +{ + int ecc_off =3D step * ecc->bytes; + int i; + + for (i =3D 0; i < step; i++) + ecc_off +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + return ecc_off; +} + +/* + * Returns the offset of the ECC for each step. + * So, it's the same as sunxi_get_oob_offset(), + * but it skips the next user data. + */ +static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand, + struct nand_ecc_ctrl *ecc, int step) +{ + return sunxi_get_oob_offset(sunxi_nand, ecc, step) + + sunxi_nfc_user_data_sz(sunxi_nand, step); +} + static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, u8 *oob, int *cur_off, bool randomize, int page) { + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int offset =3D ((ecc->bytes + USER_DATA_SZ) * ecc->steps); + int offset =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len =3D mtd->oobsize - offset; =20 if (len <=3D 0) @@ -1071,6 +1172,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf int nchunks) { bool randomized =3D nand->options & NAND_NEED_SCRAMBLING; + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; @@ -1090,7 +1192,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf =20 sunxi_nfc_hw_ecc_enable(nand); sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); + for (i =3D 0; i < nchunks; i++) + sunxi_nfc_set_user_data_len(nfc, sunxi_nfc_user_data_sz(sunxi_nand, i), = i); sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); =20 @@ -1125,7 +1228,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf =20 for (i =3D 0; i < nchunks; i++) { int data_off =3D i * ecc->size; - int oob_off =3D i * (ecc->bytes + USER_DATA_SZ); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; bool erased; @@ -1143,10 +1247,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf /* TODO: use DMA to retrieve OOB */ nand_change_read_column_op(nand, mtd->writesize + oob_off, - oob, ecc->bytes + USER_DATA_SZ, false); + oob, ecc->bytes + user_data_sz, false); =20 - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, - !i, page); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, + page, user_data_sz); } =20 if (erased) @@ -1158,7 +1262,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct na= nd_chip *nand, uint8_t *buf if (status & NFC_ECC_ERR_MSK(nfc)) { for (i =3D 0; i < nchunks; i++) { int data_off =3D i * ecc->size; - int oob_off =3D i * (ecc->bytes + USER_DATA_SZ); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; =20 @@ -1178,10 +1283,10 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf /* TODO: use DMA to retrieve OOB */ nand_change_read_column_op(nand, mtd->writesize + oob_off, - oob, ecc->bytes + USER_DATA_SZ, false); + oob, ecc->bytes + user_data_sz, false); =20 ret =3D nand_check_erased_ecc_chunk(data, ecc->size, oob, - ecc->bytes + USER_DATA_SZ, + ecc->bytes + user_data_sz, NULL, 0, ecc->strength); if (ret >=3D 0) @@ -1202,11 +1307,14 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct = nand_chip *nand, uint8_t *buf static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, const u8 *data, int data_off, const u8 *oob, int oob_off, - int *cur_off, bool bbm, + int *cur_off, int step, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + bool bbm =3D !step; int ret; /* From the controller point of view, we are at step 0 */ const int nfc_step =3D 0; @@ -1225,8 +1333,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, =20 sunxi_nfc_randomizer_config(nand, page, false); sunxi_nfc_randomizer_enable(nand); - sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, nfc_step); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page); =20 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | @@ -1238,7 +1345,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_c= hip *nand, if (ret) return ret; =20 - *cur_off =3D oob_off + ecc->bytes + USER_DATA_SZ; + *cur_off =3D oob_off + ecc->bytes + user_data_sz; =20 return 0; } @@ -1248,8 +1355,9 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct n= and_chip *nand, int page) { struct mtd_info *mtd =3D nand_to_mtd(nand); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; - int offset =3D ((ecc->bytes + USER_DATA_SZ) * ecc->steps); + int offset =3D sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len =3D mtd->oobsize - offset; =20 if (len <=3D 0) @@ -1268,6 +1376,8 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct n= and_chip *nand, static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, int oob_required, int page) { + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; unsigned int max_bitflips =3D 0; @@ -1280,16 +1390,17 @@ static int sunxi_nfc_hw_ecc_read_page(struct nand_c= hip *nand, uint8_t *buf, =20 sunxi_nfc_hw_ecc_enable(nand); =20 + sunxi_nfc_reset_user_data_len(nfc); for (i =3D 0; i < ecc->steps; i++) { int data_off =3D i * ecc->size; - int oob_off =3D i * (ecc->bytes + USER_DATA_SZ); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); u8 *data =3D buf + data_off; u8 *oob =3D nand->oob_poi + oob_off; =20 ret =3D sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, - !i, oob_required, page); + i, oob_required, page); if (ret < 0) return ret; else if (ret) @@ -1327,6 +1438,8 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nand_= chip *nand, u32 data_offs, u32 readlen, u8 *bufpoi, int page) { + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret, i, cur_off =3D 0; @@ -1338,17 +1451,18 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct nan= d_chip *nand, =20 sunxi_nfc_hw_ecc_enable(nand); =20 + sunxi_nfc_reset_user_data_len(nfc); for (i =3D data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { int data_off =3D i * ecc->size; - int oob_off =3D i * (ecc->bytes + USER_DATA_SZ); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); u8 *data =3D bufpoi + data_off; u8 *oob =3D nand->oob_poi + oob_off; =20 ret =3D sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, &max_bitflips, !i, + &cur_off, &max_bitflips, i, false, page); if (ret < 0) return ret; @@ -1383,6 +1497,8 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_ch= ip *nand, const uint8_t *buf, int oob_required, int page) { + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret, i, cur_off =3D 0; @@ -1393,15 +1509,16 @@ static int sunxi_nfc_hw_ecc_write_page(struct nand_= chip *nand, =20 sunxi_nfc_hw_ecc_enable(nand); =20 + sunxi_nfc_reset_user_data_len(nfc); for (i =3D 0; i < ecc->steps; i++) { int data_off =3D i * ecc->size; - int oob_off =3D i * (ecc->bytes + USER_DATA_SZ); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *data =3D buf + data_off; const u8 *oob =3D nand->oob_poi + oob_off; =20 ret =3D sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, !i, page); + &cur_off, i, page); if (ret) return ret; } @@ -1420,6 +1537,8 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct nand= _chip *nand, const u8 *buf, int oob_required, int page) { + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; int ret, i, cur_off =3D 0; @@ -1430,16 +1549,17 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct na= nd_chip *nand, =20 sunxi_nfc_hw_ecc_enable(nand); =20 + sunxi_nfc_reset_user_data_len(nfc); for (i =3D data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { int data_off =3D i * ecc->size; - int oob_off =3D i * (ecc->bytes + USER_DATA_SZ); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *data =3D buf + data_off; const u8 *oob =3D nand->oob_poi + oob_off; =20 ret =3D sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, !i, page); + &cur_off, i, page); if (ret) return ret; } @@ -1455,6 +1575,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nan= d_chip *nand, int page) { struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); struct nand_ecc_ctrl *ecc =3D &nand->ecc; struct scatterlist sg; u32 wait; @@ -1473,10 +1594,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct n= and_chip *nand, =20 sunxi_nfc_reset_user_data_len(nfc); for (i =3D 0; i < ecc->steps; i++) { - const u8 *oob =3D nand->oob_poi + (i * (ecc->bytes + USER_DATA_SZ)); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, i); + int oob_off =3D sunxi_get_oob_offset(sunxi_nand, ecc, i); + const u8 *oob =3D nand->oob_poi + oob_off; =20 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, i); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); } =20 nand_prog_page_begin_op(nand, page, 0, NULL, 0); @@ -1740,11 +1863,12 @@ static int sunxi_nand_ooblayout_ecc(struct mtd_info= *mtd, int section, { struct nand_chip *nand =3D mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); =20 if (section >=3D ecc->steps) return -ERANGE; =20 - oobregion->offset =3D section * (ecc->bytes + USER_DATA_SZ) + USER_DATA_S= Z; + oobregion->offset =3D sunxi_get_ecc_offset(sunxi_nand, ecc, section); oobregion->length =3D ecc->bytes; =20 return 0; @@ -1755,6 +1879,8 @@ static int sunxi_nand_ooblayout_free(struct mtd_info = *mtd, int section, { struct nand_chip *nand =3D mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc =3D &nand->ecc; + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + unsigned int user_data_sz =3D sunxi_nfc_user_data_sz(sunxi_nand, section); =20 /* * The controller does not provide access to OOB bytes @@ -1765,18 +1891,18 @@ static int sunxi_nand_ooblayout_free(struct mtd_inf= o *mtd, int section, =20 /* * The first 2 bytes are used for BB markers, hence we - * only have USER_DATA_SZ - 2 bytes available in the first user data + * only have user_data_sz - 2 bytes available in the first user data * section. */ if (section =3D=3D 0) { oobregion->offset =3D 2; - oobregion->length =3D USER_DATA_SZ - 2; + oobregion->length =3D user_data_sz - 2; =20 return 0; } =20 - oobregion->offset =3D section * (ecc->bytes + USER_DATA_SZ); - oobregion->length =3D USER_DATA_SZ; + oobregion->offset =3D sunxi_get_ecc_offset(sunxi_nand, ecc, section); + oobregion->length =3D user_data_sz; =20 return 0; } @@ -1786,6 +1912,43 @@ static const struct mtd_ooblayout_ops sunxi_nand_oob= layout_ops =3D { .free =3D sunxi_nand_ooblayout_free, }; =20 +static void sunxi_nand_detach_chip(struct nand_chip *nand) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + + devm_kfree(nfc->dev, sunxi_nand->user_data_bytes); + sunxi_nand->user_data_bytes =3D NULL; +} + +static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t o= obsize, + int ecc_bytes, int nsectors) +{ + struct sunxi_nand_chip *sunxi_nand =3D to_sunxi_nand(nand); + struct sunxi_nfc *nfc =3D to_sunxi_nfc(nand->controller); + const struct sunxi_nfc_caps *c =3D nfc->caps; + int remaining_bytes =3D oobsize - (ecc_bytes * nsectors); + int i, step; + + sunxi_nand->user_data_bytes =3D devm_kzalloc(nfc->dev, nsectors, + GFP_KERNEL); + if (!sunxi_nand->user_data_bytes) + return -ENOMEM; + + for (step =3D 0; (step < nsectors) && (remaining_bytes > 0); step++) { + for (i =3D 0; i < c->nuser_data_tab; i++) { + if (c->user_data_len_tab[i] > remaining_bytes) + break; + sunxi_nand->user_data_bytes[step] =3D c->user_data_len_tab[i]; + } + remaining_bytes -=3D sunxi_nand->user_data_bytes[step]; + if (sunxi_nand->user_data_bytes[step] =3D=3D 0) + break; + } + + return 0; +} + static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, struct nand_ecc_ctrl *ecc, struct device_node *np) @@ -1795,33 +1958,50 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_= chip *nand, const u8 *strengths =3D nfc->caps->ecc_strengths; struct mtd_info *mtd =3D nand_to_mtd(nand); struct nand_device *nanddev =3D mtd_to_nanddev(mtd); + int total_user_data_sz =3D 0; int nsectors; int ecc_mode; int i; =20 if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) { - int bytes; + int bytes =3D mtd->oobsize; =20 ecc->size =3D 1024; nsectors =3D mtd->writesize / ecc->size; =20 - /* - * The 2 BBM bytes should not be removed from the grand total, - * because they are part of the USER_DATA_SZ. - * But we can't modify that for older platform since it may - * result in a stronger ECC at the end, and break the - * compatibility. - */ - if (nfc->caps->legacy_max_strength) - bytes =3D (mtd->oobsize - 2) / nsectors; - else - bytes =3D mtd->oobsize / nsectors; + if (!nfc->caps->reg_user_data_len) { + /* + * If there's a fixed user data length, subtract it before + * computing the max ECC strength + */ + + for (i =3D 0; i < nsectors; i++) + total_user_data_sz +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + /* + * The 2 BBM bytes should not be removed from the grand total, + * because they are part of the USER_DATA_SZ. + * But we can't modify that for older platform since it may + * result in a stronger ECC at the end, and break the + * compatibility. + */ + if (nfc->caps->legacy_max_strength) + bytes -=3D 2; + + bytes -=3D total_user_data_sz; + } else { + /* + * remove at least the BBM size before computing the + * max ECC + */ + bytes -=3D 2; + } =20 /* - * USER_DATA_SZ non-ECC bytes are added before each ECC bytes - * section, they contain the 2 BBM bytes + * Once all user data has been subtracted, the rest can be used + * for ECC bytes */ - bytes -=3D USER_DATA_SZ; + bytes /=3D nsectors; =20 /* and bytes has to be even. */ if (bytes % 2) @@ -1874,7 +2054,19 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_c= hip *nand, =20 nsectors =3D mtd->writesize / ecc->size; =20 - if (mtd->oobsize < ((ecc->bytes + USER_DATA_SZ) * nsectors)) + /* + * The rationale for variable data length is to prioritize maximum ECC + * strength, and then use the remaining space for user data. + */ + if (nfc->caps->reg_user_data_len) + sunxi_nfc_maximize_user_data(nand, mtd->oobsize, ecc->bytes, + nsectors); + + if (total_user_data_sz =3D=3D 0) + for (i =3D 0; i < nsectors; i++) + total_user_data_sz +=3D sunxi_nfc_user_data_sz(sunxi_nand, i); + + if (mtd->oobsize < (ecc->bytes * nsectors + total_user_data_sz)) return -EINVAL; =20 ecc->read_oob =3D sunxi_nfc_hw_ecc_read_oob; @@ -2104,6 +2296,7 @@ static int sunxi_nfc_exec_op(struct nand_chip *nand, =20 static const struct nand_controller_ops sunxi_nand_controller_ops =3D { .attach_chip =3D sunxi_nand_attach_chip, + .detach_chip =3D sunxi_nand_detach_chip, .setup_interface =3D sunxi_nfc_setup_interface, .exec_op =3D sunxi_nfc_exec_op, };