Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934359AbbDVISU (ORCPT ); Wed, 22 Apr 2015 04:18:20 -0400 Received: from mail-wg0-f54.google.com ([74.125.82.54]:36089 "EHLO mail-wg0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934339AbbDVISO (ORCPT ); Wed, 22 Apr 2015 04:18:14 -0400 From: Tomas Hlavacek To: dwmw2@infradead.org Cc: computersforpeace@gmail.com, scottwood@freescale.com, linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RFC] mtd: fsl_elbc_nand Add ECC mode selection in DT Date: Wed, 22 Apr 2015 10:18:10 +0200 Message-Id: <1429690690-15057-1-git-send-email-tmshlvck@gmail.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4090 Lines: 112 Add device tree parameters to turn off the HW ECC and force own ECC mode and ECC parameters. New entries are: nand-ecc-mode, nand-ecc-step-size and nand-ecc-strength. Add RNDOUT operation which is required for SOFT and SOFT_BCH modes. Do not set write_subpage function pointer from the driver when it initializes in SOFT and SOFT_BCH modes. Signed-off-by: Tomas Hlavacek --- drivers/mtd/nand/fsl_elbc_nand.c | 47 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 04b22fd..76ab2e2 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -335,6 +335,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, fsl_elbc_run_command(mtd); return; + case NAND_CMD_RNDOUT: + dev_vdbg(priv->dev, + "fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n", + column); + + elbc_fcm_ctrl->index = column; + return; + /* READOOB reads only the OOB because no ECC is performed. */ case NAND_CMD_READOOB: dev_vdbg(priv->dev, @@ -656,6 +664,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) chip->ecc.steps); dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", chip->ecc.bytes); + dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.size = %d\n", + chip->ecc.size); + dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.strength = %d\n", + chip->ecc.strength); dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", chip->ecc.total); dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", @@ -677,8 +689,8 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) priv->page_size = 1; setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); /* adjust ecc setup if needed */ - if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == - BR_DECC_CHK_GEN) { + if (((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == + BR_DECC_CHK_GEN) && (chip->ecc.mode == NAND_ECC_HW)) { chip->ecc.size = 512; chip->ecc.layout = (priv->fmr & FMR_ECCM) ? &fsl_elbc_oob_lp_eccm1 : @@ -742,6 +754,8 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) struct fsl_lbc_regs __iomem *lbc = ctrl->regs; struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; struct nand_chip *chip = &priv->chip; + struct device_node *node = priv->dev->of_node; + const char *ecc_mode; dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); @@ -774,11 +788,38 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->ecc.read_page = fsl_elbc_read_page; chip->ecc.write_page = fsl_elbc_write_page; - chip->ecc.write_subpage = fsl_elbc_write_subpage; + + /* Override default HW ECC according to settings in DT */ + if (!of_property_read_string(node, "nand-ecc-mode", &ecc_mode)) { + if (!strncmp("none", ecc_mode, 4)) { + chip->ecc.mode = NAND_ECC_NONE; + return 0; + } + + if (!strncmp("soft_bch", ecc_mode, 8)) { + chip->ecc.mode = NAND_ECC_SOFT_BCH; + chip->ecc.size = 512; + chip->ecc.strength = 4; + + of_property_read_u32(node, "nand-ecc-step-size", + &chip->ecc.size); + of_property_read_u32(node, "nand-ecc-strength", + &chip->ecc.strength); + chip->ecc.bytes = ((fls(1+8*chip->ecc.size)* + chip->ecc.strength)/8); + return 0; + } + + if (!strncmp("soft", ecc_mode, 4)) { + chip->ecc.mode = NAND_ECC_SOFT; + return 0; + } + } /* If CS Base Register selects full hardware ECC then use it */ if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == BR_DECC_CHK_GEN) { + chip->ecc.write_subpage = fsl_elbc_write_subpage; chip->ecc.mode = NAND_ECC_HW; /* put in small page settings and adjust later if needed */ chip->ecc.layout = (priv->fmr & FMR_ECCM) ? -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/