Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8831e48b authored by Miquel Raynal's avatar Miquel Raynal
Browse files

mtd: rawnand: marvell: convert driver to nand_scan()



Two helpers have been added to the core to do all kind of controller
side configuration/initialization between the detection phase and the
final NAND scan. Implement these hooks so that we can convert the driver
to just use nand_scan() instead of the nand_scan_ident() +
nand_scan_tail() pair.

Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: default avatarBoris Brezillon <boris.brezillon@bootlin.com>
parent f4a48d7b
Loading
Loading
Loading
Loading
+108 −97
Original line number Diff line number Diff line
@@ -2290,6 +2290,111 @@ static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr,
	return 0;
}

static int marvell_nand_attach_chip(struct nand_chip *chip)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(nfc->dev);
	int ret;

	if (pdata && pdata->flash_bbt)
		chip->bbt_options |= NAND_BBT_USE_FLASH;

	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
		/*
		 * We'll use a bad block table stored in-flash and don't
		 * allow writing the bad block marker to the flash.
		 */
		chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
		chip->bbt_td = &bbt_main_descr;
		chip->bbt_md = &bbt_mirror_descr;
	}

	/* Save the chip-specific fields of NDCR */
	marvell_nand->ndcr = NDCR_PAGE_SZ(mtd->writesize);
	if (chip->options & NAND_BUSWIDTH_16)
		marvell_nand->ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;

	/*
	 * On small page NANDs, only one cycle is needed to pass the
	 * column address.
	 */
	if (mtd->writesize <= 512) {
		marvell_nand->addr_cyc = 1;
	} else {
		marvell_nand->addr_cyc = 2;
		marvell_nand->ndcr |= NDCR_RA_START;
	}

	/*
	 * Now add the number of cycles needed to pass the row
	 * address.
	 *
	 * Addressing a chip using CS 2 or 3 should also need the third row
	 * cycle but due to inconsistance in the documentation and lack of
	 * hardware to test this situation, this case is not supported.
	 */
	if (chip->options & NAND_ROW_ADDR_3)
		marvell_nand->addr_cyc += 3;
	else
		marvell_nand->addr_cyc += 2;

	if (pdata) {
		chip->ecc.size = pdata->ecc_step_size;
		chip->ecc.strength = pdata->ecc_strength;
	}

	ret = marvell_nand_ecc_init(mtd, &chip->ecc);
	if (ret) {
		dev_err(nfc->dev, "ECC init failed: %d\n", ret);
		return ret;
	}

	if (chip->ecc.mode == NAND_ECC_HW) {
		/*
		 * Subpage write not available with hardware ECC, prohibit also
		 * subpage read as in userspace subpage access would still be
		 * allowed and subpage write, if used, would lead to numerous
		 * uncorrectable ECC errors.
		 */
		chip->options |= NAND_NO_SUBPAGE_WRITE;
	}

	if (pdata || nfc->caps->legacy_of_bindings) {
		/*
		 * We keep the MTD name unchanged to avoid breaking platforms
		 * where the MTD cmdline parser is used and the bootloader
		 * has not been updated to use the new naming scheme.
		 */
		mtd->name = "pxa3xx_nand-0";
	} else if (!mtd->name) {
		/*
		 * If the new bindings are used and the bootloader has not been
		 * updated to pass a new mtdparts parameter on the cmdline, you
		 * should define the following property in your NAND node, ie:
		 *
		 *	label = "main-storage";
		 *
		 * This way, mtd->name will be set by the core when
		 * nand_set_flash_node() is called.
		 */
		mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
					   "%s:nand.%d", dev_name(nfc->dev),
					   marvell_nand->sels[0].cs);
		if (!mtd->name) {
			dev_err(nfc->dev, "Failed to allocate mtd->name\n");
			return -ENOMEM;
		}
	}

	return 0;
}

static const struct nand_controller_ops marvell_nand_controller_ops = {
	.attach_chip = marvell_nand_attach_chip,
};

