diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-07-25 09:31:47 -0400 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-07-31 03:46:12 -0400 |
commit | 176fc2f28ee5ebd494c39d25dda3e0a71e0b649a (patch) | |
tree | 3a0e20dc2262ec02e44b55fc245e3fabcc48244b | |
parent | ccadc14975c9bbd17da3a4b0b443325a5bda0ba2 (diff) |
mtd: rawnand: tegra: convert driver to nand_scan()
Two helpers have been added to the core to do all kind of controller
side configuration/initialization between the detection phase and the
final NAND scan. Implement these hooks so that we can convert the driver
to just use nand_scan() instead of the nand_scan_ident() +
nand_scan_tail() pair.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r-- | drivers/mtd/nand/raw/tegra_nand.c | 162 |
1 files changed, 88 insertions, 74 deletions
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c index 31c0d9ca9d23..79da1efc88d1 100644 --- a/drivers/mtd/nand/raw/tegra_nand.c +++ b/drivers/mtd/nand/raw/tegra_nand.c | |||
@@ -906,74 +906,13 @@ static int tegra_nand_select_strength(struct nand_chip *chip, int oobsize) | |||
906 | bits_per_step, oobsize); | 906 | bits_per_step, oobsize); |
907 | } | 907 | } |
908 | 908 | ||
909 | static int tegra_nand_chips_init(struct device *dev, | 909 | static int tegra_nand_attach_chip(struct nand_chip *chip) |
910 | struct tegra_nand_controller *ctrl) | ||
911 | { | 910 | { |
912 | struct device_node *np = dev->of_node; | 911 | struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller); |
913 | struct device_node *np_nand; | 912 | struct tegra_nand_chip *nand = to_tegra_chip(chip); |
914 | int nsels, nchips = of_get_child_count(np); | 913 | struct mtd_info *mtd = nand_to_mtd(chip); |
915 | struct tegra_nand_chip *nand; | ||
916 | struct mtd_info *mtd; | ||
917 | struct nand_chip *chip; | ||
918 | int bits_per_step; | 914 | int bits_per_step; |
919 | int ret; | 915 | int ret; |
920 | u32 cs; | ||
921 | |||
922 | if (nchips != 1) { | ||
923 | dev_err(dev, "Currently only one NAND chip supported\n"); | ||
924 | return -EINVAL; | ||
925 | } | ||
926 | |||
927 | np_nand = of_get_next_child(np, NULL); | ||
928 | |||
929 | nsels = of_property_count_elems_of_size(np_nand, "reg", sizeof(u32)); | ||
930 | if (nsels != 1) { | ||
931 | dev_err(dev, "Missing/invalid reg property\n"); | ||
932 | return -EINVAL; | ||
933 | } | ||
934 | |||
935 | /* Retrieve CS id, currently only single die NAND supported */ | ||
936 | ret = of_property_read_u32(np_nand, "reg", &cs); | ||
937 | if (ret) { | ||
938 | dev_err(dev, "could not retrieve reg property: %d\n", ret); | ||
939 | return ret; | ||
940 | } | ||
941 | |||
942 | nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); | ||
943 | if (!nand) | ||
944 | return -ENOMEM; | ||
945 | |||
946 | nand->cs[0] = cs; | ||
947 | |||
948 | nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); | ||
949 | |||
950 | if (IS_ERR(nand->wp_gpio)) { | ||
951 | ret = PTR_ERR(nand->wp_gpio); | ||
952 | dev_err(dev, "Failed to request WP GPIO: %d\n", ret); | ||
953 | return ret; | ||
954 | } | ||
955 | |||
956 | chip = &nand->chip; | ||
957 | chip->controller = &ctrl->controller; | ||
958 | |||
959 | mtd = nand_to_mtd(chip); | ||
960 | |||
961 | mtd->dev.parent = dev; | ||
962 | mtd->owner = THIS_MODULE; | ||
963 | |||
964 | nand_set_flash_node(chip, np_nand); | ||
965 | |||
966 | if (!mtd->name) | ||
967 | mtd->name = "tegra_nand"; | ||
968 | |||
969 | chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER; | ||
970 | chip->exec_op = tegra_nand_exec_op; | ||
971 | chip->select_chip = tegra_nand_select_chip; | ||
972 | chip->setup_data_interface = tegra_nand_setup_data_interface; | ||
973 | |||
974 | ret = nand_scan_ident(mtd, 1, NULL); | ||
975 | if (ret) | ||
976 | return ret; | ||
977 | 916 | ||
978 | if (chip->bbt_options & NAND_BBT_USE_FLASH) | 917 | if (chip->bbt_options & NAND_BBT_USE_FLASH) |
979 | chip->bbt_options |= NAND_BBT_NO_OOB; | 918 | chip->bbt_options |= NAND_BBT_NO_OOB; |
@@ -982,7 +921,8 @@ static int tegra_nand_chips_init(struct device *dev, | |||
982 | chip->ecc.size = 512; | 921 | chip->ecc.size = 512; |
983 | chip->ecc.steps = mtd->writesize / chip->ecc.size; | 922 | chip->ecc.steps = mtd->writesize / chip->ecc.size; |
984 | if (chip->ecc_step_ds != 512) { | 923 | if (chip->ecc_step_ds != 512) { |
985 | dev_err(dev, "Unsupported step size %d\n", chip->ecc_step_ds); | 924 | dev_err(ctrl->dev, "Unsupported step size %d\n", |
925 | chip->ecc_step_ds); | ||
986 | return -EINVAL; | 926 | return -EINVAL; |
987 | } | 927 | } |
988 | 928 | ||
@@ -1004,14 +944,15 @@ static int tegra_nand_chips_init(struct device *dev, | |||
1004 | } | 944 | } |
1005 | 945 | ||
1006 | if (chip->ecc.algo == NAND_ECC_BCH && mtd->writesize < 2048) { | 946 | if (chip->ecc.algo == NAND_ECC_BCH && mtd->writesize < 2048) { |
1007 | dev_err(dev, "BCH supports 2K or 4K page size only\n"); | 947 | dev_err(ctrl->dev, "BCH supports 2K or 4K page size only\n"); |
1008 | return -EINVAL; | 948 | return -EINVAL; |
1009 | } | 949 | } |
1010 | 950 | ||
1011 | if (!chip->ecc.strength) { | 951 | if (!chip->ecc.strength) { |
1012 | ret = tegra_nand_select_strength(chip, mtd->oobsize); | 952 | ret = tegra_nand_select_strength(chip, mtd->oobsize); |
1013 | if (ret < 0) { | 953 | if (ret < 0) { |
1014 | dev_err(dev, "No valid strength found, minimum %d\n", | 954 | dev_err(ctrl->dev, |
955 | "No valid strength found, minimum %d\n", | ||
1015 | chip->ecc_strength_ds); | 956 | chip->ecc_strength_ds); |
1016 | return ret; | 957 | return ret; |
1017 | } | 958 | } |
@@ -1039,7 +980,7 @@ static int tegra_nand_chips_init(struct device *dev, | |||
1039 | nand->config_ecc |= CONFIG_TVAL_8; | 980 | nand->config_ecc |= CONFIG_TVAL_8; |
1040 | break; | 981 | break; |
1041 | default: | 982 | default: |
1042 | dev_err(dev, "ECC strength %d not supported\n", | 983 | dev_err(ctrl->dev, "ECC strength %d not supported\n", |
1043 | chip->ecc.strength); | 984 | chip->ecc.strength); |
1044 | return -EINVAL; | 985 | return -EINVAL; |
1045 | } | 986 | } |
@@ -1062,17 +1003,17 @@ static int tegra_nand_chips_init(struct device *dev, | |||
1062 | nand->bch_config |= BCH_TVAL_16; | 1003 | nand->bch_config |= BCH_TVAL_16; |
1063 | break; | 1004 | break; |
1064 | default: | 1005 | default: |
1065 | dev_err(dev, "ECC strength %d not supported\n", | 1006 | dev_err(ctrl->dev, "ECC strength %d not supported\n", |
1066 | chip->ecc.strength); | 1007 | chip->ecc.strength); |
1067 | return -EINVAL; | 1008 | return -EINVAL; |
1068 | } | 1009 | } |
1069 | break; | 1010 | break; |
1070 | default: | 1011 | default: |
1071 | dev_err(dev, "ECC algorithm not supported\n"); | 1012 | dev_err(ctrl->dev, "ECC algorithm not supported\n"); |
1072 | return -EINVAL; | 1013 | return -EINVAL; |
1073 | } | 1014 | } |
1074 | 1015 | ||
1075 | dev_info(dev, "Using %s with strength %d per 512 byte step\n", | 1016 | dev_info(ctrl->dev, "Using %s with strength %d per 512 byte step\n", |
1076 | chip->ecc.algo == NAND_ECC_BCH ? "BCH" : "RS", | 1017 | chip->ecc.algo == NAND_ECC_BCH ? "BCH" : "RS", |
1077 | chip->ecc.strength); | 1018 | chip->ecc.strength); |
1078 | 1019 | ||
@@ -1095,7 +1036,8 @@ static int tegra_nand_chips_init(struct device *dev, | |||
1095 | nand->config |= CONFIG_PS_4096; | 1036 | nand->config |= CONFIG_PS_4096; |
1096 | break; | 1037 | break; |
1097 | default: | 1038 | default: |
1098 | dev_err(dev, "Unsupported writesize %d\n", mtd->writesize); | 1039 | dev_err(ctrl->dev, "Unsupported writesize %d\n", |
1040 | mtd->writesize); | ||
1099 | return -ENODEV; | 1041 | return -ENODEV; |
1100 | } | 1042 | } |
1101 | 1043 | ||
@@ -1106,7 +1048,78 @@ static int tegra_nand_chips_init(struct device *dev, | |||
1106 | nand->config |= CONFIG_TAG_BYTE_SIZE(mtd->oobsize - 1); | 1048 | nand->config |= CONFIG_TAG_BYTE_SIZE(mtd->oobsize - 1); |
1107 | writel_relaxed(nand->config, ctrl->regs + CONFIG); | 1049 | writel_relaxed(nand->config, ctrl->regs + CONFIG); |
1108 | 1050 | ||
1109 | ret = nand_scan_tail(mtd); | 1051 | return 0; |
1052 | } | ||
1053 | |||
1054 | static const struct nand_controller_ops tegra_nand_controller_ops = { | ||
1055 | .attach_chip = &tegra_nand_attach_chip, | ||
1056 | }; | ||
1057 | |||
1058 | static int tegra_nand_chips_init(struct device *dev, | ||
1059 | struct tegra_nand_controller *ctrl) | ||
1060 | { | ||
1061 | struct device_node *np = dev->of_node; | ||
1062 | struct device_node *np_nand; | ||
1063 | int nsels, nchips = of_get_child_count(np); | ||
1064 | struct tegra_nand_chip *nand; | ||
1065 | struct mtd_info *mtd; | ||
1066 | struct nand_chip *chip; | ||
1067 | int ret; | ||
1068 | u32 cs; | ||
1069 | |||
1070 | if (nchips != 1) { | ||
1071 | dev_err(dev, "Currently only one NAND chip supported\n"); | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1074 | |||
1075 | np_nand = of_get_next_child(np, NULL); | ||
1076 | |||
1077 | nsels = of_property_count_elems_of_size(np_nand, "reg", sizeof(u32)); | ||
1078 | if (nsels != 1) { | ||
1079 | dev_err(dev, "Missing/invalid reg property\n"); | ||
1080 | return -EINVAL; | ||
1081 | } | ||
1082 | |||
1083 | /* Retrieve CS id, currently only single die NAND supported */ | ||
1084 | ret = of_property_read_u32(np_nand, "reg", &cs); | ||
1085 | if (ret) { | ||
1086 | dev_err(dev, "could not retrieve reg property: %d\n", ret); | ||
1087 | return ret; | ||
1088 | } | ||
1089 | |||
1090 | nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); | ||
1091 | if (!nand) | ||
1092 | return -ENOMEM; | ||
1093 | |||
1094 | nand->cs[0] = cs; | ||
1095 | |||
1096 | nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); | ||
1097 | |||
1098 | if (IS_ERR(nand->wp_gpio)) { | ||
1099 | ret = PTR_ERR(nand->wp_gpio); | ||
1100 | dev_err(dev, "Failed to request WP GPIO: %d\n", ret); | ||
1101 | return ret; | ||
1102 | } | ||
1103 | |||
1104 | chip = &nand->chip; | ||
1105 | chip->controller = &ctrl->controller; | ||
1106 | |||
1107 | mtd = nand_to_mtd(chip); | ||
1108 | |||
1109 | mtd->dev.parent = dev; | ||
1110 | mtd->owner = THIS_MODULE; | ||
1111 | |||
1112 | nand_set_flash_node(chip, np_nand); | ||
1113 | |||
1114 | if (!mtd->name) | ||
1115 | mtd->name = "tegra_nand"; | ||
1116 | |||
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; | ||
1121 | |||
1122 | ret = nand_scan(mtd, 1); | ||
1110 | if (ret) | 1123 | if (ret) |
1111 | return ret; | 1124 | return ret; |
1112 | 1125 | ||
@@ -1137,6 +1150,7 @@ static int tegra_nand_probe(struct platform_device *pdev) | |||
1137 | 1150 | ||
1138 | ctrl->dev = &pdev->dev; | 1151 | ctrl->dev = &pdev->dev; |
1139 | nand_controller_init(&ctrl->controller); | 1152 | nand_controller_init(&ctrl->controller); |
1153 | ctrl->controller.ops = &tegra_nand_controller_ops; | ||
1140 | 1154 | ||
1141 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1155 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1142 | ctrl->regs = devm_ioremap_resource(&pdev->dev, res); | 1156 | ctrl->regs = devm_ioremap_resource(&pdev->dev, res); |