lkml.org 
[lkml]   [2018]   [Jul]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH v4 03/35] mtd: rawnand: davinci: convert driver to nand_scan()
On Fri, 20 Jul 2018 17:14:55 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
>
> Also change the unused "struct device *dev" parameter of the driver
> structure into a platform device to reuse it in the ->attach_chip()
> hook.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/nand/raw/davinci_nand.c | 195 +++++++++++++++++++-----------------
> 1 file changed, 102 insertions(+), 93 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
> index 626c9363e460..40145e206a6b 100644
> --- a/drivers/mtd/nand/raw/davinci_nand.c
> +++ b/drivers/mtd/nand/raw/davinci_nand.c
> @@ -53,7 +53,7 @@
> struct davinci_nand_info {
> struct nand_chip chip;
>
> - struct device *dev;
> + struct platform_device *pdev;

For the record, there's a to_platform_device() macro you can use to get
a platform_device object from a device one, so this change was not
really needed. Actually, you should not even need a ->dev field here
because it can be retrieved from mtd->dev.parent. Anyway, if you
patched all places using davinci->dev to now use &davinci->pdev->dev
we should be good.

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

>
> bool is_readmode;
>
> @@ -605,6 +605,104 @@ static struct davinci_nand_pdata
> }
> #endif
>
> +static int davinci_nand_attach_chip(struct nand_chip *chip)
> +{
> + struct mtd_info *mtd = nand_to_mtd(chip);
> + struct davinci_nand_info *info = to_davinci_nand(mtd);
> + struct davinci_nand_pdata *pdata = nand_davinci_get_pdata(info->pdev);
> + int ret = 0;
> +
> + if (IS_ERR(pdata))
> + return PTR_ERR(pdata);
> +
> + switch (info->chip.ecc.mode) {
> + case NAND_ECC_NONE:
> + pdata->ecc_bits = 0;
> + break;
> + case NAND_ECC_SOFT:
> + pdata->ecc_bits = 0;
> + /*
> + * This driver expects Hamming based ECC when ecc_mode is set
> + * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
> + * avoid adding an extra ->ecc_algo field to
> + * davinci_nand_pdata.
> + */
> + info->chip.ecc.algo = NAND_ECC_HAMMING;
> + break;
> + case NAND_ECC_HW:
> + if (pdata->ecc_bits == 4) {
> + /*
> + * No sanity checks: CPUs must support this,
> + * and the chips may not use NAND_BUSWIDTH_16.
> + */
> +
> + /* No sharing 4-bit hardware between chipselects yet */
> + spin_lock_irq(&davinci_nand_lock);
> + if (ecc4_busy)
> + ret = -EBUSY;
> + else
> + ecc4_busy = true;
> + spin_unlock_irq(&davinci_nand_lock);
> +
> + if (ret == -EBUSY)
> + return ret;
> +
> + info->chip.ecc.calculate = nand_davinci_calculate_4bit;
> + info->chip.ecc.correct = nand_davinci_correct_4bit;
> + info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
> + info->chip.ecc.bytes = 10;
> + info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
> + info->chip.ecc.algo = NAND_ECC_BCH;
> + } else {
> + /* 1bit ecc hamming */
> + info->chip.ecc.calculate = nand_davinci_calculate_1bit;
> + info->chip.ecc.correct = nand_davinci_correct_1bit;
> + info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
> + info->chip.ecc.bytes = 3;
> + info->chip.ecc.algo = NAND_ECC_HAMMING;
> + }
> + info->chip.ecc.size = 512;
> + info->chip.ecc.strength = pdata->ecc_bits;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + /*
> + * Update ECC layout if needed ... for 1-bit HW ECC, the default
> + * is OK, but it allocates 6 bytes when only 3 are needed (for
> + * each 512 bytes). For the 4-bit HW ECC, that default is not
> + * usable: 10 bytes are needed, not 6.
> + */
> + if (pdata->ecc_bits == 4) {
> + int chunks = mtd->writesize / 512;
> +
> + if (!chunks || mtd->oobsize < 16) {
> + dev_dbg(&info->pdev->dev, "too small\n");
> + return -EINVAL;
> + }
> +
> + /* For small page chips, preserve the manufacturer's
> + * badblock marking data ... and make sure a flash BBT
> + * table marker fits in the free bytes.
> + */
> + if (chunks == 1) {
> + mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
> + } else if (chunks == 4 || chunks == 8) {
> + mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> + info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> + } else {
> + return -EIO;
> + }
> + }
> +
> + return ret;
> +}
> +
> +static const struct nand_controller_ops davinci_nand_controller_ops = {
> + .attach_chip = davinci_nand_attach_chip,
> +};
> +
> static int nand_davinci_probe(struct platform_device *pdev)
> {
> struct davinci_nand_pdata *pdata;
> @@ -658,7 +756,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
> return -EADDRNOTAVAIL;
> }
>
> - info->dev = &pdev->dev;
> + info->pdev = pdev;
> info->base = base;
> info->vaddr = vaddr;
>
> @@ -708,97 +806,13 @@ static int nand_davinci_probe(struct platform_device *pdev)
> spin_unlock_irq(&davinci_nand_lock);
>
> /* Scan to find existence of the device(s) */
> - ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL);
> + info->chip.dummy_controller.ops = &davinci_nand_controller_ops;
> + ret = nand_scan(mtd, pdata->mask_chipsel ? 2 : 1);
> if (ret < 0) {
> dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
> return ret;
> }
>
> - switch (info->chip.ecc.mode) {
> - case NAND_ECC_NONE:
> - pdata->ecc_bits = 0;
> - break;
> - case NAND_ECC_SOFT:
> - pdata->ecc_bits = 0;
> - /*
> - * This driver expects Hamming based ECC when ecc_mode is set
> - * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
> - * avoid adding an extra ->ecc_algo field to
> - * davinci_nand_pdata.
> - */
> - info->chip.ecc.algo = NAND_ECC_HAMMING;
> - break;
> - case NAND_ECC_HW:
> - if (pdata->ecc_bits == 4) {
> - /* No sanity checks: CPUs must support this,
> - * and the chips may not use NAND_BUSWIDTH_16.
> - */
> -
> - /* No sharing 4-bit hardware between chipselects yet */
> - spin_lock_irq(&davinci_nand_lock);
> - if (ecc4_busy)
> - ret = -EBUSY;
> - else
> - ecc4_busy = true;
> - spin_unlock_irq(&davinci_nand_lock);
> -
> - if (ret == -EBUSY)
> - return ret;
> -
> - info->chip.ecc.calculate = nand_davinci_calculate_4bit;
> - info->chip.ecc.correct = nand_davinci_correct_4bit;
> - info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
> - info->chip.ecc.bytes = 10;
> - info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
> - info->chip.ecc.algo = NAND_ECC_BCH;
> - } else {
> - /* 1bit ecc hamming */
> - info->chip.ecc.calculate = nand_davinci_calculate_1bit;
> - info->chip.ecc.correct = nand_davinci_correct_1bit;
> - info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
> - info->chip.ecc.bytes = 3;
> - info->chip.ecc.algo = NAND_ECC_HAMMING;
> - }
> - info->chip.ecc.size = 512;
> - info->chip.ecc.strength = pdata->ecc_bits;
> - break;
> - default:
> - return -EINVAL;
> - }
> -
> - /* Update ECC layout if needed ... for 1-bit HW ECC, the default
> - * is OK, but it allocates 6 bytes when only 3 are needed (for
> - * each 512 bytes). For the 4-bit HW ECC, that default is not
> - * usable: 10 bytes are needed, not 6.
> - */
> - if (pdata->ecc_bits == 4) {
> - int chunks = mtd->writesize / 512;
> -
> - if (!chunks || mtd->oobsize < 16) {
> - dev_dbg(&pdev->dev, "too small\n");
> - ret = -EINVAL;
> - goto err;
> - }
> -
> - /* For small page chips, preserve the manufacturer's
> - * badblock marking data ... and make sure a flash BBT
> - * table marker fits in the free bytes.
> - */
> - if (chunks == 1) {
> - mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
> - } else if (chunks == 4 || chunks == 8) {
> - mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> - info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> - } else {
> - ret = -EIO;
> - goto err;
> - }
> - }
> -
> - ret = nand_scan_tail(mtd);
> - if (ret < 0)
> - goto err;
> -
> if (pdata->parts)
> ret = mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
> else
> @@ -815,11 +829,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
> err_cleanup_nand:
> nand_cleanup(&info->chip);
>
> -err:
> - spin_lock_irq(&davinci_nand_lock);
> - if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
> - ecc4_busy = false;
> - spin_unlock_irq(&davinci_nand_lock);
> return ret;
> }
>

\
 
 \ /
  Last update: 2018-07-21 08:44    [W:0.279 / U:0.436 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site