| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 2004-2008 Freescale Semiconductor, Inc. |
|---|
| 3 | 4 | * Copyright 2009 Semihalf. |
|---|
| .. | .. |
|---|
| 8 | 9 | * Based on original driver from Freescale Semiconductor |
|---|
| 9 | 10 | * written by John Rigby <jrigby@freescale.com> on basis of mxc_nand.c. |
|---|
| 10 | 11 | * Reworked and extended by Piotr Ziecik <kosmo@semihalf.com>. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or |
|---|
| 13 | | - * modify it under the terms of the GNU General Public License |
|---|
| 14 | | - * as published by the Free Software Foundation; either version 2 |
|---|
| 15 | | - * of the License, or (at your option) any later version. |
|---|
| 16 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 17 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 19 | | - * GNU General Public License for more details. |
|---|
| 20 | | - * |
|---|
| 21 | | - * You should have received a copy of the GNU General Public License |
|---|
| 22 | | - * along with this program; if not, write to the Free Software |
|---|
| 23 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|---|
| 24 | | - * MA 02110-1301, USA. |
|---|
| 25 | 12 | */ |
|---|
| 26 | 13 | |
|---|
| 27 | 14 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 117 | 104 | #define NFC_TIMEOUT (HZ / 10) /* 1/10 s */ |
|---|
| 118 | 105 | |
|---|
| 119 | 106 | struct mpc5121_nfc_prv { |
|---|
| 107 | + struct nand_controller controller; |
|---|
| 120 | 108 | struct nand_chip chip; |
|---|
| 121 | 109 | int irq; |
|---|
| 122 | 110 | void __iomem *regs; |
|---|
| .. | .. |
|---|
| 263 | 251 | } |
|---|
| 264 | 252 | |
|---|
| 265 | 253 | /* Control chip select signals */ |
|---|
| 266 | | -static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip) |
|---|
| 254 | +static void mpc5121_nfc_select_chip(struct nand_chip *nand, int chip) |
|---|
| 267 | 255 | { |
|---|
| 256 | + struct mtd_info *mtd = nand_to_mtd(nand); |
|---|
| 257 | + |
|---|
| 268 | 258 | if (chip < 0) { |
|---|
| 269 | 259 | nfc_clear(mtd, NFC_CONFIG1, NFC_CE); |
|---|
| 270 | 260 | return; |
|---|
| .. | .. |
|---|
| 299 | 289 | } |
|---|
| 300 | 290 | |
|---|
| 301 | 291 | /* Control chips select signal on ADS5121 board */ |
|---|
| 302 | | -static void ads5121_select_chip(struct mtd_info *mtd, int chip) |
|---|
| 292 | +static void ads5121_select_chip(struct nand_chip *nand, int chip) |
|---|
| 303 | 293 | { |
|---|
| 304 | | - struct nand_chip *nand = mtd_to_nand(mtd); |
|---|
| 305 | 294 | struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand); |
|---|
| 306 | 295 | u8 v; |
|---|
| 307 | 296 | |
|---|
| .. | .. |
|---|
| 309 | 298 | v |= 0x0F; |
|---|
| 310 | 299 | |
|---|
| 311 | 300 | if (chip >= 0) { |
|---|
| 312 | | - mpc5121_nfc_select_chip(mtd, 0); |
|---|
| 301 | + mpc5121_nfc_select_chip(nand, 0); |
|---|
| 313 | 302 | v &= ~(1 << chip); |
|---|
| 314 | 303 | } else |
|---|
| 315 | | - mpc5121_nfc_select_chip(mtd, -1); |
|---|
| 304 | + mpc5121_nfc_select_chip(nand, -1); |
|---|
| 316 | 305 | |
|---|
| 317 | 306 | out_8(prv->csreg, v); |
|---|
| 318 | 307 | } |
|---|
| 319 | 308 | |
|---|
| 320 | 309 | /* Read NAND Ready/Busy signal */ |
|---|
| 321 | | -static int mpc5121_nfc_dev_ready(struct mtd_info *mtd) |
|---|
| 310 | +static int mpc5121_nfc_dev_ready(struct nand_chip *nand) |
|---|
| 322 | 311 | { |
|---|
| 323 | 312 | /* |
|---|
| 324 | 313 | * NFC handles ready/busy signal internally. Therefore, this function |
|---|
| .. | .. |
|---|
| 328 | 317 | } |
|---|
| 329 | 318 | |
|---|
| 330 | 319 | /* Write command to NAND flash */ |
|---|
| 331 | | -static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, |
|---|
| 332 | | - int column, int page) |
|---|
| 320 | +static void mpc5121_nfc_command(struct nand_chip *chip, unsigned command, |
|---|
| 321 | + int column, int page) |
|---|
| 333 | 322 | { |
|---|
| 334 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 323 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 335 | 324 | struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); |
|---|
| 336 | 325 | |
|---|
| 337 | 326 | prv->column = (column >= 0) ? column : 0; |
|---|
| .. | .. |
|---|
| 362 | 351 | break; |
|---|
| 363 | 352 | |
|---|
| 364 | 353 | case NAND_CMD_SEQIN: |
|---|
| 365 | | - mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page); |
|---|
| 354 | + mpc5121_nfc_command(chip, NAND_CMD_READ0, column, page); |
|---|
| 366 | 355 | column = 0; |
|---|
| 367 | 356 | break; |
|---|
| 368 | 357 | |
|---|
| .. | .. |
|---|
| 449 | 438 | buffer += blksize; |
|---|
| 450 | 439 | offset += blksize; |
|---|
| 451 | 440 | size -= blksize; |
|---|
| 452 | | - }; |
|---|
| 441 | + } |
|---|
| 453 | 442 | } |
|---|
| 454 | 443 | |
|---|
| 455 | 444 | /* Copy data from/to NFC main and spare buffers */ |
|---|
| .. | .. |
|---|
| 493 | 482 | } |
|---|
| 494 | 483 | |
|---|
| 495 | 484 | /* Read data from NFC buffers */ |
|---|
| 496 | | -static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
|---|
| 485 | +static void mpc5121_nfc_read_buf(struct nand_chip *chip, u_char *buf, int len) |
|---|
| 497 | 486 | { |
|---|
| 498 | | - mpc5121_nfc_buf_copy(mtd, buf, len, 0); |
|---|
| 487 | + mpc5121_nfc_buf_copy(nand_to_mtd(chip), buf, len, 0); |
|---|
| 499 | 488 | } |
|---|
| 500 | 489 | |
|---|
| 501 | 490 | /* Write data to NFC buffers */ |
|---|
| 502 | | -static void mpc5121_nfc_write_buf(struct mtd_info *mtd, |
|---|
| 503 | | - const u_char *buf, int len) |
|---|
| 491 | +static void mpc5121_nfc_write_buf(struct nand_chip *chip, const u_char *buf, |
|---|
| 492 | + int len) |
|---|
| 504 | 493 | { |
|---|
| 505 | | - mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1); |
|---|
| 494 | + mpc5121_nfc_buf_copy(nand_to_mtd(chip), (u_char *)buf, len, 1); |
|---|
| 506 | 495 | } |
|---|
| 507 | 496 | |
|---|
| 508 | 497 | /* Read byte from NFC buffers */ |
|---|
| 509 | | -static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd) |
|---|
| 498 | +static u8 mpc5121_nfc_read_byte(struct nand_chip *chip) |
|---|
| 510 | 499 | { |
|---|
| 511 | 500 | u8 tmp; |
|---|
| 512 | 501 | |
|---|
| 513 | | - mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp)); |
|---|
| 514 | | - |
|---|
| 515 | | - return tmp; |
|---|
| 516 | | -} |
|---|
| 517 | | - |
|---|
| 518 | | -/* Read word from NFC buffers */ |
|---|
| 519 | | -static u16 mpc5121_nfc_read_word(struct mtd_info *mtd) |
|---|
| 520 | | -{ |
|---|
| 521 | | - u16 tmp; |
|---|
| 522 | | - |
|---|
| 523 | | - mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp)); |
|---|
| 502 | + mpc5121_nfc_read_buf(chip, &tmp, sizeof(tmp)); |
|---|
| 524 | 503 | |
|---|
| 525 | 504 | return tmp; |
|---|
| 526 | 505 | } |
|---|
| .. | .. |
|---|
| 623 | 602 | iounmap(prv->csreg); |
|---|
| 624 | 603 | } |
|---|
| 625 | 604 | |
|---|
| 605 | +static int mpc5121_nfc_attach_chip(struct nand_chip *chip) |
|---|
| 606 | +{ |
|---|
| 607 | + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && |
|---|
| 608 | + chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) |
|---|
| 609 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; |
|---|
| 610 | + |
|---|
| 611 | + return 0; |
|---|
| 612 | +} |
|---|
| 613 | + |
|---|
| 614 | +static const struct nand_controller_ops mpc5121_nfc_ops = { |
|---|
| 615 | + .attach_chip = mpc5121_nfc_attach_chip, |
|---|
| 616 | +}; |
|---|
| 617 | + |
|---|
| 626 | 618 | static int mpc5121_nfc_probe(struct platform_device *op) |
|---|
| 627 | 619 | { |
|---|
| 628 | 620 | struct device_node *dn = op->dev.of_node; |
|---|
| .. | .. |
|---|
| 654 | 646 | |
|---|
| 655 | 647 | chip = &prv->chip; |
|---|
| 656 | 648 | mtd = nand_to_mtd(chip); |
|---|
| 649 | + |
|---|
| 650 | + nand_controller_init(&prv->controller); |
|---|
| 651 | + prv->controller.ops = &mpc5121_nfc_ops; |
|---|
| 652 | + chip->controller = &prv->controller; |
|---|
| 657 | 653 | |
|---|
| 658 | 654 | mtd->dev.parent = dev; |
|---|
| 659 | 655 | nand_set_controller_data(chip, prv); |
|---|
| .. | .. |
|---|
| 700 | 696 | } |
|---|
| 701 | 697 | |
|---|
| 702 | 698 | mtd->name = "MPC5121 NAND"; |
|---|
| 703 | | - chip->dev_ready = mpc5121_nfc_dev_ready; |
|---|
| 704 | | - chip->cmdfunc = mpc5121_nfc_command; |
|---|
| 705 | | - chip->read_byte = mpc5121_nfc_read_byte; |
|---|
| 706 | | - chip->read_word = mpc5121_nfc_read_word; |
|---|
| 707 | | - chip->read_buf = mpc5121_nfc_read_buf; |
|---|
| 708 | | - chip->write_buf = mpc5121_nfc_write_buf; |
|---|
| 709 | | - chip->select_chip = mpc5121_nfc_select_chip; |
|---|
| 710 | | - chip->set_features = nand_get_set_features_notsupp; |
|---|
| 711 | | - chip->get_features = nand_get_set_features_notsupp; |
|---|
| 699 | + chip->legacy.dev_ready = mpc5121_nfc_dev_ready; |
|---|
| 700 | + chip->legacy.cmdfunc = mpc5121_nfc_command; |
|---|
| 701 | + chip->legacy.read_byte = mpc5121_nfc_read_byte; |
|---|
| 702 | + chip->legacy.read_buf = mpc5121_nfc_read_buf; |
|---|
| 703 | + chip->legacy.write_buf = mpc5121_nfc_write_buf; |
|---|
| 704 | + chip->legacy.select_chip = mpc5121_nfc_select_chip; |
|---|
| 705 | + chip->legacy.set_features = nand_get_set_features_notsupp; |
|---|
| 706 | + chip->legacy.get_features = nand_get_set_features_notsupp; |
|---|
| 712 | 707 | chip->bbt_options = NAND_BBT_USE_FLASH; |
|---|
| 713 | | - chip->ecc.mode = NAND_ECC_SOFT; |
|---|
| 714 | | - chip->ecc.algo = NAND_ECC_HAMMING; |
|---|
| 715 | 708 | |
|---|
| 716 | 709 | /* Support external chip-select logic on ADS5121 board */ |
|---|
| 717 | 710 | if (of_machine_is_compatible("fsl,mpc5121ads")) { |
|---|
| .. | .. |
|---|
| 721 | 714 | return retval; |
|---|
| 722 | 715 | } |
|---|
| 723 | 716 | |
|---|
| 724 | | - chip->select_chip = ads5121_select_chip; |
|---|
| 717 | + chip->legacy.select_chip = ads5121_select_chip; |
|---|
| 725 | 718 | } |
|---|
| 726 | 719 | |
|---|
| 727 | 720 | /* Enable NFC clock */ |
|---|
| .. | .. |
|---|
| 777 | 770 | goto error; |
|---|
| 778 | 771 | } |
|---|
| 779 | 772 | |
|---|
| 773 | + /* |
|---|
| 774 | + * This driver assumes that the default ECC engine should be TYPE_SOFT. |
|---|
| 775 | + * Set ->engine_type before registering the NAND devices in order to |
|---|
| 776 | + * provide a driver specific default value. |
|---|
| 777 | + */ |
|---|
| 778 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; |
|---|
| 779 | + |
|---|
| 780 | 780 | /* Detect NAND chips */ |
|---|
| 781 | 781 | retval = nand_scan(chip, be32_to_cpup(chips_no)); |
|---|
| 782 | 782 | if (retval) { |
|---|
| .. | .. |
|---|
| 827 | 827 | { |
|---|
| 828 | 828 | struct device *dev = &op->dev; |
|---|
| 829 | 829 | struct mtd_info *mtd = dev_get_drvdata(dev); |
|---|
| 830 | + int ret; |
|---|
| 830 | 831 | |
|---|
| 831 | | - nand_release(mtd_to_nand(mtd)); |
|---|
| 832 | + ret = mtd_device_unregister(mtd); |
|---|
| 833 | + WARN_ON(ret); |
|---|
| 834 | + nand_cleanup(mtd_to_nand(mtd)); |
|---|
| 832 | 835 | mpc5121_nfc_free(dev, mtd); |
|---|
| 833 | 836 | |
|---|
| 834 | 837 | return 0; |
|---|