summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>2015-11-20 20:36:09 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-11-23 08:17:25 +0100
commit87bddaf82e42d97771eb2716c3e8e0d4957a2708 (patch)
treeac4ae5880d4b971bf0191100244622d65ac08afc
parentf7d39e122e5dc6c119f0f9576f96ff546ac5aa6c (diff)
downloadbarebox-87bddaf82e42d97771eb2716c3e8e0d4957a2708.tar.gz
barebox-87bddaf82e42d97771eb2716c3e8e0d4957a2708.tar.xz
mtd: nand_mrvl_nfc: Add support for HW BCH ECC
Add support for HW BCH ECC for those HW versions that support it. Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/mtd/nand/nand_mrvl_nfc.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/mtd/nand/nand_mrvl_nfc.c b/drivers/mtd/nand/nand_mrvl_nfc.c
index b1ebecb3b5..f97c005bd0 100644
--- a/drivers/mtd/nand/nand_mrvl_nfc.c
+++ b/drivers/mtd/nand/nand_mrvl_nfc.c
@@ -92,6 +92,8 @@
#define NDSR_RDDREQ (0x1 << 1)
#define NDSR_WRCMDREQ (0x1)
+#define NDECCCTRL_BCH_EN BIT(0)
+
#define NDCB0_LEN_OVRD (0x1 << 28)
#define NDCB0_ST_ROW_EN (0x1 << 26)
#define NDCB0_AUTO_RS (0x1 << 25)
@@ -426,6 +428,17 @@ static void mrvl_nand_start(struct mrvl_nand_host *host)
{
uint32_t ndcr;
+ if (host->hwflags & HWFLAGS_ECC_BCH) {
+ uint32_t reg = nand_readl(host, NDECCCTRL);
+
+ if (host->use_ecc && host->ecc_bch)
+ reg |= NDECCCTRL_BCH_EN;
+ else
+ reg &= ~NDECCCTRL_BCH_EN;
+
+ nand_writel(host, NDECCCTRL, reg);
+ }
+
ndcr = host->reg_ndcr;
if (host->use_ecc)
ndcr |= NDCR_ECC_EN;
@@ -794,8 +807,14 @@ static int mrvl_nand_read_page_hwecc(struct mtd_info *mtd,
else
ret = -EBADMSG;
}
- if (ndsr & NDSR_CORERR)
+ if (ndsr & NDSR_CORERR) {
ret = 1;
+ if ((host->hwflags & HWFLAGS_ECC_BCH) && host->ecc_bch) {
+ ret = NDSR_ERR_CNT(ndsr);
+ ndsr &= ~(NDSR_ERR_CNT_MASK << NDSR_ERR_CNT_OFF);
+ nand_writel(host, NDSR, ndsr);
+ }
+ }
dev_dbg(host->dev, "%s(buf=%p, page=%d, oob_required=%d) => %d\n",
__func__, buf, page, oob_required, ret);
return ret;
@@ -1011,6 +1030,11 @@ static int mrvl_nand_scan(struct mtd_info *mtd)
ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
host->reg_ndcr = ndcr;
+ /* Device detection must be done with BCH ECC disabled */
+ if (host->hwflags & HWFLAGS_ECC_BCH)
+ nand_writel(host, NDECCCTRL,
+ nand_readl(host, NDECCCTRL) & ~NDECCCTRL_BCH_EN);
+
mrvl_nand_set_timing(host, true);
if (nand_scan_ident(mtd, 1, NULL)) {
host->reg_ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;