static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
				  struct device_node *np)
{
@@ -2432,105 +2537,10 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
	marvell_nand->ndtr1 = readl_relaxed(nfc->regs + NDTR1);

	chip->options |= NAND_BUSWIDTH_AUTO;
	ret = nand_scan_ident(mtd, marvell_nand->nsels, NULL);
	if (ret) {
		dev_err(dev, "could not identify the nand chip\n");
		return ret;
	}

	if (pdata && pdata->flash_bbt)
		chip->bbt_options |= NAND_BBT_USE_FLASH;

	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
		/*
		 * We'll use a bad block table stored in-flash and don't
		 * allow writing the bad block marker to the flash.
		 */
		chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
		chip->bbt_td = &bbt_main_descr;
		chip->bbt_md = &bbt_mirror_descr;
	}

	/* Save the chip-specific fields of NDCR */
	marvell_nand->ndcr = NDCR_PAGE_SZ(mtd->writesize);
	if (chip->options & NAND_BUSWIDTH_16)
		marvell_nand->ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;

	/*
	 * On small page NANDs, only one cycle is needed to pass the
	 * column address.
	 */
	if (mtd->writesize <= 512) {
		marvell_nand->addr_cyc = 1;
	} else {
		marvell_nand->addr_cyc = 2;
		marvell_nand->ndcr |= NDCR_RA_START;
	}

	/*
	 * Now add the number of cycles needed to pass the row
	 * address.
	 *
	 * Addressing a chip using CS 2 or 3 should also need the third row
	 * cycle but due to inconsistance in the documentation and lack of
	 * hardware to test this situation, this case is not supported.
	 */
	if (chip->options & NAND_ROW_ADDR_3)
		marvell_nand->addr_cyc += 3;
	else
		marvell_nand->addr_cyc += 2;

	if (pdata) {
		chip->ecc.size = pdata->ecc_step_size;
		chip->ecc.strength = pdata->ecc_strength;
	}

	ret = marvell_nand_ecc_init(mtd, &chip->ecc);
	if (ret) {
		dev_err(dev, "ECC init failed: %d\n", ret);
		return ret;
	}

	if (chip->ecc.mode == NAND_ECC_HW) {
		/*
		 * Subpage write not available with hardware ECC, prohibit also
		 * subpage read as in userspace subpage access would still be
		 * allowed and subpage write, if used, would lead to numerous
		 * uncorrectable ECC errors.
		 */
		chip->options |= NAND_NO_SUBPAGE_WRITE;
	}

	if (pdata || nfc->caps->legacy_of_bindings) {
		/*
		 * We keep the MTD name unchanged to avoid breaking platforms
		 * where the MTD cmdline parser is used and the bootloader
		 * has not been updated to use the new naming scheme.
		 */
		mtd->name = "pxa3xx_nand-0";
	} else if (!mtd->name) {
		/*
		 * If the new bindings are used and the bootloader has not been
		 * updated to pass a new mtdparts parameter on the cmdline, you
		 * should define the following property in your NAND node, ie:
		 *
		 *	label = "main-storage";
		 *
		 * This way, mtd->name will be set by the core when
		 * nand_set_flash_node() is called.
		 */
		mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
					   "%s:nand.%d", dev_name(nfc->dev),
					   marvell_nand->sels[0].cs);
		if (!mtd->name) {
			dev_err(nfc->dev, "Failed to allocate mtd->name\n");
			return -ENOMEM;
		}
	}

	ret = nand_scan_tail(mtd);
	ret = nand_scan(mtd, marvell_nand->nsels);
	if (ret) {
		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
		dev_err(dev, "could not scan the nand chip\n");
		return ret;
	}

@@ -2746,6 +2756,7 @@ static int marvell_nfc_probe(struct platform_device *pdev)

	nfc->dev = dev;
	nand_controller_init(&nfc->controller);
	nfc->controller.ops = &marvell_nand_controller_ops;
	INIT_LIST_HEAD(&nfc->chips);

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);