.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Generic NAND driver |
---|
3 | 4 | * |
---|
4 | 5 | * Author: Vitaly Wool <vitalywool@gmail.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | #include <linux/err.h> |
---|
.. | .. |
---|
15 | 11 | #include <linux/platform_device.h> |
---|
16 | 12 | #include <linux/slab.h> |
---|
17 | 13 | #include <linux/mtd/mtd.h> |
---|
18 | | -#include <linux/mtd/rawnand.h> |
---|
19 | | -#include <linux/mtd/partitions.h> |
---|
| 14 | +#include <linux/mtd/platnand.h> |
---|
20 | 15 | |
---|
21 | 16 | struct plat_nand_data { |
---|
| 17 | + struct nand_controller controller; |
---|
22 | 18 | struct nand_chip chip; |
---|
23 | 19 | void __iomem *io_base; |
---|
| 20 | +}; |
---|
| 21 | + |
---|
| 22 | +static int plat_nand_attach_chip(struct nand_chip *chip) |
---|
| 23 | +{ |
---|
| 24 | + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && |
---|
| 25 | + chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) |
---|
| 26 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; |
---|
| 27 | + |
---|
| 28 | + return 0; |
---|
| 29 | +} |
---|
| 30 | + |
---|
| 31 | +static const struct nand_controller_ops plat_nand_ops = { |
---|
| 32 | + .attach_chip = plat_nand_attach_chip, |
---|
24 | 33 | }; |
---|
25 | 34 | |
---|
26 | 35 | /* |
---|
.. | .. |
---|
51 | 60 | if (!data) |
---|
52 | 61 | return -ENOMEM; |
---|
53 | 62 | |
---|
| 63 | + data->controller.ops = &plat_nand_ops; |
---|
| 64 | + nand_controller_init(&data->controller); |
---|
| 65 | + data->chip.controller = &data->controller; |
---|
| 66 | + |
---|
54 | 67 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
55 | 68 | data->io_base = devm_ioremap_resource(&pdev->dev, res); |
---|
56 | 69 | if (IS_ERR(data->io_base)) |
---|
.. | .. |
---|
60 | 73 | mtd = nand_to_mtd(&data->chip); |
---|
61 | 74 | mtd->dev.parent = &pdev->dev; |
---|
62 | 75 | |
---|
63 | | - data->chip.IO_ADDR_R = data->io_base; |
---|
64 | | - data->chip.IO_ADDR_W = data->io_base; |
---|
65 | | - data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; |
---|
66 | | - data->chip.dev_ready = pdata->ctrl.dev_ready; |
---|
67 | | - data->chip.select_chip = pdata->ctrl.select_chip; |
---|
68 | | - data->chip.write_buf = pdata->ctrl.write_buf; |
---|
69 | | - data->chip.read_buf = pdata->ctrl.read_buf; |
---|
70 | | - data->chip.chip_delay = pdata->chip.chip_delay; |
---|
| 76 | + data->chip.legacy.IO_ADDR_R = data->io_base; |
---|
| 77 | + data->chip.legacy.IO_ADDR_W = data->io_base; |
---|
| 78 | + data->chip.legacy.cmd_ctrl = pdata->ctrl.cmd_ctrl; |
---|
| 79 | + data->chip.legacy.dev_ready = pdata->ctrl.dev_ready; |
---|
| 80 | + data->chip.legacy.select_chip = pdata->ctrl.select_chip; |
---|
| 81 | + data->chip.legacy.write_buf = pdata->ctrl.write_buf; |
---|
| 82 | + data->chip.legacy.read_buf = pdata->ctrl.read_buf; |
---|
| 83 | + data->chip.legacy.chip_delay = pdata->chip.chip_delay; |
---|
71 | 84 | data->chip.options |= pdata->chip.options; |
---|
72 | 85 | data->chip.bbt_options |= pdata->chip.bbt_options; |
---|
73 | | - |
---|
74 | | - data->chip.ecc.mode = NAND_ECC_SOFT; |
---|
75 | | - data->chip.ecc.algo = NAND_ECC_HAMMING; |
---|
76 | 86 | |
---|
77 | 87 | platform_set_drvdata(pdev, data); |
---|
78 | 88 | |
---|
.. | .. |
---|
82 | 92 | if (err) |
---|
83 | 93 | goto out; |
---|
84 | 94 | } |
---|
| 95 | + |
---|
| 96 | + /* |
---|
| 97 | + * This driver assumes that the default ECC engine should be TYPE_SOFT. |
---|
| 98 | + * Set ->engine_type before registering the NAND devices in order to |
---|
| 99 | + * provide a driver specific default value. |
---|
| 100 | + */ |
---|
| 101 | + data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; |
---|
85 | 102 | |
---|
86 | 103 | /* Scan to find existence of the device */ |
---|
87 | 104 | err = nand_scan(&data->chip, pdata->chip.nr_chips); |
---|
.. | .. |
---|
111 | 128 | { |
---|
112 | 129 | struct plat_nand_data *data = platform_get_drvdata(pdev); |
---|
113 | 130 | struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); |
---|
| 131 | + struct nand_chip *chip = &data->chip; |
---|
| 132 | + int ret; |
---|
114 | 133 | |
---|
115 | | - nand_release(&data->chip); |
---|
| 134 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
---|
| 135 | + WARN_ON(ret); |
---|
| 136 | + nand_cleanup(chip); |
---|
116 | 137 | if (pdata->ctrl.remove) |
---|
117 | 138 | pdata->ctrl.remove(pdev); |
---|
118 | 139 | |
---|