| .. | .. |
|---|
| 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; |
|---|