mtd: brcmnand: respect ECC algorithm set by NAND subsystem

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Mon May 23 21:59:25 PDT 2016


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=666b65683dad9aa90efaa4aad24ef3710101e3aa
Commit:     666b65683dad9aa90efaa4aad24ef3710101e3aa
Parent:     bd2e778c9ee361c23ccb2b10591712e129d97893
Author:     Brian Norris <computersforpeace at gmail.com>
AuthorDate: Mon Apr 25 22:53:55 2016 -0700
Committer:  Boris Brezillon <boris.brezillon at free-electrons.com>
CommitDate: Thu May 5 23:55:15 2016 +0200

    mtd: brcmnand: respect ECC algorithm set by NAND subsystem
    
    This is more obvious than guessing based on ECC strength. It allows
    using NAND on devices with BCH-1 (e.g. D-Link DIR-885L).
    
    This maintains DT backward compatibility by defaulting to Hamming if a
    1-bit ECC algorithm is specified without a corresponding algorithm
    selection. i.e., to use BCH-1, you must specify:
    
      nand-ecc-strength = <1>;
      nand-ecc-step-size = <512>;
      nand-ecc-algo = "bch";
    
    Also adds a check to ensure we haven't allowed someone to get by with SW
    ECC. If we want to support SW ECC, we need to refactor some other pieces
    of this driver.
    
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
    Tested-by: Rafał Miłecki <zajec5 at gmail.com>
    Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
---
 drivers/mtd/nand/brcmnand/brcmnand.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index c3331ff..b76ad7c 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -1925,9 +1925,31 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
 	cfg->col_adr_bytes = 2;
 	cfg->blk_adr_bytes = get_blk_adr_bytes(mtd->size, mtd->writesize);
 
+	if (chip->ecc.mode != NAND_ECC_HW) {
+		dev_err(ctrl->dev, "only HW ECC supported; selected: %d\n",
+			chip->ecc.mode);
+		return -EINVAL;
+	}
+
+	if (chip->ecc.algo == NAND_ECC_UNKNOWN) {
+		if (chip->ecc.strength == 1 && chip->ecc.size == 512)
+			/* Default to Hamming for 1-bit ECC, if unspecified */
+			chip->ecc.algo = NAND_ECC_HAMMING;
+		else
+			/* Otherwise, BCH */
+			chip->ecc.algo = NAND_ECC_BCH;
+	}
+
+	if (chip->ecc.algo == NAND_ECC_HAMMING && (chip->ecc.strength != 1 ||
+						   chip->ecc.size != 512)) {
+		dev_err(ctrl->dev, "invalid Hamming params: %d bits per %d bytes\n",
+			chip->ecc.strength, chip->ecc.size);
+		return -EINVAL;
+	}
+
 	switch (chip->ecc.size) {
 	case 512:
-		if (chip->ecc.strength == 1) /* Hamming */
+		if (chip->ecc.algo == NAND_ECC_HAMMING)
 			cfg->ecc_level = 15;
 		else
 			cfg->ecc_level = chip->ecc.strength;



More information about the linux-mtd-cvs mailing list