[PATCH v2] ath79: rb4xx-nand: fix 512 byte pages compatibility

Sergey Ryazanov ryazanov.s.a at gmail.com
Mon May 31 13:40:29 PDT 2021


MikroTik boards with 512 byte NAND pages require the old YAFFS1 OOB
layout for compatibility with the RouterBoot bootloader. The RB4xx NAND
driver supports such OOB layout, but checks a NAND page size too early
before the flash identification, what effectively preventing the old OOB
layout from being used.

To fix this issue, move the page size check and OOB layout configuration
to the chip attaching hook, which is specially intorduced for ECC and
OOB tweaking.

While at it, copy a comment from the old AR71xx driver to make it clear,
why do we need this OOB layout tweaking.

Run tested with MikroTik RB411U board.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a at gmail.com>
---

Changes since v1:
 * rebased on top of latest master
 * rephrased the comment in the hook function, thanks to Bas for
   noticing this

 .../files/drivers/mtd/nand/raw/nand_rb4xx.c   | 25 ++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb4xx.c b/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb4xx.c
index 22e2660b38..6778e70d34 100644
--- a/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb4xx.c
+++ b/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb4xx.c
@@ -81,6 +81,23 @@ static const struct mtd_ooblayout_ops rb4xx_nand_ecclayout_ops = {
 	.free = rb4xx_ooblayout_free,
 };
 
+static int rb4xx_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	/*
+	 * At this point, we know the flash params and can tweak the OOB layout
+	 * for 512-byte page (usually this is a 64MiB flash).
+	 *
+	 * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB
+	 * bootloader will not be able to find the kernel that we load.
+	 */
+	if (mtd->writesize == 512)
+		mtd_set_ooblayout(mtd, &rb4xx_nand_ecclayout_ops);
+
+	return 0;
+}
+
 static u8 rb4xx_nand_read_byte(struct nand_chip *chip)
 {
 	struct rb4xx_nand *nand = chip->priv;
@@ -135,6 +152,10 @@ static int rb4xx_nand_dev_ready(struct nand_chip *chip)
 	return gpiod_get_value_cansleep(nand->rdy);
 }
 
+static const struct nand_controller_ops rb4xx_nand_controller_ops = {
+	.attach_chip = rb4xx_nand_attach_chip,
+};
+
 static int rb4xx_nand_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -185,9 +206,6 @@ static int rb4xx_nand_probe(struct platform_device *pdev)
 	mtd->dev.parent	= dev;
 	mtd_set_of_node(mtd, dev->of_node);
 
-	if (mtd->writesize == 512)
-		mtd_set_ooblayout(mtd, &rb4xx_nand_ecclayout_ops);
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
 	nand->chip.ecc.engine_type	= NAND_ECC_ENGINE_TYPE_SOFT;
 	nand->chip.ecc.algo		= NAND_ECC_ALGO_HAMMING;
@@ -204,6 +222,7 @@ static int rb4xx_nand_probe(struct platform_device *pdev)
 	nand->chip.legacy.cmd_ctrl	= rb4xx_nand_cmd_ctrl;
 	nand->chip.legacy.dev_ready	= rb4xx_nand_dev_ready;
 	nand->chip.legacy.chip_delay	= 25;
+	nand->chip.legacy.dummy_controller.ops = &rb4xx_nand_controller_ops;
 
 	ret = nand_scan(&nand->chip, 1);
 	if (ret)
-- 
2.30.1




More information about the openwrt-devel mailing list