| .. | .. |
|---|
| 454 | 454 | NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 4)), |
|---|
| 455 | 455 | ); |
|---|
| 456 | 456 | |
|---|
| 457 | +static void tegra_nand_select_target(struct nand_chip *chip, |
|---|
| 458 | + unsigned int die_nr) |
|---|
| 459 | +{ |
|---|
| 460 | + struct tegra_nand_chip *nand = to_tegra_chip(chip); |
|---|
| 461 | + struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
|---|
| 462 | + |
|---|
| 463 | + ctrl->cur_cs = nand->cs[die_nr]; |
|---|
| 464 | +} |
|---|
| 465 | + |
|---|
| 457 | 466 | static int tegra_nand_exec_op(struct nand_chip *chip, |
|---|
| 458 | 467 | const struct nand_operation *op, |
|---|
| 459 | 468 | bool check_only) |
|---|
| 460 | 469 | { |
|---|
| 470 | + if (!check_only) |
|---|
| 471 | + tegra_nand_select_target(chip, op->cs); |
|---|
| 472 | + |
|---|
| 461 | 473 | return nand_op_parser_exec_op(chip, &tegra_nand_op_parser, op, |
|---|
| 462 | 474 | check_only); |
|---|
| 463 | | -} |
|---|
| 464 | | - |
|---|
| 465 | | -static void tegra_nand_select_chip(struct mtd_info *mtd, int die_nr) |
|---|
| 466 | | -{ |
|---|
| 467 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 468 | | - struct tegra_nand_chip *nand = to_tegra_chip(chip); |
|---|
| 469 | | - struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
|---|
| 470 | | - |
|---|
| 471 | | - WARN_ON(die_nr >= (int)ARRAY_SIZE(nand->cs)); |
|---|
| 472 | | - |
|---|
| 473 | | - if (die_nr < 0 || die_nr > 0) { |
|---|
| 474 | | - ctrl->cur_cs = -1; |
|---|
| 475 | | - return; |
|---|
| 476 | | - } |
|---|
| 477 | | - |
|---|
| 478 | | - ctrl->cur_cs = nand->cs[die_nr]; |
|---|
| 479 | 475 | } |
|---|
| 480 | 476 | |
|---|
| 481 | 477 | static void tegra_nand_hw_ecc(struct tegra_nand_controller *ctrl, |
|---|
| .. | .. |
|---|
| 483 | 479 | { |
|---|
| 484 | 480 | struct tegra_nand_chip *nand = to_tegra_chip(chip); |
|---|
| 485 | 481 | |
|---|
| 486 | | - if (chip->ecc.algo == NAND_ECC_BCH && enable) |
|---|
| 482 | + if (chip->ecc.algo == NAND_ECC_ALGO_BCH && enable) |
|---|
| 487 | 483 | writel_relaxed(nand->bch_config, ctrl->regs + BCH_CONFIG); |
|---|
| 488 | 484 | else |
|---|
| 489 | 485 | writel_relaxed(0, ctrl->regs + BCH_CONFIG); |
|---|
| .. | .. |
|---|
| 503 | 499 | dma_addr_t dma_addr = 0, dma_addr_oob = 0; |
|---|
| 504 | 500 | u32 addr1, cmd, dma_ctrl; |
|---|
| 505 | 501 | int ret; |
|---|
| 502 | + |
|---|
| 503 | + tegra_nand_select_target(chip, chip->cur_cs); |
|---|
| 506 | 504 | |
|---|
| 507 | 505 | if (read) { |
|---|
| 508 | 506 | writel_relaxed(NAND_CMD_READ0, ctrl->regs + CMD_REG1); |
|---|
| .. | .. |
|---|
| 615 | 613 | return ret; |
|---|
| 616 | 614 | } |
|---|
| 617 | 615 | |
|---|
| 618 | | -static int tegra_nand_read_page_raw(struct mtd_info *mtd, |
|---|
| 619 | | - struct nand_chip *chip, u8 *buf, |
|---|
| 616 | +static int tegra_nand_read_page_raw(struct nand_chip *chip, u8 *buf, |
|---|
| 620 | 617 | int oob_required, int page) |
|---|
| 621 | 618 | { |
|---|
| 619 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 622 | 620 | void *oob_buf = oob_required ? chip->oob_poi : NULL; |
|---|
| 623 | 621 | |
|---|
| 624 | 622 | return tegra_nand_page_xfer(mtd, chip, buf, oob_buf, |
|---|
| 625 | 623 | mtd->oobsize, page, true); |
|---|
| 626 | 624 | } |
|---|
| 627 | 625 | |
|---|
| 628 | | -static int tegra_nand_write_page_raw(struct mtd_info *mtd, |
|---|
| 629 | | - struct nand_chip *chip, const u8 *buf, |
|---|
| 626 | +static int tegra_nand_write_page_raw(struct nand_chip *chip, const u8 *buf, |
|---|
| 630 | 627 | int oob_required, int page) |
|---|
| 631 | 628 | { |
|---|
| 629 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 632 | 630 | void *oob_buf = oob_required ? chip->oob_poi : NULL; |
|---|
| 633 | 631 | |
|---|
| 634 | 632 | return tegra_nand_page_xfer(mtd, chip, (void *)buf, oob_buf, |
|---|
| 635 | 633 | mtd->oobsize, page, false); |
|---|
| 636 | 634 | } |
|---|
| 637 | 635 | |
|---|
| 638 | | -static int tegra_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 639 | | - int page) |
|---|
| 636 | +static int tegra_nand_read_oob(struct nand_chip *chip, int page) |
|---|
| 640 | 637 | { |
|---|
| 638 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 639 | + |
|---|
| 641 | 640 | return tegra_nand_page_xfer(mtd, chip, NULL, chip->oob_poi, |
|---|
| 642 | 641 | mtd->oobsize, page, true); |
|---|
| 643 | 642 | } |
|---|
| 644 | 643 | |
|---|
| 645 | | -static int tegra_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 646 | | - int page) |
|---|
| 644 | +static int tegra_nand_write_oob(struct nand_chip *chip, int page) |
|---|
| 647 | 645 | { |
|---|
| 646 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 647 | + |
|---|
| 648 | 648 | return tegra_nand_page_xfer(mtd, chip, NULL, chip->oob_poi, |
|---|
| 649 | 649 | mtd->oobsize, page, false); |
|---|
| 650 | 650 | } |
|---|
| 651 | 651 | |
|---|
| 652 | | -static int tegra_nand_read_page_hwecc(struct mtd_info *mtd, |
|---|
| 653 | | - struct nand_chip *chip, u8 *buf, |
|---|
| 652 | +static int tegra_nand_read_page_hwecc(struct nand_chip *chip, u8 *buf, |
|---|
| 654 | 653 | int oob_required, int page) |
|---|
| 655 | 654 | { |
|---|
| 655 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 656 | 656 | struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
|---|
| 657 | 657 | struct tegra_nand_chip *nand = to_tegra_chip(chip); |
|---|
| 658 | 658 | void *oob_buf = oob_required ? chip->oob_poi : NULL; |
|---|
| .. | .. |
|---|
| 716 | 716 | * erased or if error correction just failed for all sub- |
|---|
| 717 | 717 | * pages. |
|---|
| 718 | 718 | */ |
|---|
| 719 | | - ret = tegra_nand_read_oob(mtd, chip, page); |
|---|
| 719 | + ret = tegra_nand_read_oob(chip, page); |
|---|
| 720 | 720 | if (ret < 0) |
|---|
| 721 | 721 | return ret; |
|---|
| 722 | 722 | |
|---|
| .. | .. |
|---|
| 759 | 759 | } |
|---|
| 760 | 760 | } |
|---|
| 761 | 761 | |
|---|
| 762 | | -static int tegra_nand_write_page_hwecc(struct mtd_info *mtd, |
|---|
| 763 | | - struct nand_chip *chip, const u8 *buf, |
|---|
| 762 | +static int tegra_nand_write_page_hwecc(struct nand_chip *chip, const u8 *buf, |
|---|
| 764 | 763 | int oob_required, int page) |
|---|
| 765 | 764 | { |
|---|
| 765 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 766 | 766 | struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
|---|
| 767 | 767 | void *oob_buf = oob_required ? chip->oob_poi : NULL; |
|---|
| 768 | 768 | int ret; |
|---|
| .. | .. |
|---|
| 813 | 813 | writel_relaxed(reg, ctrl->regs + TIMING_2); |
|---|
| 814 | 814 | } |
|---|
| 815 | 815 | |
|---|
| 816 | | -static int tegra_nand_setup_data_interface(struct mtd_info *mtd, int csline, |
|---|
| 817 | | - const struct nand_data_interface *conf) |
|---|
| 816 | +static int tegra_nand_setup_interface(struct nand_chip *chip, int csline, |
|---|
| 817 | + const struct nand_interface_config *conf) |
|---|
| 818 | 818 | { |
|---|
| 819 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 820 | 819 | struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
|---|
| 821 | 820 | const struct nand_sdr_timings *timings; |
|---|
| 822 | 821 | |
|---|
| .. | .. |
|---|
| 841 | 840 | int strength_len, int bits_per_step, |
|---|
| 842 | 841 | int oobsize) |
|---|
| 843 | 842 | { |
|---|
| 844 | | - bool maximize = chip->ecc.options & NAND_ECC_MAXIMIZE; |
|---|
| 843 | + struct nand_device *base = mtd_to_nanddev(nand_to_mtd(chip)); |
|---|
| 844 | + const struct nand_ecc_props *requirements = |
|---|
| 845 | + nanddev_get_ecc_requirements(base); |
|---|
| 846 | + bool maximize = base->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH; |
|---|
| 845 | 847 | int i; |
|---|
| 846 | 848 | |
|---|
| 847 | 849 | /* |
|---|
| .. | .. |
|---|
| 856 | 858 | } else { |
|---|
| 857 | 859 | strength_sel = strength[i]; |
|---|
| 858 | 860 | |
|---|
| 859 | | - if (strength_sel < chip->ecc_strength_ds) |
|---|
| 861 | + if (strength_sel < requirements->strength) |
|---|
| 860 | 862 | continue; |
|---|
| 861 | 863 | } |
|---|
| 862 | 864 | |
|---|
| .. | .. |
|---|
| 878 | 880 | int strength_len, bits_per_step; |
|---|
| 879 | 881 | |
|---|
| 880 | 882 | switch (chip->ecc.algo) { |
|---|
| 881 | | - case NAND_ECC_RS: |
|---|
| 883 | + case NAND_ECC_ALGO_RS: |
|---|
| 882 | 884 | bits_per_step = BITS_PER_STEP_RS; |
|---|
| 883 | 885 | if (chip->options & NAND_IS_BOOT_MEDIUM) { |
|---|
| 884 | 886 | strength = rs_strength_bootable; |
|---|
| .. | .. |
|---|
| 888 | 890 | strength_len = ARRAY_SIZE(rs_strength); |
|---|
| 889 | 891 | } |
|---|
| 890 | 892 | break; |
|---|
| 891 | | - case NAND_ECC_BCH: |
|---|
| 893 | + case NAND_ECC_ALGO_BCH: |
|---|
| 892 | 894 | bits_per_step = BITS_PER_STEP_BCH; |
|---|
| 893 | 895 | if (chip->options & NAND_IS_BOOT_MEDIUM) { |
|---|
| 894 | 896 | strength = bch_strength_bootable; |
|---|
| .. | .. |
|---|
| 909 | 911 | static int tegra_nand_attach_chip(struct nand_chip *chip) |
|---|
| 910 | 912 | { |
|---|
| 911 | 913 | struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
|---|
| 914 | + const struct nand_ecc_props *requirements = |
|---|
| 915 | + nanddev_get_ecc_requirements(&chip->base); |
|---|
| 912 | 916 | struct tegra_nand_chip *nand = to_tegra_chip(chip); |
|---|
| 913 | 917 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 914 | 918 | int bits_per_step; |
|---|
| .. | .. |
|---|
| 917 | 921 | if (chip->bbt_options & NAND_BBT_USE_FLASH) |
|---|
| 918 | 922 | chip->bbt_options |= NAND_BBT_NO_OOB; |
|---|
| 919 | 923 | |
|---|
| 920 | | - chip->ecc.mode = NAND_ECC_HW; |
|---|
| 924 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
|---|
| 921 | 925 | chip->ecc.size = 512; |
|---|
| 922 | 926 | chip->ecc.steps = mtd->writesize / chip->ecc.size; |
|---|
| 923 | | - if (chip->ecc_step_ds != 512) { |
|---|
| 927 | + if (requirements->step_size != 512) { |
|---|
| 924 | 928 | dev_err(ctrl->dev, "Unsupported step size %d\n", |
|---|
| 925 | | - chip->ecc_step_ds); |
|---|
| 929 | + requirements->step_size); |
|---|
| 926 | 930 | return -EINVAL; |
|---|
| 927 | 931 | } |
|---|
| 928 | 932 | |
|---|
| .. | .. |
|---|
| 936 | 940 | if (chip->options & NAND_BUSWIDTH_16) |
|---|
| 937 | 941 | nand->config |= CONFIG_BUS_WIDTH_16; |
|---|
| 938 | 942 | |
|---|
| 939 | | - if (chip->ecc.algo == NAND_ECC_UNKNOWN) { |
|---|
| 943 | + if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) { |
|---|
| 940 | 944 | if (mtd->writesize < 2048) |
|---|
| 941 | | - chip->ecc.algo = NAND_ECC_RS; |
|---|
| 945 | + chip->ecc.algo = NAND_ECC_ALGO_RS; |
|---|
| 942 | 946 | else |
|---|
| 943 | | - chip->ecc.algo = NAND_ECC_BCH; |
|---|
| 947 | + chip->ecc.algo = NAND_ECC_ALGO_BCH; |
|---|
| 944 | 948 | } |
|---|
| 945 | 949 | |
|---|
| 946 | | - if (chip->ecc.algo == NAND_ECC_BCH && mtd->writesize < 2048) { |
|---|
| 950 | + if (chip->ecc.algo == NAND_ECC_ALGO_BCH && mtd->writesize < 2048) { |
|---|
| 947 | 951 | dev_err(ctrl->dev, "BCH supports 2K or 4K page size only\n"); |
|---|
| 948 | 952 | return -EINVAL; |
|---|
| 949 | 953 | } |
|---|
| .. | .. |
|---|
| 953 | 957 | if (ret < 0) { |
|---|
| 954 | 958 | dev_err(ctrl->dev, |
|---|
| 955 | 959 | "No valid strength found, minimum %d\n", |
|---|
| 956 | | - chip->ecc_strength_ds); |
|---|
| 960 | + requirements->strength); |
|---|
| 957 | 961 | return ret; |
|---|
| 958 | 962 | } |
|---|
| 959 | 963 | |
|---|
| .. | .. |
|---|
| 964 | 968 | CONFIG_SKIP_SPARE_SIZE_4; |
|---|
| 965 | 969 | |
|---|
| 966 | 970 | switch (chip->ecc.algo) { |
|---|
| 967 | | - case NAND_ECC_RS: |
|---|
| 971 | + case NAND_ECC_ALGO_RS: |
|---|
| 968 | 972 | bits_per_step = BITS_PER_STEP_RS * chip->ecc.strength; |
|---|
| 969 | 973 | mtd_set_ooblayout(mtd, &tegra_nand_oob_rs_ops); |
|---|
| 970 | 974 | nand->config_ecc |= CONFIG_HW_ECC | CONFIG_ECC_SEL | |
|---|
| .. | .. |
|---|
| 985 | 989 | return -EINVAL; |
|---|
| 986 | 990 | } |
|---|
| 987 | 991 | break; |
|---|
| 988 | | - case NAND_ECC_BCH: |
|---|
| 992 | + case NAND_ECC_ALGO_BCH: |
|---|
| 989 | 993 | bits_per_step = BITS_PER_STEP_BCH * chip->ecc.strength; |
|---|
| 990 | 994 | mtd_set_ooblayout(mtd, &tegra_nand_oob_bch_ops); |
|---|
| 991 | 995 | nand->bch_config = BCH_ENABLE; |
|---|
| .. | .. |
|---|
| 1014 | 1018 | } |
|---|
| 1015 | 1019 | |
|---|
| 1016 | 1020 | dev_info(ctrl->dev, "Using %s with strength %d per 512 byte step\n", |
|---|
| 1017 | | - chip->ecc.algo == NAND_ECC_BCH ? "BCH" : "RS", |
|---|
| 1021 | + chip->ecc.algo == NAND_ECC_ALGO_BCH ? "BCH" : "RS", |
|---|
| 1018 | 1022 | chip->ecc.strength); |
|---|
| 1019 | 1023 | |
|---|
| 1020 | 1024 | chip->ecc.bytes = DIV_ROUND_UP(bits_per_step, BITS_PER_BYTE); |
|---|
| .. | .. |
|---|
| 1053 | 1057 | |
|---|
| 1054 | 1058 | static const struct nand_controller_ops tegra_nand_controller_ops = { |
|---|
| 1055 | 1059 | .attach_chip = &tegra_nand_attach_chip, |
|---|
| 1060 | + .exec_op = tegra_nand_exec_op, |
|---|
| 1061 | + .setup_interface = tegra_nand_setup_interface, |
|---|
| 1056 | 1062 | }; |
|---|
| 1057 | 1063 | |
|---|
| 1058 | 1064 | static int tegra_nand_chips_init(struct device *dev, |
|---|
| .. | .. |
|---|
| 1114 | 1120 | if (!mtd->name) |
|---|
| 1115 | 1121 | mtd->name = "tegra_nand"; |
|---|
| 1116 | 1122 | |
|---|
| 1117 | | - chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER; |
|---|
| 1118 | | - chip->exec_op = tegra_nand_exec_op; |
|---|
| 1119 | | - chip->select_chip = tegra_nand_select_chip; |
|---|
| 1120 | | - chip->setup_data_interface = tegra_nand_setup_data_interface; |
|---|
| 1123 | + chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USES_DMA; |
|---|
| 1121 | 1124 | |
|---|
| 1122 | 1125 | ret = nand_scan(chip, 1); |
|---|
| 1123 | 1126 | if (ret) |
|---|