public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [RESEND PATCH v2 27/53] mtd: nand: denali: avoid hard-coding ecc.strength and ecc.bytes
@ 2017-03-23  0:17 Masahiro Yamada
  2017-03-23  0:17 ` [RESEND PATCH v2 28/53] mtd: nand: denali: support "nand-ecc-strength" DT property Masahiro Yamada
                   ` (25 more replies)
  0 siblings, 26 replies; 41+ messages in thread
From: Masahiro Yamada @ 2017-03-23  0:17 UTC (permalink / raw)
  To: linux-mtd
  Cc: Boris Brezillon, David Woodhouse, Marek Vasut, Brian Norris,
	thorsten.christiansson, laurent.monat, Dinh Nguyen,
	Artem Bityutskiy, Graham Moore, Enrico Jorns, Chuanxiao Dong,
	Masami Hiramatsu, Jassi Brar, Rob Herring, Masahiro Yamada

Another problem of this driver is hard-coded ecc.strength and
ecc.bytes.  Currently ecc.bytes is defined as follows:

  #define ECC_8BITS	14
  #define ECC_15BITS	26

The parameters were hard-coded because only the following two cases
are possible on Intel platforms:

 - ecc.size = 512, ecc.strength = 8    --> ecc.bytes = 14
 - ecc.size = 512, ecc.strength = 15   --> ecc.bytes = 26

However, they are actually customizable parameters, for example,
UniPhier platform supports the following:

 - ecc.size = 1024, ecc.strength = 8   --> ecc.bytes = 14
 - ecc.size = 1024, ecc.strength = 16  --> ecc.bytes = 28
 - ecc.size = 1024, ecc.strength = 24  --> ecc.bytes = 42

So, we need to handle these parameters in a more generic manner.
Fortunately, the Denali User's Guide explains how to calculate the
ecc.bytes.  The formula is:

  ecc.bytes = 2 * CEIL(13 * ecc.strength / 16)  (for ecc.size = 512)
  ecc.bytes = 2 * CEIL(14 * ecc.strength / 16)  (for ecc.size = 1024)

This commit allows platforms to specify denali->ecc_strength_avail,
each bit of which represents supported ECC strength.  I am not using
the bitmap here because "unsigned long" should be enough to cover
the ECC strength of this IP.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v2: None

 drivers/mtd/nand/denali.c     | 73 +++++++++++++++++++++++++++----------------
 drivers/mtd/nand/denali.h     |  1 +
 drivers/mtd/nand/denali_dt.c  |  3 ++
 drivers/mtd/nand/denali_pci.c |  1 +
 4 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index cf8daba..96074b8 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1340,13 +1340,45 @@ static void denali_hw_init(struct denali_nand_info *denali)
 	denali_irq_init(denali);
 }
 
-/*
- * Althogh controller spec said SLC ECC is forceb to be 4bit,
- * but denali controller in MRST only support 15bit and 8bit ECC
- * correction
- */
-#define ECC_8BITS	14
-#define ECC_15BITS	26
+static int denali_calc_ecc_bytes(int ecc_size, int ecc_strength)
+{
+	WARN_ON(ecc_size != 512 && ecc_size != 1024);
+
+	return DIV_ROUND_UP(ecc_strength * (ecc_size == 512 ? 13 : 14), 16) * 2;
+}
+
+static int denali_set_max_ecc_strength(struct denali_nand_info *denali)
+{
+	struct nand_chip *chip = &denali->nand;
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int oobsize = mtd->oobsize;
+	int ecc_size = chip->ecc.size;
+	int ecc_steps = mtd->writesize / chip->ecc.size;
+	int ecc_strength, ecc_bytes;
+	int max_strength = 0;
+
+	/* carve out the BBM area */
+	oobsize -= denali->bbtskipbytes;
+
+	for_each_set_bit(ecc_strength, &denali->ecc_strength_avail,
+			 sizeof(denali->ecc_strength_avail) * BITS_PER_BYTE) {
+		ecc_bytes = denali_calc_ecc_bytes(ecc_size, ecc_strength);
+		if (ecc_bytes * ecc_steps > oobsize)
+			break;
+
+		max_strength = ecc_strength;
+	}
+
+	if (!max_strength) {
+		dev_err(denali->dev,
+			"Your NAND chip OOB is too small. No available ECC strength.\n");
+		return -EINVAL;
+	}
+
+	chip->ecc.strength = max_strength;
+
+	return 0;
+}
 
 static int denali_ooblayout_ecc(struct mtd_info *mtd, int section,
 				struct mtd_oob_region *oobregion)
