.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2004 Richard Purdie |
---|
3 | 4 | * Copyright (C) 2008 Dmitry Baryshkov |
---|
4 | 5 | * |
---|
5 | 6 | * Based on Sharp's NAND driver sharp_sl.c |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | #include <linux/genhd.h> |
---|
.. | .. |
---|
24 | 20 | #include <linux/io.h> |
---|
25 | 21 | |
---|
26 | 22 | struct sharpsl_nand { |
---|
| 23 | + struct nand_controller controller; |
---|
27 | 24 | struct nand_chip chip; |
---|
28 | 25 | |
---|
29 | 26 | void __iomem *io; |
---|
.. | .. |
---|
59 | 56 | * NAND_ALE: bit 2 -> bit 2 |
---|
60 | 57 | * |
---|
61 | 58 | */ |
---|
62 | | -static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, |
---|
| 59 | +static void sharpsl_nand_hwcontrol(struct nand_chip *chip, int cmd, |
---|
63 | 60 | unsigned int ctrl) |
---|
64 | 61 | { |
---|
65 | | - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); |
---|
66 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
| 62 | + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); |
---|
67 | 63 | |
---|
68 | 64 | if (ctrl & NAND_CTRL_CHANGE) { |
---|
69 | 65 | unsigned char bits = ctrl & 0x07; |
---|
.. | .. |
---|
76 | 72 | } |
---|
77 | 73 | |
---|
78 | 74 | if (cmd != NAND_CMD_NONE) |
---|
79 | | - writeb(cmd, chip->IO_ADDR_W); |
---|
| 75 | + writeb(cmd, chip->legacy.IO_ADDR_W); |
---|
80 | 76 | } |
---|
81 | 77 | |
---|
82 | | -static int sharpsl_nand_dev_ready(struct mtd_info *mtd) |
---|
| 78 | +static int sharpsl_nand_dev_ready(struct nand_chip *chip) |
---|
83 | 79 | { |
---|
84 | | - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); |
---|
| 80 | + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); |
---|
85 | 81 | return !((readb(sharpsl->io + FLASHCTL) & FLRYBY) == 0); |
---|
86 | 82 | } |
---|
87 | 83 | |
---|
88 | | -static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode) |
---|
| 84 | +static void sharpsl_nand_enable_hwecc(struct nand_chip *chip, int mode) |
---|
89 | 85 | { |
---|
90 | | - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); |
---|
| 86 | + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); |
---|
91 | 87 | writeb(0, sharpsl->io + ECCCLRR); |
---|
92 | 88 | } |
---|
93 | 89 | |
---|
94 | | -static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code) |
---|
| 90 | +static int sharpsl_nand_calculate_ecc(struct nand_chip *chip, |
---|
| 91 | + const u_char * dat, u_char * ecc_code) |
---|
95 | 92 | { |
---|
96 | | - struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); |
---|
| 93 | + struct sharpsl_nand *sharpsl = mtd_to_sharpsl(nand_to_mtd(chip)); |
---|
97 | 94 | ecc_code[0] = ~readb(sharpsl->io + ECCLPUB); |
---|
98 | 95 | ecc_code[1] = ~readb(sharpsl->io + ECCLPLB); |
---|
99 | 96 | ecc_code[2] = (~readb(sharpsl->io + ECCCP) << 2) | 0x03; |
---|
100 | 97 | return readb(sharpsl->io + ECCCNTR) != 0; |
---|
101 | 98 | } |
---|
| 99 | + |
---|
| 100 | +static int sharpsl_attach_chip(struct nand_chip *chip) |
---|
| 101 | +{ |
---|
| 102 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) |
---|
| 103 | + return 0; |
---|
| 104 | + |
---|
| 105 | + chip->ecc.size = 256; |
---|
| 106 | + chip->ecc.bytes = 3; |
---|
| 107 | + chip->ecc.strength = 1; |
---|
| 108 | + chip->ecc.hwctl = sharpsl_nand_enable_hwecc; |
---|
| 109 | + chip->ecc.calculate = sharpsl_nand_calculate_ecc; |
---|
| 110 | + chip->ecc.correct = nand_correct_data; |
---|
| 111 | + |
---|
| 112 | + return 0; |
---|
| 113 | +} |
---|
| 114 | + |
---|
| 115 | +static const struct nand_controller_ops sharpsl_ops = { |
---|
| 116 | + .attach_chip = sharpsl_attach_chip, |
---|
| 117 | +}; |
---|
102 | 118 | |
---|
103 | 119 | /* |
---|
104 | 120 | * Main initialization routine |
---|
.. | .. |
---|
140 | 156 | /* Get pointer to private data */ |
---|
141 | 157 | this = (struct nand_chip *)(&sharpsl->chip); |
---|
142 | 158 | |
---|
| 159 | + nand_controller_init(&sharpsl->controller); |
---|
| 160 | + sharpsl->controller.ops = &sharpsl_ops; |
---|
| 161 | + this->controller = &sharpsl->controller; |
---|
| 162 | + |
---|
143 | 163 | /* Link the private data with the MTD structure */ |
---|
144 | 164 | mtd = nand_to_mtd(this); |
---|
145 | 165 | mtd->dev.parent = &pdev->dev; |
---|
.. | .. |
---|
153 | 173 | writeb(readb(sharpsl->io + FLASHCTL) | FLWP, sharpsl->io + FLASHCTL); |
---|
154 | 174 | |
---|
155 | 175 | /* Set address of NAND IO lines */ |
---|
156 | | - this->IO_ADDR_R = sharpsl->io + FLASHIO; |
---|
157 | | - this->IO_ADDR_W = sharpsl->io + FLASHIO; |
---|
| 176 | + this->legacy.IO_ADDR_R = sharpsl->io + FLASHIO; |
---|
| 177 | + this->legacy.IO_ADDR_W = sharpsl->io + FLASHIO; |
---|
158 | 178 | /* Set address of hardware control function */ |
---|
159 | | - this->cmd_ctrl = sharpsl_nand_hwcontrol; |
---|
160 | | - this->dev_ready = sharpsl_nand_dev_ready; |
---|
| 179 | + this->legacy.cmd_ctrl = sharpsl_nand_hwcontrol; |
---|
| 180 | + this->legacy.dev_ready = sharpsl_nand_dev_ready; |
---|
161 | 181 | /* 15 us command delay time */ |
---|
162 | | - this->chip_delay = 15; |
---|
163 | | - /* set eccmode using hardware ECC */ |
---|
164 | | - this->ecc.mode = NAND_ECC_HW; |
---|
165 | | - this->ecc.size = 256; |
---|
166 | | - this->ecc.bytes = 3; |
---|
167 | | - this->ecc.strength = 1; |
---|
| 182 | + this->legacy.chip_delay = 15; |
---|
168 | 183 | this->badblock_pattern = data->badblock_pattern; |
---|
169 | | - this->ecc.hwctl = sharpsl_nand_enable_hwecc; |
---|
170 | | - this->ecc.calculate = sharpsl_nand_calculate_ecc; |
---|
171 | | - this->ecc.correct = nand_correct_data; |
---|
172 | 184 | |
---|
173 | 185 | /* Scan to find existence of the device */ |
---|
174 | 186 | err = nand_scan(this, 1); |
---|
.. | .. |
---|
203 | 215 | static int sharpsl_nand_remove(struct platform_device *pdev) |
---|
204 | 216 | { |
---|
205 | 217 | struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev); |
---|
| 218 | + struct nand_chip *chip = &sharpsl->chip; |
---|
| 219 | + int ret; |
---|
206 | 220 | |
---|
207 | | - /* Release resources, unregister device */ |
---|
208 | | - nand_release(&sharpsl->chip); |
---|
| 221 | + /* Unregister device */ |
---|
| 222 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
---|
| 223 | + WARN_ON(ret); |
---|
| 224 | + |
---|
| 225 | + /* Release resources */ |
---|
| 226 | + nand_cleanup(chip); |
---|
209 | 227 | |
---|
210 | 228 | iounmap(sharpsl->io); |
---|
211 | 229 | |
---|
212 | | - /* Free the MTD device structure */ |
---|
| 230 | + /* Free the driver's structure */ |
---|
213 | 231 | kfree(sharpsl); |
---|
214 | 232 | |
---|
215 | 233 | return 0; |
---|