diff options
| -rw-r--r-- | MAINTAINERS | 15 | ||||
| -rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 6 | ||||
| -rw-r--r-- | drivers/mtd/nand/mtk_ecc.c | 19 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_base.c | 60 | ||||
| -rw-r--r-- | include/linux/mtd/nand.h | 2 |
5 files changed, 71 insertions, 31 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index ccae35bb3904..411e3b87b8c2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -7925,6 +7925,10 @@ F: mm/ | |||
| 7925 | MEMORY TECHNOLOGY DEVICES (MTD) | 7925 | MEMORY TECHNOLOGY DEVICES (MTD) |
| 7926 | M: David Woodhouse <dwmw2@infradead.org> | 7926 | M: David Woodhouse <dwmw2@infradead.org> |
| 7927 | M: Brian Norris <computersforpeace@gmail.com> | 7927 | M: Brian Norris <computersforpeace@gmail.com> |
| 7928 | M: Boris Brezillon <boris.brezillon@free-electrons.com> | ||
| 7929 | M: Marek Vasut <marek.vasut@gmail.com> | ||
| 7930 | M: Richard Weinberger <richard@nod.at> | ||
| 7931 | M: Cyrille Pitchen <cyrille.pitchen@atmel.com> | ||
| 7928 | L: linux-mtd@lists.infradead.org | 7932 | L: linux-mtd@lists.infradead.org |
| 7929 | W: http://www.linux-mtd.infradead.org/ | 7933 | W: http://www.linux-mtd.infradead.org/ |
| 7930 | Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ | 7934 | Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ |
| @@ -11404,6 +11408,17 @@ W: http://www.st.com/spear | |||
| 11404 | S: Maintained | 11408 | S: Maintained |
| 11405 | F: drivers/clk/spear/ | 11409 | F: drivers/clk/spear/ |
| 11406 | 11410 | ||
| 11411 | SPI NOR SUBSYSTEM | ||
| 11412 | M: Cyrille Pitchen <cyrille.pitchen@atmel.com> | ||
| 11413 | M: Marek Vasut <marek.vasut@gmail.com> | ||
| 11414 | L: linux-mtd@lists.infradead.org | ||
| 11415 | W: http://www.linux-mtd.infradead.org/ | ||
| 11416 | Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ | ||
| 11417 | T: git git://github.com/spi-nor/linux.git | ||
| 11418 | S: Maintained | ||
| 11419 | F: drivers/mtd/spi-nor/ | ||
| 11420 | F: include/linux/mtd/spi-nor.h | ||
| 11421 | |||
| 11407 | SPI SUBSYSTEM | 11422 | SPI SUBSYSTEM |
| 11408 | M: Mark Brown <broonie@kernel.org> | 11423 | M: Mark Brown <broonie@kernel.org> |
| 11409 | L: linux-spi@vger.kernel.org | 11424 | L: linux-spi@vger.kernel.org |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 0f68a99fc4ad..141bd70a49c2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c | |||
| @@ -161,7 +161,7 @@ int gpmi_init(struct gpmi_nand_data *this) | |||
| 161 | 161 | ||
| 162 | ret = gpmi_enable_clk(this); | 162 | ret = gpmi_enable_clk(this); |
| 163 | if (ret) | 163 | if (ret) |
| 164 | goto err_out; | 164 | return ret; |
| 165 | ret = gpmi_reset_block(r->gpmi_regs, false); | 165 | ret = gpmi_reset_block(r->gpmi_regs, false); |
| 166 | if (ret) | 166 | if (ret) |
| 167 | goto err_out; | 167 | goto err_out; |
| @@ -197,6 +197,7 @@ int gpmi_init(struct gpmi_nand_data *this) | |||
| 197 | gpmi_disable_clk(this); | 197 | gpmi_disable_clk(this); |
| 198 | return 0; | 198 | return 0; |
| 199 | err_out: | 199 | err_out: |
| 200 | gpmi_disable_clk(this); | ||
| 200 | return ret; | 201 | return ret; |
| 201 | } | 202 | } |
| 202 | 203 | ||
| @@ -270,7 +271,7 @@ int bch_set_geometry(struct gpmi_nand_data *this) | |||
| 270 | 271 | ||
| 271 | ret = gpmi_enable_clk(this); | 272 | ret = gpmi_enable_clk(this); |
| 272 | if (ret) | 273 | if (ret) |
| 273 | goto err_out; | 274 | return ret; |
| 274 | 275 | ||
| 275 | /* | 276 | /* |
| 276 | * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this | 277 | * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this |
| @@ -308,6 +309,7 @@ int bch_set_geometry(struct gpmi_nand_data *this) | |||
| 308 | gpmi_disable_clk(this); | 309 | gpmi_disable_clk(this); |
| 309 | return 0; | 310 | return 0; |
| 310 | err_out: | 311 | err_out: |
| 312 | gpmi_disable_clk(this); | ||
| 311 | return ret; | 313 | return ret; |
| 312 | } | 314 | } |
| 313 | 315 | ||
diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c index d54f666417e1..dbf256217b3e 100644 --- a/drivers/mtd/nand/mtk_ecc.c +++ b/drivers/mtd/nand/mtk_ecc.c | |||
| @@ -86,6 +86,8 @@ struct mtk_ecc { | |||
| 86 | struct completion done; | 86 | struct completion done; |
| 87 | struct mutex lock; | 87 | struct mutex lock; |
| 88 | u32 sectors; | 88 | u32 sectors; |
| 89 | |||
| 90 | u8 eccdata[112]; | ||
| 89 | }; | 91 | }; |
| 90 | 92 | ||
| 91 | static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, | 93 | static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, |
| @@ -366,9 +368,8 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, | |||
| 366 | u8 *data, u32 bytes) | 368 | u8 *data, u32 bytes) |
| 367 | { | 369 | { |
| 368 | dma_addr_t addr; | 370 | dma_addr_t addr; |
| 369 | u8 *p; | 371 | u32 len; |
| 370 | u32 len, i, val; | 372 | int ret; |
| 371 | int ret = 0; | ||
| 372 | 373 | ||
| 373 | addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE); | 374 | addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE); |
| 374 | ret = dma_mapping_error(ecc->dev, addr); | 375 | ret = dma_mapping_error(ecc->dev, addr); |
| @@ -393,14 +394,12 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config, | |||
| 393 | 394 | ||
| 394 | /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ | 395 | /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */ |
| 395 | len = (config->strength * ECC_PARITY_BITS + 7) >> 3; | 396 | len = (config->strength * ECC_PARITY_BITS + 7) >> 3; |
| 396 | p = data + bytes; | ||
| 397 | 397 | ||
| 398 | /* write the parity bytes generated by the ECC back to the OOB region */ | 398 | /* write the parity bytes generated by the ECC back to temp buffer */ |
| 399 | for (i = 0; i < len; i++) { | 399 | __ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, 4)); |
| 400 | if ((i % 4) == 0) | 400 | |
| 401 | val = readl(ecc->regs + ECC_ENCPAR(i / 4)); | 401 | /* copy into possibly unaligned OOB region with actual length */ |
| 402 | p[i] = (val >> ((i % 4) * 8)) & 0xff; | 402 | memcpy(data + bytes, ecc->eccdata, len); |
| 403 | } | ||
| 404 | timeout: | 403 | timeout: |
| 405 | 404 | ||
| 406 | dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); | 405 | dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e5718e5ecf92..3bde96a3f7bf 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -1095,10 +1095,11 @@ static void nand_release_data_interface(struct nand_chip *chip) | |||
| 1095 | /** | 1095 | /** |
| 1096 | * nand_reset - Reset and initialize a NAND device | 1096 | * nand_reset - Reset and initialize a NAND device |
| 1097 | * @chip: The NAND chip | 1097 | * @chip: The NAND chip |
| 1098 | * @chipnr: Internal die id | ||
| 1098 | * | 1099 | * |
| 1099 | * Returns 0 for success or negative error code otherwise | 1100 | * Returns 0 for success or negative error code otherwise |
| 1100 | */ | 1101 | */ |
| 1101 | int nand_reset(struct nand_chip *chip) | 1102 | int nand_reset(struct nand_chip *chip, int chipnr) |
| 1102 | { | 1103 | { |
| 1103 | struct mtd_info *mtd = nand_to_mtd(chip); | 1104 | struct mtd_info *mtd = nand_to_mtd(chip); |
| 1104 | int ret; | 1105 | int ret; |
| @@ -1107,9 +1108,17 @@ int nand_reset(struct nand_chip *chip) | |||
| 1107 | if (ret) | 1108 | if (ret) |
| 1108 | return ret; | 1109 | return ret; |
| 1109 | 1110 | ||
| 1111 | /* | ||
| 1112 | * The CS line has to be released before we can apply the new NAND | ||
| 1113 | * interface settings, hence this weird ->select_chip() dance. | ||
| 1114 | */ | ||
| 1115 | chip->select_chip(mtd, chipnr); | ||
| 1110 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | 1116 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); |
| 1117 | chip->select_chip(mtd, -1); | ||
| 1111 | 1118 | ||
| 1119 | chip->select_chip(mtd, chipnr); | ||
| 1112 | ret = nand_setup_data_interface(chip); | 1120 | ret = nand_setup_data_interface(chip); |
| 1121 | chip->select_chip(mtd, -1); | ||
| 1113 | if (ret) | 1122 | if (ret) |
| 1114 | return ret; | 1123 | return ret; |
| 1115 | 1124 | ||
| @@ -1185,8 +1194,6 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
| 1185 | /* Shift to get chip number */ | 1194 | /* Shift to get chip number */ |
| 1186 | chipnr = ofs >> chip->chip_shift; | 1195 | chipnr = ofs >> chip->chip_shift; |
| 1187 | 1196 | ||
| 1188 | chip->select_chip(mtd, chipnr); | ||
| 1189 | |||
| 1190 | /* | 1197 | /* |
| 1191 | * Reset the chip. | 1198 | * Reset the chip. |
| 1192 | * If we want to check the WP through READ STATUS and check the bit 7 | 1199 | * If we want to check the WP through READ STATUS and check the bit 7 |
| @@ -1194,7 +1201,9 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
| 1194 | * some operation can also clear the bit 7 of status register | 1201 | * some operation can also clear the bit 7 of status register |
| 1195 | * eg. erase/program a locked block | 1202 | * eg. erase/program a locked block |
| 1196 | */ | 1203 | */ |
| 1197 | nand_reset(chip); | 1204 | nand_reset(chip, chipnr); |
| 1205 | |||
| 1206 | chip->select_chip(mtd, chipnr); | ||
| 1198 | 1207 | ||
| 1199 | /* Check, if it is write protected */ | 1208 | /* Check, if it is write protected */ |
| 1200 | if (nand_check_wp(mtd)) { | 1209 | if (nand_check_wp(mtd)) { |
| @@ -1244,8 +1253,6 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
| 1244 | /* Shift to get chip number */ | 1253 | /* Shift to get chip number */ |
| 1245 | chipnr = ofs >> chip->chip_shift; | 1254 | chipnr = ofs >> chip->chip_shift; |
| 1246 | 1255 | ||
| 1247 | chip->select_chip(mtd, chipnr); | ||
| 1248 | |||
| 1249 | /* | 1256 | /* |
| 1250 | * Reset the chip. | 1257 | * Reset the chip. |
| 1251 | * If we want to check the WP through READ STATUS and check the bit 7 | 1258 | * If we want to check the WP through READ STATUS and check the bit 7 |
| @@ -1253,7 +1260,9 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
| 1253 | * some operation can also clear the bit 7 of status register | 1260 | * some operation can also clear the bit 7 of status register |
| 1254 | * eg. erase/program a locked block | 1261 | * eg. erase/program a locked block |
| 1255 | */ | 1262 | */ |
| 1256 | nand_reset(chip); | 1263 | nand_reset(chip, chipnr); |
| 1264 | |||
| 1265 | chip->select_chip(mtd, chipnr); | ||
| 1257 | 1266 | ||
| 1258 | /* Check, if it is write protected */ | 1267 | /* Check, if it is write protected */ |
| 1259 | if (nand_check_wp(mtd)) { | 1268 | if (nand_check_wp(mtd)) { |
| @@ -2940,10 +2949,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
| 2940 | } | 2949 | } |
| 2941 | 2950 | ||
| 2942 | chipnr = (int)(to >> chip->chip_shift); | 2951 | chipnr = (int)(to >> chip->chip_shift); |
| 2943 | chip->select_chip(mtd, chipnr); | ||
| 2944 | |||
| 2945 | /* Shift to get page */ | ||
| 2946 | page = (int)(to >> chip->page_shift); | ||
| 2947 | 2952 | ||
| 2948 | /* | 2953 | /* |
| 2949 | * Reset the chip. Some chips (like the Toshiba TC5832DC found in one | 2954 | * Reset the chip. Some chips (like the Toshiba TC5832DC found in one |
| @@ -2951,7 +2956,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | |||
| 2951 | * if we don't do this. I have no clue why, but I seem to have 'fixed' | 2956 | * if we don't do this. I have no clue why, but I seem to have 'fixed' |
| 2952 | * it in the doc2000 driver in August 1999. dwmw2. | 2957 | * it in the doc2000 driver in August 1999. dwmw2. |
| 2953 | */ | 2958 | */ |
| 2954 | nand_reset(chip); | 2959 | nand_reset(chip, chipnr); |
| 2960 | |||
| 2961 | chip->select_chip(mtd, chipnr); | ||
| 2962 | |||
| 2963 | /* Shift to get page */ | ||
| 2964 | page = (int)(to >> chip->page_shift); | ||
| 2955 | 2965 | ||
| 2956 | /* Check, if it is write protected */ | 2966 | /* Check, if it is write protected */ |
| 2957 | if (nand_check_wp(mtd)) { | 2967 | if (nand_check_wp(mtd)) { |
| @@ -3984,14 +3994,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
| 3984 | int i, maf_idx; | 3994 | int i, maf_idx; |
| 3985 | u8 id_data[8]; | 3995 | u8 id_data[8]; |
| 3986 | 3996 | ||
| 3987 | /* Select the device */ | ||
| 3988 | chip->select_chip(mtd, 0); | ||
| 3989 | |||
| 3990 | /* | 3997 | /* |
| 3991 | * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) | 3998 | * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) |
| 3992 | * after power-up. | 3999 | * after power-up. |
| 3993 | */ | 4000 | */ |
| 3994 | nand_reset(chip); | 4001 | nand_reset(chip, 0); |
| 4002 | |||
| 4003 | /* Select the device */ | ||
| 4004 | chip->select_chip(mtd, 0); | ||
| 3995 | 4005 | ||
| 3996 | /* Send the command for reading device ID */ | 4006 | /* Send the command for reading device ID */ |
| 3997 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 4007 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
| @@ -4329,17 +4339,31 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
| 4329 | return PTR_ERR(type); | 4339 | return PTR_ERR(type); |
| 4330 | } | 4340 | } |
| 4331 | 4341 | ||
| 4342 | /* Initialize the ->data_interface field. */ | ||
| 4332 | ret = nand_init_data_interface(chip); | 4343 | ret = nand_init_data_interface(chip); |
| 4333 | if (ret) | 4344 | if (ret) |
| 4334 | return ret; | 4345 | return ret; |
| 4335 | 4346 | ||
| 4347 | /* | ||
| 4348 | * Setup the data interface correctly on the chip and controller side. | ||
| 4349 | * This explicit call to nand_setup_data_interface() is only required | ||
| 4350 | * for the first die, because nand_reset() has been called before | ||
| 4351 | * ->data_interface and ->default_onfi_timing_mode were set. | ||
| 4352 | * For the other dies, nand_reset() will automatically switch to the | ||
| 4353 | * best mode for us. | ||
| 4354 | */ | ||
| 4355 | ret = nand_setup_data_interface(chip); | ||
| 4356 | if (ret) | ||
| 4357 | return ret; | ||
| 4358 | |||
| 4336 | chip->select_chip(mtd, -1); | 4359 | chip->select_chip(mtd, -1); |
| 4337 | 4360 | ||
| 4338 | /* Check for a chip array */ | 4361 | /* Check for a chip array */ |
| 4339 | for (i = 1; i < maxchips; i++) { | 4362 | for (i = 1; i < maxchips; i++) { |
| 4340 | chip->select_chip(mtd, i); | ||
| 4341 | /* See comment in nand_get_flash_type for reset */ | 4363 | /* See comment in nand_get_flash_type for reset */ |
| 4342 | nand_reset(chip); | 4364 | nand_reset(chip, i); |
| 4365 | |||
| 4366 | chip->select_chip(mtd, i); | ||
| 4343 | /* Send the command for reading device ID */ | 4367 | /* Send the command for reading device ID */ |
| 4344 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 4368 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
| 4345 | /* Read manufacturer and device IDs */ | 4369 | /* Read manufacturer and device IDs */ |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index c5d3d5024fc8..d8905a229f34 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
| @@ -1184,7 +1184,7 @@ int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1184 | int page); | 1184 | int page); |
| 1185 | 1185 | ||
| 1186 | /* Reset and initialize a NAND device */ | 1186 | /* Reset and initialize a NAND device */ |
| 1187 | int nand_reset(struct nand_chip *chip); | 1187 | int nand_reset(struct nand_chip *chip, int chipnr); |
| 1188 | 1188 | ||
| 1189 | /* Free resources held by the NAND device */ | 1189 | /* Free resources held by the NAND device */ |
| 1190 | void nand_cleanup(struct nand_chip *chip); | 1190 | void nand_cleanup(struct nand_chip *chip); |