@@ -1595,27 +1627,14 @@ int denali_init(struct denali_nand_info *denali)
 		goto failed_req_irq;
 	}
 
-	/*
-	 * Denali Controller only support 15bit and 8bit ECC in MRST,
-	 * so just let controller do 15bit ECC for MLC and 8bit ECC for
-	 * SLC if possible.
-	 * */
-	if (!nand_is_slc(chip) &&
-			mtd->oobsize > denali->bbtskipbytes +
-			ECC_15BITS * (mtd->writesize / chip->ecc.size)) {
-		/* if MLC OOB size is large enough, use 15bit ECC*/
-		chip->ecc.strength = 15;
-		chip->ecc.bytes = ECC_15BITS;
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-	} else if (mtd->oobsize <
-		   denali->bbtskipbytes + ECC_8BITS * (mtd->writesize / chip->ecc.size)) {
-		pr_err("Your NAND chip OOB is not large enough to contain 8bit ECC correction codes");
+	ret = denali_set_max_ecc_strength(denali);
+	if (ret)
 		goto failed_req_irq;
-	} else {
-		chip->ecc.strength = 8;
-		chip->ecc.bytes = ECC_8BITS;
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-	}
+
+	chip->ecc.bytes = denali_calc_ecc_bytes(chip->ecc.size,
+						chip->ecc.strength);
+
+	iowrite32(chip->ecc.strength, denali->flash_reg + ECC_CORRECTION);
 
 	iowrite32(chip->ecc.size, denali->flash_reg + CFG_DATA_BLOCK_SIZE);
 	iowrite32(chip->ecc.size, denali->flash_reg + CFG_LAST_DATA_BLOCK_SIZE);
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index aa6548a..003d234a 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -353,6 +353,7 @@ struct denali_nand_info {
 	int bbtskipbytes;
 	int max_banks;
 	unsigned int revision;
+	unsigned long ecc_strength_avail;
 	unsigned int caps;
 #define DENALI_CAP_HW_ECC_FIXUP			BIT(0)
 #define DENALI_CAP_DMA_64BIT			BIT(1)
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c
index 1681a30..c3bc333 100644
--- a/drivers/mtd/nand/denali_dt.c
+++ b/drivers/mtd/nand/denali_dt.c
@@ -31,10 +31,12 @@ struct denali_dt {
 
 struct denali_dt_data {
 	unsigned int revision;
+	unsigned long ecc_strength_avail;
 	unsigned int caps;
 };
 
 static const struct denali_dt_data denali_socfpga_data = {
+	.ecc_strength_avail = BIT(15) | BIT(8),
 	.caps = DENALI_CAP_HW_ECC_FIXUP |
 		DENALI_CAP_ECC_SIZE_512,
 };
@@ -64,6 +66,7 @@ static int denali_dt_probe(struct platform_device *pdev)
 	data = of_device_get_match_data(&pdev->dev);
 	if (data) {
 		denali->revision = data->revision;
+		denali->ecc_strength_avail = data->ecc_strength_avail;
 		denali->caps = data->caps;
 	}
 
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
index 5202a11..a1ee9f8 100644
--- a/drivers/mtd/nand/denali_pci.c
+++ b/drivers/mtd/nand/denali_pci.c
@@ -85,6 +85,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_remap_reg;
 	}
 
+	denali->ecc_strength_avail = BIT(15) | BIT(8);
 	denali->caps |= DENALI_CAP_ECC_SIZE_512;
 
 	ret = denali_init(denali);
-- 
2.7.4

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

end of thread, other threads:[~2017-03-29  7:04 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-23  0:17 [RESEND PATCH v2 27/53] mtd: nand: denali: avoid hard-coding ecc.strength and ecc.bytes Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 28/53] mtd: nand: denali: support "nand-ecc-strength" DT property Masahiro Yamada
2017-03-23  8:43   ` Boris Brezillon
2017-03-23  0:17 ` [RESEND PATCH v2 29/53] mtd: nand: denali: remove Toshiba and Hynix specific fixup code Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 30/53] mtd: nand: denali_dt: add compatible strings for UniPhier SoC variants Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 31/53] mtd: nand: denali: set NAND_ECC_CUSTOM_PAGE_ACCESS Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 32/53] mtd: nand: denali: do not propagate NAND_STATUS_FAIL to waitfunc() Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 33/53] mtd: nand: denali: use BIT() and GENMASK() for register macros Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 34/53] mtd: nand: denali: remove unneeded find_valid_banks() Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 35/53] mtd: nand: denali: handle timing parameters by setup_data_interface() Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 36/53] mtd: nand: denali: remove meaningless pipeline read-ahead operation Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 37/53] mtd: nand: denali: rework interrupt handling Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 38/53] mtd: nand: denali: fix NAND_CMD_STATUS handling Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 39/53] mtd: nand: denali: fix NAND_CMD_PARAM handling Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 40/53] mtd: nand: do not check R/B# for CMD_READID in nand_command(_lp) Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 41/53] mtd: nand: do not check R/B# for CMD_SET_FEATURES " Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 42/53] mtd: nand: denali: switch over to cmd_ctrl instead of cmdfunc Masahiro Yamada
2017-03-23  8:52   ` Boris Brezillon
2017-03-23  0:17 ` [RESEND PATCH v2 43/53] mtd: nand: denali: fix bank reset function Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 44/53] mtd: nand: denali: use interrupt instead of polling for bank reset Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 45/53] mtd: nand: denali: propagate page to helpers via function argument Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 46/53] mtd: nand: denali: merge struct nand_buf into struct denali_nand_info Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 47/53] mtd: nand: denali: use flag instead of register macro for direction Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 48/53] mtd: nand: denali: fix raw and oob accessors for syndrome page layout Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 49/53] mtd: nand: denali: support hardware-assisted erased page detection Masahiro Yamada
2017-03-23  0:17 ` [RESEND PATCH v2 50/53] mtd: nand: allocate aligned buffers if NAND_OWN_BUFFERS is unset Masahiro Yamada
2017-03-27  8:00   ` Boris Brezillon
2017-03-28  1:13     ` yamada.masahiro
2017-03-28  7:59       ` Boris Brezillon
2017-03-28  8:07         ` Boris Brezillon
2017-03-28 10:22           ` Russell King - ARM Linux
2017-03-28 10:17         ` Russell King - ARM Linux
2017-03-28 12:13           ` Boris Brezillon
2017-03-29  3:22         ` yamada.masahiro
2017-03-29  7:03           ` Boris Brezillon
2017-03-23  0:18 ` [RESEND PATCH v2 51/53] mtd: nand: denali: skip driver internal bounce buffer when possible Masahiro Yamada
2017-03-23  0:18 ` [RESEND PATCH v2 52/53] mtd: nand: denali: use non-managed kmalloc() for DMA buffer Masahiro Yamada
2017-03-23 11:33   ` Robin Murphy
2017-03-24  1:41     ` yamada.masahiro
2017-03-24 17:09       ` Robin Murphy
2017-03-23  0:18 ` [RESEND PATCH v2 53/53] mtd: nand: denali: enable bad block table scan Masahiro Yamada

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