diff options
Diffstat (limited to 'drivers/mtd/nand/raw/plat_nand.c')
| -rw-r--r-- | drivers/mtd/nand/raw/plat_nand.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c index a994b76daa50..0bcd455328ef 100644 --- a/drivers/mtd/nand/raw/plat_nand.c +++ b/drivers/mtd/nand/raw/plat_nand.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Generic NAND driver * * Author: Vitaly Wool <vitalywool@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/err.h> @@ -18,10 +14,24 @@ #include <linux/mtd/platnand.h> struct plat_nand_data { + struct nand_controller controller; struct nand_chip chip; void __iomem *io_base; }; +static int plat_nand_attach_chip(struct nand_chip *chip) +{ + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && + chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + + return 0; +} + +static const struct nand_controller_ops plat_nand_ops = { + .attach_chip = plat_nand_attach_chip, +}; + /* * Probe for the NAND device. */ @@ -30,7 +40,6 @@ static int plat_nand_probe(struct platform_device *pdev) struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); struct plat_nand_data *data; struct mtd_info *mtd; - struct resource *res; const char **part_types; int err = 0; @@ -50,8 +59,11 @@ static int plat_nand_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->io_base = devm_ioremap_resource(&pdev->dev, res); + data->controller.ops = &plat_nand_ops; + nand_controller_init(&data->controller); + data->chip.controller = &data->controller; + + data->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(data->io_base)) return PTR_ERR(data->io_base); @@ -70,9 +82,6 @@ static int plat_nand_probe(struct platform_device *pdev) data->chip.options |= pdata->chip.options; data->chip.bbt_options |= pdata->chip.bbt_options; - data->chip.ecc.mode = NAND_ECC_SOFT; - data->chip.ecc.algo = NAND_ECC_HAMMING; - platform_set_drvdata(pdev, data); /* Handle any platform specific setup */ @@ -82,6 +91,13 @@ static int plat_nand_probe(struct platform_device *pdev) goto out; } + /* + * This driver assumes that the default ECC engine should be TYPE_SOFT. + * Set ->engine_type before registering the NAND devices in order to + * provide a driver specific default value. + */ + data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; + /* Scan to find existence of the device */ err = nand_scan(&data->chip, pdata->chip.nr_chips); if (err) @@ -96,7 +112,7 @@ static int plat_nand_probe(struct platform_device *pdev) if (!err) return err; - nand_release(&data->chip); + nand_cleanup(&data->chip); out: if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); @@ -106,16 +122,18 @@ out: /* * Remove a NAND device. */ -static int plat_nand_remove(struct platform_device *pdev) +static void plat_nand_remove(struct platform_device *pdev) { struct plat_nand_data *data = platform_get_drvdata(pdev); struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); + struct nand_chip *chip = &data->chip; + int ret; - nand_release(&data->chip); + ret = mtd_device_unregister(nand_to_mtd(chip)); + WARN_ON(ret); + nand_cleanup(chip); if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); - - return 0; } static const struct of_device_id plat_nand_match[] = { @@ -126,7 +144,7 @@ MODULE_DEVICE_TABLE(of, plat_nand_match); static struct platform_driver plat_nand_driver = { .probe = plat_nand_probe, - .remove = plat_nand_remove, + .remove = plat_nand_remove, .driver = { .name = "gen_nand", .of_match_table = plat_nand_match, |
