public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] mtd: rawnand: gpmi: Refactor bch geometry settings function
@ 2022-03-25 21:14 Han Xu
  2022-03-25 21:14 ` [PATCH v2 2/2] mtd: rawnand: gpmi: Add large oob bch setting support Han Xu
  2022-03-28  9:17 ` [PATCH v2 1/2] mtd: rawnand: gpmi: Refactor bch geometry settings function Miquel Raynal
  0 siblings, 2 replies; 4+ messages in thread
From: Han Xu @ 2022-03-25 21:14 UTC (permalink / raw)
  To: sbabic, sean, frieder.schrempf, festevam
  Cc: ye.li, peng.fan, han.xu, miquel.raynal, linux-mtd

The code change refactor the bch geometry setting function, which still
use the legacy bch setting as default option, while user may choose to
use chips required minimum ecc strength by DT flag "fsl,use-minimum-ecc".
It also improve the gpmi_check_ecc function to check if the selected ecc
strength is strong enough.

The driver uses legacy bch geometry settings by default, if the NAND
chips oob size is less than 1KB. The legacy_set_geometry() sets the data
chunk size(step_size) larger than oob size to make sure BBM locates in
data chunk, then set the maximum ecc stength oob can hold. It always use
unbalanced ECC layout, which ecc0 will cover both meta and data0 chunk.

For all other cases,set the bch geometry by chip required strength and
step size, which uses the minimum ecc strength chip required. It can be
explicitly enabled by DT flag "fsl,use-minimum-ecc", but need to be
en/disabled in both u-boot and kernel at the same time.

Signed-off-by: Han Xu <han.xu@nxp.com>
Tested-by: Sean Nyekjaer <sean@geanix.com>

---
Changes in v2
 - split the patch to two parts
 - change the commit log
 - add test tag
---
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 56 ++++++++++++++++------
 1 file changed, 42 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index d96899fa90b7..9a37f8cc663e 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -238,9 +238,14 @@ static void gpmi_dump_info(struct gpmi_nand_data *this)
 		geo->block_mark_bit_offset);
 }
 
-static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
+static bool gpmi_check_ecc(struct gpmi_nand_data *this)
 {
+	struct nand_chip *chip = &this->nand;
+	struct mtd_info *mtd = nand_to_mtd(&this->nand);
 	struct bch_geometry *geo = &this->bch_geometry;
+	const struct nand_ecc_props *requirements =
+		nanddev_get_ecc_requirements(&chip->base);
+	int corr, ds_corr;
 
 	/* Do the sanity check. */
 	if (GPMI_IS_MXS(this)) {
@@ -248,7 +253,22 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
 		if (geo->gf_len == 14)
 			return false;
 	}
-	return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
+
+	if (geo->ecc_strength > this->devdata->bch_max_ecc_strength)
+		return false;
+
+	/* check ecc strength, same as nand_ecc_is_strong_enough() did */
+	if (requirements->step_size) {
+		corr = mtd->writesize * geo->ecc_strength /
+		       geo->ecc_chunk_size;
+		ds_corr = mtd->writesize * requirements->strength /
+			  requirements->step_size;
+		if (corr < ds_corr ||
+		    geo->ecc_strength < requirements->strength)
+			return false;
+	}
+
+	return true;
 }
 
 /*
@@ -514,24 +534,32 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
 static int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
 	struct nand_chip *chip = &this->nand;
+	struct mtd_info *mtd = nand_to_mtd(&this->nand);
 	const struct nand_ecc_props *requirements =
 		nanddev_get_ecc_requirements(&chip->base);
+	bool use_minimun_ecc;
+	int err;
 
-	if (chip->ecc.strength > 0 && chip->ecc.size > 0)
-		return set_geometry_by_ecc_info(this, chip->ecc.strength,
-						chip->ecc.size);
-
-	if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
-				|| legacy_set_geometry(this)) {
-		if (!(requirements->strength > 0 && requirements->step_size > 0))
-			return -EINVAL;
+	use_minimun_ecc = of_property_read_bool(this->dev->of_node,
+						"fsl,use-minimum-ecc");
 
-		return set_geometry_by_ecc_info(this,
-						requirements->strength,
-						requirements->step_size);
+	/* use legacy bch geometry settings by default*/
+	if ((!use_minimun_ecc && mtd->oobsize < 1024) ||
+	    !(requirements->strength > 0 && requirements->step_size > 0)) {
+		dev_dbg(this->dev, "use legacy bch geometry\n");
+		err = legacy_set_geometry(this);
+		if (!err)
+			return 0;
 	}
 
-	return 0;
+	/* otherwise use the minimum ecc nand chip required */
+	dev_dbg(this->dev, "use minimum ecc bch geometry\n");
+	err = set_geometry_by_ecc_info(this, requirements->strength,
+					requirements->step_size);
+	if (err)
+		dev_err(this->dev, "none of the bch geometry setting works\n");
+
+	return err;
 }
 
 /* Configures the geometry for BCH.  */
-- 
2.17.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

end of thread, other threads:[~2022-03-28  9:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-25 21:14 [PATCH v2 1/2] mtd: rawnand: gpmi: Refactor bch geometry settings function Han Xu
2022-03-25 21:14 ` [PATCH v2 2/2] mtd: rawnand: gpmi: Add large oob bch setting support Han Xu
2022-03-28  9:10   ` Miquel Raynal
2022-03-28  9:17 ` [PATCH v2 1/2] mtd: rawnand: gpmi: Refactor bch geometry settings function Miquel Raynal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox