From eff78bc2c385f592294278582f38ad5fa4ed2b34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Wed, 27 Jan 2016 08:47:03 +0100
Subject: [PATCH] mtd: brcmnand: set initial ECC params based on info from HW
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

So far we were depending on nand_dt_init getting ECC info from DT and
setting it in ECC struct. It is possible to simply read this info from
hardware registers which makes adding support for new hardware way
easier (no more guessing & trying all combinations).
Please note it still gives a precedence to DT which was overwrite
whatever was initially set by the driver.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
It took me hours to figure out how to setup NAND on my D-Link DIR-885L.
This should be very helpful for ppl adding new devices support.
---
 drivers/mtd/nand/brcmnand/brcmnand.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -645,6 +645,17 @@ static inline u32 brcmnand_ecc_level_mas
 	return mask << NAND_ACC_CONTROL_ECC_SHIFT;
 }
 
+static int brcmnand_get_ecc_strength(struct brcmnand_host *host)
+{
+	struct brcmnand_controller *ctrl = host->ctrl;
+	u32 mask = brcmnand_ecc_level_mask(ctrl);
+	u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs,
+						  BRCMNAND_CS_ACC_CONTROL);
+
+	return (nand_readreg(ctrl, acc_control_offs) & mask) >>
+		NAND_ACC_CONTROL_ECC_SHIFT;
+}
+
 static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
 {
 	struct brcmnand_controller *ctrl = host->ctrl;
@@ -1997,6 +2008,9 @@ static int brcmnand_init_cs(struct brcmn
 	nand_writereg(ctrl, cfg_offs,
 		      nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH);
 
+	chip->ecc.strength = brcmnand_get_ecc_strength(host);
+	chip->ecc.size = brcmnand_get_sector_size_1k(host) ? 1024 : 512;
+
 	if (nand_scan_ident(mtd, 1, NULL))
 		return -ENXIO;
 
