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