Commit f6424c22 authored by Marek Behún's avatar Marek Behún Committed by Miquel Raynal
Browse files

mtd: rawnand: fsl_elbc: Make SW ECC work



Move the code that choses ECC into _attach_chip, which is executed only
after the chip->ecc.* properties were loaded from device-tree. This way
we know which ECC method was chosen by the device-tree and can set
methods appropriately.

The chip->ecc.*page methods should be set to fsl_elbc_*page only in HW
ECC mode.

Signed-off-by: default avatarMarek Behún <marek.behun@nic.cz>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parent 070fb974
Loading
Loading
Loading
Loading
+34 −18
Original line number Diff line number Diff line
@@ -730,13 +730,30 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
	chip->controller = &elbc_fcm_ctrl->controller;
	nand_set_controller_data(chip, 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;
	return 0;
}

static int fsl_elbc_attach_chip(struct nand_chip *chip)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
	unsigned int al;

	switch (chip->ecc.mode) {
	/*
	 * if ECC was not chosen in DT, decide whether to use HW or SW ECC from
	 * CS Base Register
	 */
	case NAND_ECC_NONE:
		/* 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.read_page = fsl_elbc_read_page;
			chip->ecc.write_page = fsl_elbc_write_page;
			chip->ecc.write_subpage = fsl_elbc_write_subpage;

			chip->ecc.mode = NAND_ECC_HW;
			mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
			chip->ecc.size = 512;
@@ -747,17 +764,16 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
			chip->ecc.mode = NAND_ECC_SOFT;
			chip->ecc.algo = NAND_ECC_HAMMING;
		}
		break;

	return 0;
}
	/* if SW ECC was chosen in DT, we do not need to set anything here */
	case NAND_ECC_SOFT:
		break;

static int fsl_elbc_attach_chip(struct nand_chip *chip)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
	unsigned int al;
	/* should we also implement NAND_ECC_HW to do as the code above? */
	default:
		return -EINVAL;
	}

	/* calculate FMR Address Length field */
	al = 0;