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

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
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment