mtd: brcmnand: respect ECC algorithm set by NAND subsystem
authorBrian Norris <computersforpeace@gmail.com>
Tue, 26 Apr 2016 05:53:55 +0000 (22:53 -0700)
committerBoris Brezillon <boris.brezillon@free-electrons.com>
Thu, 5 May 2016 21:55:15 +0000 (23:55 +0200)
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@gmail.com>
Tested-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
drivers/mtd/nand/brcmnand/brcmnand.c

index c3331ffcaffd23cf529a446a90998c4c6c0c6592..b76ad7c0144f7501e7de328c8c0175690df3a039 100644 (file)
@@ -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;