linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/3] Fixes for Rockchip NAND controller driver
@ 2023-07-10 12:40 Johan Jonker
  2023-07-10 12:42 ` [PATCH v4 1/3] mtd: rawnand: rockchip: fix oobfree offset and description Johan Jonker
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Johan Jonker @ 2023-07-10 12:40 UTC (permalink / raw)
  To: miquel.raynal
  Cc: richard, vigneshr, heiko, linux-mtd, linux-kernel,
	linux-arm-kernel, linux-rockchip, yifeng.zhao

This serie contains various fixes for the Rockchip NAND controller
driver that showed up while testing boot block writing.

Fixed are:
  Always copy hwecc PA data to/from oob_poi buffer in order to be able
  to read/write the various boot block layouts.
  Add option to safely probe the driver on a NAND with unknown data layout.
  Fix oobfree layout.

Changed V4:
  Reduce subject size
  Add 'Fixes:' tag
  Reword

Changed V3:
  Change patch order, layout fixes first
  Change prefixes
  Reword
  State that patches break all existing jffs2 users

Changed V2:
  Add tag
  Add manufacturer ops
  Reword

Johan Jonker (3):
  mtd: rawnand: rockchip: fix oobfree offset and description
  mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer
  mtd: rawnand: rockchip: add skipbbt option

 .../mtd/nand/raw/rockchip-nand-controller.c   | 52 ++++++++++++-------
 1 file changed, 32 insertions(+), 20 deletions(-)

--
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v4 1/3] mtd: rawnand: rockchip: fix oobfree offset and description
  2023-07-10 12:40 [PATCH v4 0/3] Fixes for Rockchip NAND controller driver Johan Jonker
@ 2023-07-10 12:42 ` Johan Jonker
  2023-07-10 12:42 ` [PATCH v4 2/3] mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer Johan Jonker
  2023-07-10 12:42 ` [PATCH v4 3/3] mtd: rawnand: rockchip: add skipbbt option Johan Jonker
  2 siblings, 0 replies; 5+ messages in thread
From: Johan Jonker @ 2023-07-10 12:42 UTC (permalink / raw)
  To: miquel.raynal
  Cc: richard, vigneshr, heiko, linux-mtd, linux-kernel,
	linux-arm-kernel, linux-rockchip, yifeng.zhao

Rockchip boot blocks are written per 4 x 512 byte sectors per page.
Each page with boot blocks must have a page address (PA) pointer in OOB
to the next page.

The currently advertised free OOB area starts at offset 6, like
if 4 PA bytes were located right after the BBM. This is wrong as the
PA bytes are located right before the ECC bytes.

Fix the layout by allowing access to all bytes between the BBM and the
PA bytes instead of reserving 4 bytes right after the BBM.

This change breaks existing jffs2 users.

Fixes: 058e0e847d54 ("mtd: rawnand: rockchip: NFC driver for RK3308, RK2928 and others")
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---

Changed V4:
  Reduce subject size
  Add 'Fixes:' tag
  Reword

Changed V3:
  Change prefixes
  Reword
  State break existing users.

---

Example:

Wrong free OOB offset starts at OOB6:
oob_region->offset = NFC_SYS_DATA_SIZE + 2;
                   = 4 + 2
                   = 6

oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
                   = 32 - 4 - 2
                   = 26

Together with this length above it overlaps a reserved space for the
boot blocks Page Address(PA)

chip->oob_poi buffer layout for 8 steps:

BBM0   BBM1  OOB2  OOB3  | OOB4  OOB5  OOB6  OOB7

OOB8   OOB9  OOB10 OOB11 | OOB12 OOB13 OOB15 OOB15
OOB16  OOB17 OOB18 OOB19 | OOB20 OOB21 OOB22 OOB23

OOB24  OOB25 OOB26 OOB27 | PA0   PA1   PA2   PA3

ECC0   ECC1  ECC2  ECC3  | ...   ...   ...   ...

Fix by new offset at OOB2:
oob_region->offset = 2;

The full range of free OOB with 8 steps runs from OOB2
till/including OOB27.
---
 drivers/mtd/nand/raw/rockchip-nand-controller.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
index 2312e27362cb..37fc07ba57aa 100644
--- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
+++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
@@ -562,9 +562,10 @@ static int rk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf,
 		 *    BBM  OOB1 OOB2 OOB3 |......|  PA0  PA1  PA2  PA3
 		 *
 		 * The rk_nfc_ooblayout_free() function already has reserved
-		 * these 4 bytes with:
+		 * these 4 bytes together with 2 bytes for BBM
+		 * by reducing it's length:
 		 *
-		 * oob_region->offset = NFC_SYS_DATA_SIZE + 2;
+		 * oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
 		 */
 		if (!i)
 			memcpy(rk_nfc_oob_ptr(chip, i),
@@ -933,12 +934,8 @@ static int rk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
 	if (section)
 		return -ERANGE;

-	/*
-	 * The beginning of the OOB area stores the reserved data for the NFC,
-	 * the size of the reserved data is NFC_SYS_DATA_SIZE bytes.
-	 */
 	oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2;
-	oob_region->offset = NFC_SYS_DATA_SIZE + 2;
+	oob_region->offset = 2;

 	return 0;
 }
--
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 2/3] mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer
  2023-07-10 12:40 [PATCH v4 0/3] Fixes for Rockchip NAND controller driver Johan Jonker
  2023-07-10 12:42 ` [PATCH v4 1/3] mtd: rawnand: rockchip: fix oobfree offset and description Johan Jonker
@ 2023-07-10 12:42 ` Johan Jonker
  2023-07-12 12:43   ` Miquel Raynal
  2023-07-10 12:42 ` [PATCH v4 3/3] mtd: rawnand: rockchip: add skipbbt option Johan Jonker
  2 siblings, 1 reply; 5+ messages in thread
From: Johan Jonker @ 2023-07-10 12:42 UTC (permalink / raw)
  To: miquel.raynal
  Cc: richard, vigneshr, heiko, linux-mtd, linux-kernel,
	linux-arm-kernel, linux-rockchip, yifeng.zhao

Rockchip boot blocks are written per 4 x 512 byte sectors per page.
Each page with boot blocks must have a page address (PA) pointer in OOB
to the next page. Pages are written in a pattern depending on the NAND chip ID.
This logic used to build a page pattern table is not fully disclosed and
is not easy to fit in the MTD framework.
The formula in rk_nfc_write_page_hwecc() function is not correct.
read/write_page_hwecc and read/write_page_raw are not aligned.
Make hwecc and raw behavior identical.
Generate boot block page address and pattern for hwecc in user space
and copy PA data to/from the already reserved last 4 bytes before ECC
in the chip->oob_poi data layout.

This patch breaks all existing jffs2 users that have free OOB overlap
with the reserved space for PA data.

Fixes: 058e0e847d54 ("mtd: rawnand: rockchip: NFC driver for RK3308, RK2928 and others")
Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---

Changed V4:
  Reduce subject size
  Add 'Fixes:' tag
  Fix abbreviation
  Reword

Changed V3:
  Change prefixes
  Reword
---
 .../mtd/nand/raw/rockchip-nand-controller.c   | 34 ++++++++++++-------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
index 37fc07ba57aa..5a04680342c3 100644
--- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
+++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
@@ -598,7 +598,7 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
 	int pages_per_blk = mtd->erasesize / mtd->writesize;
 	int ret = 0, i, boot_rom_mode = 0;
 	dma_addr_t dma_data, dma_oob;
-	u32 reg;
+	u32 tmp;
 	u8 *oob;

 	nand_prog_page_begin_op(chip, page, 0, NULL, 0);
@@ -625,6 +625,13 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
 	 *
 	 *   0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ...
 	 *
+	 * The code here just swaps the first 4 bytes with the last
+	 * 4 bytes without losing any data.
+	 *
+	 * The chip->oob_poi data layout:
+	 *
+	 *    BBM  OOB1 OOB2 OOB3 |......|  PA0  PA1  PA2  PA3
+	 *
 	 * Configure the ECC algorithm supported by the boot ROM.
 	 */
 	if ((page < (pages_per_blk * rknand->boot_blks)) &&
@@ -635,21 +642,17 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
 	}

 	for (i = 0; i < ecc->steps; i++) {
-		if (!i) {
-			reg = 0xFFFFFFFF;
-		} else {
+		if (!i)
+			oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
+		else
 			oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
-			reg = oob[0] | oob[1] << 8 | oob[2] << 16 |
-			      oob[3] << 24;
-		}

-		if (!i && boot_rom_mode)
-			reg = (page & (pages_per_blk - 1)) * 4;
+		tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24;

 		if (nfc->cfg->type == NFC_V9)
-			nfc->oob_buf[i] = reg;
+			nfc->oob_buf[i] = tmp;
 		else
-			nfc->oob_buf[i * (oob_step / 4)] = reg;
+			nfc->oob_buf[i * (oob_step / 4)] = tmp;
 	}

 	dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf,
@@ -812,12 +815,17 @@ static int rk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_on,
 		goto timeout_err;
 	}

-	for (i = 1; i < ecc->steps; i++) {
-		oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
+	for (i = 0; i < ecc->steps; i++) {
+		if (!i)
+			oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
+		else
+			oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
+
 		if (nfc->cfg->type == NFC_V9)
 			tmp = nfc->oob_buf[i];
 		else
 			tmp = nfc->oob_buf[i * (oob_step / 4)];
+
 		*oob++ = (u8)tmp;
 		*oob++ = (u8)(tmp >> 8);
 		*oob++ = (u8)(tmp >> 16);
--
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 3/3] mtd: rawnand: rockchip: add skipbbt option
  2023-07-10 12:40 [PATCH v4 0/3] Fixes for Rockchip NAND controller driver Johan Jonker
  2023-07-10 12:42 ` [PATCH v4 1/3] mtd: rawnand: rockchip: fix oobfree offset and description Johan Jonker
  2023-07-10 12:42 ` [PATCH v4 2/3] mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer Johan Jonker
@ 2023-07-10 12:42 ` Johan Jonker
  2 siblings, 0 replies; 5+ messages in thread
From: Johan Jonker @ 2023-07-10 12:42 UTC (permalink / raw)
  To: miquel.raynal
  Cc: richard, vigneshr, heiko, linux-mtd, linux-kernel,
	linux-arm-kernel, linux-rockchip, yifeng.zhao

On Rockchip SoCs the first boot stages are written on NAND
with help of manufacturer software that uses a different format
then the MTD framework. Skip the automatic BBT scan with the
NAND_SKIP_BBTSCAN option so that the original content is unchanged
during the driver probe.
The NAND_NO_BBM_QUIRK option allows us to erase bad blocks with
the nand_erase_nand() function and the flash_erase command.
With these options the user has the "freedom of choice" by neutral
access mode to read and write in whatever format is needed.

Signed-off-by: Johan Jonker <jbx6244@gmail.com>
---

Changed V4:
  Reduce subject size

Changes V3:
  Change prefixes

Changed V2:
  reword

---

I'm aware that the maintainer finds it "awful",
but it's absolute necessary to:
1: read/write boot blocks in user space without touching original content
2: format a NAND for MTD either with built in or external driver module

So we keep it include in this serie.
---
 drivers/mtd/nand/raw/rockchip-nand-controller.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
index 5a04680342c3..fcda4c760ffa 100644
--- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
+++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
@@ -188,6 +188,10 @@ struct rk_nfc {
 	unsigned long assigned_cs;
 };

+static int skipbbt;
+module_param(skipbbt, int, 0644);
+MODULE_PARM_DESC(skipbbt, "Skip BBT scan if data on the NAND chip is not in MTD format.");
+
 static inline struct rk_nfc_nand_chip *rk_nfc_to_rknand(struct nand_chip *chip)
 {
 	return container_of(chip, struct rk_nfc_nand_chip, chip);
@@ -1153,6 +1157,9 @@ static int rk_nfc_nand_chip_init(struct device *dev, struct rk_nfc *nfc,

 	nand_set_controller_data(chip, nfc);

+	if (skipbbt)
+		chip->options |= NAND_SKIP_BBTSCAN | NAND_NO_BBM_QUIRK;
+
 	chip->options |= NAND_USES_DMA | NAND_NO_SUBPAGE_WRITE;
 	chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;

--
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 2/3] mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer
  2023-07-10 12:42 ` [PATCH v4 2/3] mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer Johan Jonker
@ 2023-07-12 12:43   ` Miquel Raynal
  0 siblings, 0 replies; 5+ messages in thread
From: Miquel Raynal @ 2023-07-12 12:43 UTC (permalink / raw)
  To: Johan Jonker
  Cc: richard, vigneshr, heiko, linux-mtd, linux-kernel,
	linux-arm-kernel, linux-rockchip, yifeng.zhao

Hi Johan,

jbx6244@gmail.com wrote on Mon, 10 Jul 2023 14:42:28 +0200:

> Rockchip boot blocks are written per 4 x 512 byte sectors per page.
> Each page with boot blocks must have a page address (PA) pointer in OOB
> to the next page. Pages are written in a pattern depending on the NAND chip ID.
> This logic used to build a page pattern table is not fully disclosed and
> is not easy to fit in the MTD framework.
> The formula in rk_nfc_write_page_hwecc() function is not correct.
> read/write_page_hwecc and read/write_page_raw are not aligned.
> Make hwecc and raw behavior identical.
> Generate boot block page address and pattern for hwecc in user space
> and copy PA data to/from the already reserved last 4 bytes before ECC
> in the chip->oob_poi data layout.
> 
> This patch breaks all existing jffs2 users that have free OOB overlap
> with the reserved space for PA data.

I think I am fine with your patch, but the description is still way too
imprecise.

You need to separate two things: what is done wrong and perhaps why you
detected it or why you need it. Let me propose something:

"
mtd: rawnand: rockchip: Align hwecc vs. raw page helper layouts

Currently, read/write_page_hwecc() and read/write_page_raw() are not
aligned: there is a mismatch in the OOB bytes which are not
read/written at the same offset in both cases (raw vs. hwecc).

This is a real problem when relying on the presence of the Page
Addresses (PA) when using the NAND chip as a boot device, as the
BootROM expects additional data in the OOB area at specific locations.
<here you can put more context about this, like you do in your current
commit log>.

Align the different helpers. This change breaks existing jffs2 users.
"

> 
> Fixes: 058e0e847d54 ("mtd: rawnand: rockchip: NFC driver for RK3308, RK2928 and others")
> Signed-off-by: Johan Jonker <jbx6244@gmail.com>
> ---
> 
> Changed V4:
>   Reduce subject size
>   Add 'Fixes:' tag
>   Fix abbreviation
>   Reword
> 
> Changed V3:
>   Change prefixes
>   Reword
> ---
>  .../mtd/nand/raw/rockchip-nand-controller.c   | 34 ++++++++++++-------
>  1 file changed, 21 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/rockchip-nand-controller.c b/drivers/mtd/nand/raw/rockchip-nand-controller.c
> index 37fc07ba57aa..5a04680342c3 100644
> --- a/drivers/mtd/nand/raw/rockchip-nand-controller.c
> +++ b/drivers/mtd/nand/raw/rockchip-nand-controller.c
> @@ -598,7 +598,7 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
>  	int pages_per_blk = mtd->erasesize / mtd->writesize;
>  	int ret = 0, i, boot_rom_mode = 0;
>  	dma_addr_t dma_data, dma_oob;
> -	u32 reg;
> +	u32 tmp;
>  	u8 *oob;
> 
>  	nand_prog_page_begin_op(chip, page, 0, NULL, 0);
> @@ -625,6 +625,13 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
>  	 *
>  	 *   0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ...
>  	 *
> +	 * The code here just swaps the first 4 bytes with the last
> +	 * 4 bytes without losing any data.
> +	 *
> +	 * The chip->oob_poi data layout:
> +	 *
> +	 *    BBM  OOB1 OOB2 OOB3 |......|  PA0  PA1  PA2  PA3
> +	 *
>  	 * Configure the ECC algorithm supported by the boot ROM.
>  	 */
>  	if ((page < (pages_per_blk * rknand->boot_blks)) &&
> @@ -635,21 +642,17 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
>  	}
> 
>  	for (i = 0; i < ecc->steps; i++) {
> -		if (!i) {
> -			reg = 0xFFFFFFFF;
> -		} else {
> +		if (!i)
> +			oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
> +		else
>  			oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
> -			reg = oob[0] | oob[1] << 8 | oob[2] << 16 |
> -			      oob[3] << 24;
> -		}
> 
> -		if (!i && boot_rom_mode)
> -			reg = (page & (pages_per_blk - 1)) * 4;
> +		tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24;
> 
>  		if (nfc->cfg->type == NFC_V9)
> -			nfc->oob_buf[i] = reg;
> +			nfc->oob_buf[i] = tmp;
>  		else
> -			nfc->oob_buf[i * (oob_step / 4)] = reg;
> +			nfc->oob_buf[i * (oob_step / 4)] = tmp;
>  	}
> 
>  	dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf,
> @@ -812,12 +815,17 @@ static int rk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_on,
>  		goto timeout_err;
>  	}
> 
> -	for (i = 1; i < ecc->steps; i++) {
> -		oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
> +	for (i = 0; i < ecc->steps; i++) {
> +		if (!i)
> +			oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE;
> +		else
> +			oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE;
> +
>  		if (nfc->cfg->type == NFC_V9)
>  			tmp = nfc->oob_buf[i];
>  		else
>  			tmp = nfc->oob_buf[i * (oob_step / 4)];
> +
>  		*oob++ = (u8)tmp;
>  		*oob++ = (u8)(tmp >> 8);
>  		*oob++ = (u8)(tmp >> 16);
> --
> 2.30.2
> 


Thanks,
Miquèl

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-07-12 12:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-10 12:40 [PATCH v4 0/3] Fixes for Rockchip NAND controller driver Johan Jonker
2023-07-10 12:42 ` [PATCH v4 1/3] mtd: rawnand: rockchip: fix oobfree offset and description Johan Jonker
2023-07-10 12:42 ` [PATCH v4 2/3] mtd: rawnand: rockchip: copy hwecc PA data to oob_poi buffer Johan Jonker
2023-07-12 12:43   ` Miquel Raynal
2023-07-10 12:42 ` [PATCH v4 3/3] mtd: rawnand: rockchip: add skipbbt option Johan Jonker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).