| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* Freescale Enhanced Local Bus Controller NAND driver |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
|---|
| .. | .. |
|---|
| 6 | 7 | * Scott Wood <scottwood@freescale.com> |
|---|
| 7 | 8 | * Jack Lan <jack.lan@freescale.com> |
|---|
| 8 | 9 | * Roy Zang <tie-fei.zang@freescale.com> |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 13 | | - * (at your option) any later version. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - * GNU General Public License for more details. |
|---|
| 19 | | - * |
|---|
| 20 | | - * You should have received a copy of the GNU General Public License |
|---|
| 21 | | - * along with this program; if not, write to the Free Software |
|---|
| 22 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 23 | 10 | */ |
|---|
| 24 | 11 | |
|---|
| 25 | 12 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 257 | 244 | return -EIO; |
|---|
| 258 | 245 | } |
|---|
| 259 | 246 | |
|---|
| 260 | | - if (chip->ecc.mode != NAND_ECC_HW) |
|---|
| 247 | + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) |
|---|
| 261 | 248 | return 0; |
|---|
| 262 | 249 | |
|---|
| 263 | 250 | elbc_fcm_ctrl->max_bitflips = 0; |
|---|
| .. | .. |
|---|
| 317 | 304 | } |
|---|
| 318 | 305 | |
|---|
| 319 | 306 | /* cmdfunc send commands to the FCM */ |
|---|
| 320 | | -static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, |
|---|
| 307 | +static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command, |
|---|
| 321 | 308 | int column, int page_addr) |
|---|
| 322 | 309 | { |
|---|
| 323 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 310 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 324 | 311 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 325 | 312 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
|---|
| 326 | 313 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
|---|
| .. | .. |
|---|
| 337 | 324 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ |
|---|
| 338 | 325 | case NAND_CMD_READ1: |
|---|
| 339 | 326 | column += 256; |
|---|
| 340 | | - |
|---|
| 341 | | - /* fall-through */ |
|---|
| 327 | + fallthrough; |
|---|
| 342 | 328 | case NAND_CMD_READ0: |
|---|
| 343 | 329 | dev_dbg(priv->dev, |
|---|
| 344 | 330 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" |
|---|
| .. | .. |
|---|
| 353 | 339 | |
|---|
| 354 | 340 | fsl_elbc_do_read(chip, 0); |
|---|
| 355 | 341 | fsl_elbc_run_command(mtd); |
|---|
| 342 | + return; |
|---|
| 343 | + |
|---|
| 344 | + /* RNDOUT moves the pointer inside the page */ |
|---|
| 345 | + case NAND_CMD_RNDOUT: |
|---|
| 346 | + dev_dbg(priv->dev, |
|---|
| 347 | + "fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n", |
|---|
| 348 | + column); |
|---|
| 349 | + |
|---|
| 350 | + elbc_fcm_ctrl->index = column; |
|---|
| 356 | 351 | return; |
|---|
| 357 | 352 | |
|---|
| 358 | 353 | /* READOOB reads only the OOB because no ECC is performed. */ |
|---|
| .. | .. |
|---|
| 533 | 528 | } |
|---|
| 534 | 529 | } |
|---|
| 535 | 530 | |
|---|
| 536 | | -static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip) |
|---|
| 531 | +static void fsl_elbc_select_chip(struct nand_chip *chip, int cs) |
|---|
| 537 | 532 | { |
|---|
| 538 | 533 | /* The hardware does not seem to support multiple |
|---|
| 539 | 534 | * chips per bank. |
|---|
| .. | .. |
|---|
| 543 | 538 | /* |
|---|
| 544 | 539 | * Write buf to the FCM Controller Data Buffer |
|---|
| 545 | 540 | */ |
|---|
| 546 | | -static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) |
|---|
| 541 | +static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len) |
|---|
| 547 | 542 | { |
|---|
| 548 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 543 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 549 | 544 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 550 | 545 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
|---|
| 551 | 546 | unsigned int bufsize = mtd->writesize + mtd->oobsize; |
|---|
| .. | .. |
|---|
| 581 | 576 | * read a byte from either the FCM hardware buffer if it has any data left |
|---|
| 582 | 577 | * otherwise issue a command to read a single byte. |
|---|
| 583 | 578 | */ |
|---|
| 584 | | -static u8 fsl_elbc_read_byte(struct mtd_info *mtd) |
|---|
| 579 | +static u8 fsl_elbc_read_byte(struct nand_chip *chip) |
|---|
| 585 | 580 | { |
|---|
| 586 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 587 | 581 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 588 | 582 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
|---|
| 589 | 583 | |
|---|
| .. | .. |
|---|
| 598 | 592 | /* |
|---|
| 599 | 593 | * Read from the FCM Controller Data Buffer |
|---|
| 600 | 594 | */ |
|---|
| 601 | | -static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) |
|---|
| 595 | +static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len) |
|---|
| 602 | 596 | { |
|---|
| 603 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 604 | 597 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 605 | 598 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
|---|
| 606 | 599 | int avail; |
|---|
| .. | .. |
|---|
| 623 | 616 | /* This function is called after Program and Erase Operations to |
|---|
| 624 | 617 | * check for success or failure. |
|---|
| 625 | 618 | */ |
|---|
| 626 | | -static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) |
|---|
| 619 | +static int fsl_elbc_wait(struct nand_chip *chip) |
|---|
| 627 | 620 | { |
|---|
| 628 | 621 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 629 | 622 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
|---|
| .. | .. |
|---|
| 637 | 630 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; |
|---|
| 638 | 631 | } |
|---|
| 639 | 632 | |
|---|
| 633 | +static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, |
|---|
| 634 | + int oob_required, int page) |
|---|
| 635 | +{ |
|---|
| 636 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 637 | + struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 638 | + struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
|---|
| 639 | + struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
|---|
| 640 | + |
|---|
| 641 | + nand_read_page_op(chip, page, 0, buf, mtd->writesize); |
|---|
| 642 | + if (oob_required) |
|---|
| 643 | + fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize); |
|---|
| 644 | + |
|---|
| 645 | + if (fsl_elbc_wait(chip) & NAND_STATUS_FAIL) |
|---|
| 646 | + mtd->ecc_stats.failed++; |
|---|
| 647 | + |
|---|
| 648 | + return elbc_fcm_ctrl->max_bitflips; |
|---|
| 649 | +} |
|---|
| 650 | + |
|---|
| 651 | +/* ECC will be calculated automatically, and errors will be detected in |
|---|
| 652 | + * waitfunc. |
|---|
| 653 | + */ |
|---|
| 654 | +static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf, |
|---|
| 655 | + int oob_required, int page) |
|---|
| 656 | +{ |
|---|
| 657 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 658 | + |
|---|
| 659 | + nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); |
|---|
| 660 | + fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize); |
|---|
| 661 | + |
|---|
| 662 | + return nand_prog_page_end_op(chip); |
|---|
| 663 | +} |
|---|
| 664 | + |
|---|
| 665 | +/* ECC will be calculated automatically, and errors will be detected in |
|---|
| 666 | + * waitfunc. |
|---|
| 667 | + */ |
|---|
| 668 | +static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset, |
|---|
| 669 | + uint32_t data_len, const uint8_t *buf, |
|---|
| 670 | + int oob_required, int page) |
|---|
| 671 | +{ |
|---|
| 672 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 673 | + |
|---|
| 674 | + nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
|---|
| 675 | + fsl_elbc_write_buf(chip, buf, mtd->writesize); |
|---|
| 676 | + fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize); |
|---|
| 677 | + return nand_prog_page_end_op(chip); |
|---|
| 678 | +} |
|---|
| 679 | + |
|---|
| 680 | +static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
|---|
| 681 | +{ |
|---|
| 682 | + struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
|---|
| 683 | + struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
|---|
| 684 | + struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
|---|
| 685 | + struct nand_chip *chip = &priv->chip; |
|---|
| 686 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 687 | + |
|---|
| 688 | + dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); |
|---|
| 689 | + |
|---|
| 690 | + /* Fill in fsl_elbc_mtd structure */ |
|---|
| 691 | + mtd->dev.parent = priv->dev; |
|---|
| 692 | + nand_set_flash_node(chip, priv->dev->of_node); |
|---|
| 693 | + |
|---|
| 694 | + /* set timeout to maximum */ |
|---|
| 695 | + priv->fmr = 15 << FMR_CWTO_SHIFT; |
|---|
| 696 | + if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS) |
|---|
| 697 | + priv->fmr |= FMR_ECCM; |
|---|
| 698 | + |
|---|
| 699 | + /* fill in nand_chip structure */ |
|---|
| 700 | + /* set up function call table */ |
|---|
| 701 | + chip->legacy.read_byte = fsl_elbc_read_byte; |
|---|
| 702 | + chip->legacy.write_buf = fsl_elbc_write_buf; |
|---|
| 703 | + chip->legacy.read_buf = fsl_elbc_read_buf; |
|---|
| 704 | + chip->legacy.select_chip = fsl_elbc_select_chip; |
|---|
| 705 | + chip->legacy.cmdfunc = fsl_elbc_cmdfunc; |
|---|
| 706 | + chip->legacy.waitfunc = fsl_elbc_wait; |
|---|
| 707 | + chip->legacy.set_features = nand_get_set_features_notsupp; |
|---|
| 708 | + chip->legacy.get_features = nand_get_set_features_notsupp; |
|---|
| 709 | + |
|---|
| 710 | + chip->bbt_td = &bbt_main_descr; |
|---|
| 711 | + chip->bbt_md = &bbt_mirror_descr; |
|---|
| 712 | + |
|---|
| 713 | + /* set up nand options */ |
|---|
| 714 | + chip->bbt_options = NAND_BBT_USE_FLASH; |
|---|
| 715 | + |
|---|
| 716 | + chip->controller = &elbc_fcm_ctrl->controller; |
|---|
| 717 | + nand_set_controller_data(chip, priv); |
|---|
| 718 | + |
|---|
| 719 | + return 0; |
|---|
| 720 | +} |
|---|
| 721 | + |
|---|
| 640 | 722 | static int fsl_elbc_attach_chip(struct nand_chip *chip) |
|---|
| 641 | 723 | { |
|---|
| 642 | 724 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| .. | .. |
|---|
| 644 | 726 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
|---|
| 645 | 727 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
|---|
| 646 | 728 | unsigned int al; |
|---|
| 729 | + |
|---|
| 730 | + /* |
|---|
| 731 | + * if ECC was not chosen in DT, decide whether to use HW or SW ECC from |
|---|
| 732 | + * CS Base Register |
|---|
| 733 | + */ |
|---|
| 734 | + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) { |
|---|
| 735 | + /* If CS Base Register selects full hardware ECC then use it */ |
|---|
| 736 | + if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == |
|---|
| 737 | + BR_DECC_CHK_GEN) { |
|---|
| 738 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
|---|
| 739 | + } else { |
|---|
| 740 | + /* otherwise fall back to default software ECC */ |
|---|
| 741 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; |
|---|
| 742 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; |
|---|
| 743 | + } |
|---|
| 744 | + } |
|---|
| 745 | + |
|---|
| 746 | + switch (chip->ecc.engine_type) { |
|---|
| 747 | + /* if HW ECC was chosen, setup ecc and oob layout */ |
|---|
| 748 | + case NAND_ECC_ENGINE_TYPE_ON_HOST: |
|---|
| 749 | + chip->ecc.read_page = fsl_elbc_read_page; |
|---|
| 750 | + chip->ecc.write_page = fsl_elbc_write_page; |
|---|
| 751 | + chip->ecc.write_subpage = fsl_elbc_write_subpage; |
|---|
| 752 | + mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); |
|---|
| 753 | + chip->ecc.size = 512; |
|---|
| 754 | + chip->ecc.bytes = 3; |
|---|
| 755 | + chip->ecc.strength = 1; |
|---|
| 756 | + break; |
|---|
| 757 | + |
|---|
| 758 | + /* if none or SW ECC was chosen, we do not need to set anything here */ |
|---|
| 759 | + case NAND_ECC_ENGINE_TYPE_NONE: |
|---|
| 760 | + case NAND_ECC_ENGINE_TYPE_SOFT: |
|---|
| 761 | + case NAND_ECC_ENGINE_TYPE_ON_DIE: |
|---|
| 762 | + break; |
|---|
| 763 | + |
|---|
| 764 | + default: |
|---|
| 765 | + return -EINVAL; |
|---|
| 766 | + } |
|---|
| 647 | 767 | |
|---|
| 648 | 768 | /* calculate FMR Address Length field */ |
|---|
| 649 | 769 | al = 0; |
|---|
| .. | .. |
|---|
| 655 | 775 | priv->fmr |= al << FMR_AL_SHIFT; |
|---|
| 656 | 776 | |
|---|
| 657 | 777 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", |
|---|
| 658 | | - chip->numchips); |
|---|
| 778 | + nanddev_ntargets(&chip->base)); |
|---|
| 659 | 779 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", |
|---|
| 660 | | - chip->chipsize); |
|---|
| 780 | + nanddev_target_size(&chip->base)); |
|---|
| 661 | 781 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", |
|---|
| 662 | 782 | chip->pagemask); |
|---|
| 663 | | - dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n", |
|---|
| 664 | | - chip->chip_delay); |
|---|
| 783 | + dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n", |
|---|
| 784 | + chip->legacy.chip_delay); |
|---|
| 665 | 785 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", |
|---|
| 666 | 786 | chip->badblockpos); |
|---|
| 667 | 787 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", |
|---|
| .. | .. |
|---|
| 670 | 790 | chip->page_shift); |
|---|
| 671 | 791 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", |
|---|
| 672 | 792 | chip->phys_erase_shift); |
|---|
| 673 | | - dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", |
|---|
| 674 | | - chip->ecc.mode); |
|---|
| 793 | + dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.engine_type = %d\n", |
|---|
| 794 | + chip->ecc.engine_type); |
|---|
| 675 | 795 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", |
|---|
| 676 | 796 | chip->ecc.steps); |
|---|
| 677 | 797 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", |
|---|
| .. | .. |
|---|
| 709 | 829 | static const struct nand_controller_ops fsl_elbc_controller_ops = { |
|---|
| 710 | 830 | .attach_chip = fsl_elbc_attach_chip, |
|---|
| 711 | 831 | }; |
|---|
| 712 | | - |
|---|
| 713 | | -static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 714 | | - uint8_t *buf, int oob_required, int page) |
|---|
| 715 | | -{ |
|---|
| 716 | | - struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
|---|
| 717 | | - struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
|---|
| 718 | | - struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
|---|
| 719 | | - |
|---|
| 720 | | - nand_read_page_op(chip, page, 0, buf, mtd->writesize); |
|---|
| 721 | | - if (oob_required) |
|---|
| 722 | | - fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); |
|---|
| 723 | | - |
|---|
| 724 | | - if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) |
|---|
| 725 | | - mtd->ecc_stats.failed++; |
|---|
| 726 | | - |
|---|
| 727 | | - return elbc_fcm_ctrl->max_bitflips; |
|---|
| 728 | | -} |
|---|
| 729 | | - |
|---|
| 730 | | -/* ECC will be calculated automatically, and errors will be detected in |
|---|
| 731 | | - * waitfunc. |
|---|
| 732 | | - */ |
|---|
| 733 | | -static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 734 | | - const uint8_t *buf, int oob_required, int page) |
|---|
| 735 | | -{ |
|---|
| 736 | | - nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); |
|---|
| 737 | | - fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
|---|
| 738 | | - |
|---|
| 739 | | - return nand_prog_page_end_op(chip); |
|---|
| 740 | | -} |
|---|
| 741 | | - |
|---|
| 742 | | -/* ECC will be calculated automatically, and errors will be detected in |
|---|
| 743 | | - * waitfunc. |
|---|
| 744 | | - */ |
|---|
| 745 | | -static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 746 | | - uint32_t offset, uint32_t data_len, |
|---|
| 747 | | - const uint8_t *buf, int oob_required, int page) |
|---|
| 748 | | -{ |
|---|
| 749 | | - nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
|---|
| 750 | | - fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
|---|
| 751 | | - fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
|---|
| 752 | | - return nand_prog_page_end_op(chip); |
|---|
| 753 | | -} |
|---|
| 754 | | - |
|---|
| 755 | | -static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
|---|
| 756 | | -{ |
|---|
| 757 | | - struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
|---|
| 758 | | - struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
|---|
| 759 | | - struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
|---|
| 760 | | - struct nand_chip *chip = &priv->chip; |
|---|
| 761 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 762 | | - |
|---|
| 763 | | - dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); |
|---|
| 764 | | - |
|---|
| 765 | | - /* Fill in fsl_elbc_mtd structure */ |
|---|
| 766 | | - mtd->dev.parent = priv->dev; |
|---|
| 767 | | - nand_set_flash_node(chip, priv->dev->of_node); |
|---|
| 768 | | - |
|---|
| 769 | | - /* set timeout to maximum */ |
|---|
| 770 | | - priv->fmr = 15 << FMR_CWTO_SHIFT; |
|---|
| 771 | | - if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS) |
|---|
| 772 | | - priv->fmr |= FMR_ECCM; |
|---|
| 773 | | - |
|---|
| 774 | | - /* fill in nand_chip structure */ |
|---|
| 775 | | - /* set up function call table */ |
|---|
| 776 | | - chip->read_byte = fsl_elbc_read_byte; |
|---|
| 777 | | - chip->write_buf = fsl_elbc_write_buf; |
|---|
| 778 | | - chip->read_buf = fsl_elbc_read_buf; |
|---|
| 779 | | - chip->select_chip = fsl_elbc_select_chip; |
|---|
| 780 | | - chip->cmdfunc = fsl_elbc_cmdfunc; |
|---|
| 781 | | - chip->waitfunc = fsl_elbc_wait; |
|---|
| 782 | | - chip->set_features = nand_get_set_features_notsupp; |
|---|
| 783 | | - chip->get_features = nand_get_set_features_notsupp; |
|---|
| 784 | | - |
|---|
| 785 | | - chip->bbt_td = &bbt_main_descr; |
|---|
| 786 | | - chip->bbt_md = &bbt_mirror_descr; |
|---|
| 787 | | - |
|---|
| 788 | | - /* set up nand options */ |
|---|
| 789 | | - chip->bbt_options = NAND_BBT_USE_FLASH; |
|---|
| 790 | | - |
|---|
| 791 | | - chip->controller = &elbc_fcm_ctrl->controller; |
|---|
| 792 | | - nand_set_controller_data(chip, priv); |
|---|
| 793 | | - |
|---|
| 794 | | - chip->ecc.read_page = fsl_elbc_read_page; |
|---|
| 795 | | - chip->ecc.write_page = fsl_elbc_write_page; |
|---|
| 796 | | - chip->ecc.write_subpage = fsl_elbc_write_subpage; |
|---|
| 797 | | - |
|---|
| 798 | | - /* If CS Base Register selects full hardware ECC then use it */ |
|---|
| 799 | | - if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == |
|---|
| 800 | | - BR_DECC_CHK_GEN) { |
|---|
| 801 | | - chip->ecc.mode = NAND_ECC_HW; |
|---|
| 802 | | - mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); |
|---|
| 803 | | - chip->ecc.size = 512; |
|---|
| 804 | | - chip->ecc.bytes = 3; |
|---|
| 805 | | - chip->ecc.strength = 1; |
|---|
| 806 | | - } else { |
|---|
| 807 | | - /* otherwise fall back to default software ECC */ |
|---|
| 808 | | - chip->ecc.mode = NAND_ECC_SOFT; |
|---|
| 809 | | - chip->ecc.algo = NAND_ECC_HAMMING; |
|---|
| 810 | | - } |
|---|
| 811 | | - |
|---|
| 812 | | - return 0; |
|---|
| 813 | | -} |
|---|
| 814 | 832 | |
|---|
| 815 | 833 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) |
|---|
| 816 | 834 | { |
|---|
| .. | .. |
|---|
| 942 | 960 | { |
|---|
| 943 | 961 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; |
|---|
| 944 | 962 | struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev); |
|---|
| 963 | + struct nand_chip *chip = &priv->chip; |
|---|
| 964 | + int ret; |
|---|
| 945 | 965 | |
|---|
| 946 | | - nand_release(&priv->chip); |
|---|
| 966 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
|---|
| 967 | + WARN_ON(ret); |
|---|
| 968 | + nand_cleanup(chip); |
|---|
| 969 | + |
|---|
| 947 | 970 | fsl_elbc_chip_remove(priv); |
|---|
| 948 | 971 | |
|---|
| 949 | 972 | mutex_lock(&fsl_elbc_nand_mutex); |
|---|