0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) "nand: " fmt
0011
0012 #include <linux/module.h>
0013 #include <linux/mtd/nand.h>
0014
0015
0016
0017
0018
0019
0020
0021
0022 bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos)
0023 {
0024 if (mtd_check_expert_analysis_mode())
0025 return false;
0026
0027 if (nanddev_bbt_is_initialized(nand)) {
0028 unsigned int entry;
0029 int status;
0030
0031 entry = nanddev_bbt_pos_to_entry(nand, pos);
0032 status = nanddev_bbt_get_block_status(nand, entry);
0033
0034 if (status == NAND_BBT_BLOCK_STATUS_UNKNOWN) {
0035 if (nand->ops->isbad(nand, pos))
0036 status = NAND_BBT_BLOCK_FACTORY_BAD;
0037 else
0038 status = NAND_BBT_BLOCK_GOOD;
0039
0040 nanddev_bbt_set_block_status(nand, entry, status);
0041 }
0042
0043 if (status == NAND_BBT_BLOCK_WORN ||
0044 status == NAND_BBT_BLOCK_FACTORY_BAD)
0045 return true;
0046
0047 return false;
0048 }
0049
0050 return nand->ops->isbad(nand, pos);
0051 }
0052 EXPORT_SYMBOL_GPL(nanddev_isbad);
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos)
0065 {
0066 struct mtd_info *mtd = nanddev_to_mtd(nand);
0067 unsigned int entry;
0068 int ret = 0;
0069
0070 if (nanddev_isbad(nand, pos))
0071 return 0;
0072
0073 ret = nand->ops->markbad(nand, pos);
0074 if (ret)
0075 pr_warn("failed to write BBM to block @%llx (err = %d)\n",
0076 nanddev_pos_to_offs(nand, pos), ret);
0077
0078 if (!nanddev_bbt_is_initialized(nand))
0079 goto out;
0080
0081 entry = nanddev_bbt_pos_to_entry(nand, pos);
0082 ret = nanddev_bbt_set_block_status(nand, entry, NAND_BBT_BLOCK_WORN);
0083 if (ret)
0084 goto out;
0085
0086 ret = nanddev_bbt_update(nand);
0087
0088 out:
0089 if (!ret)
0090 mtd->ecc_stats.badblocks++;
0091
0092 return ret;
0093 }
0094 EXPORT_SYMBOL_GPL(nanddev_markbad);
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos)
0106 {
0107 unsigned int entry;
0108 int status;
0109
0110 if (!nanddev_bbt_is_initialized(nand))
0111 return false;
0112
0113
0114 entry = nanddev_bbt_pos_to_entry(nand, pos);
0115 status = nanddev_bbt_get_block_status(nand, entry);
0116 return status == NAND_BBT_BLOCK_RESERVED;
0117 }
0118 EXPORT_SYMBOL_GPL(nanddev_isreserved);
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
0130 {
0131 if (nanddev_isbad(nand, pos) || nanddev_isreserved(nand, pos)) {
0132 pr_warn("attempt to erase a bad/reserved block @%llx\n",
0133 nanddev_pos_to_offs(nand, pos));
0134 return -EIO;
0135 }
0136
0137 return nand->ops->erase(nand, pos);
0138 }
0139 EXPORT_SYMBOL_GPL(nanddev_erase);
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo)
0157 {
0158 struct nand_device *nand = mtd_to_nanddev(mtd);
0159 struct nand_pos pos, last;
0160 int ret;
0161
0162 nanddev_offs_to_pos(nand, einfo->addr, &pos);
0163 nanddev_offs_to_pos(nand, einfo->addr + einfo->len - 1, &last);
0164 while (nanddev_pos_cmp(&pos, &last) <= 0) {
0165 ret = nanddev_erase(nand, &pos);
0166 if (ret) {
0167 einfo->fail_addr = nanddev_pos_to_offs(nand, &pos);
0168
0169 return ret;
0170 }
0171
0172 nanddev_pos_next_eraseblock(nand, &pos);
0173 }
0174
0175 return 0;
0176 }
0177 EXPORT_SYMBOL_GPL(nanddev_mtd_erase);
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len)
0193 {
0194 struct nand_device *nand = mtd_to_nanddev(mtd);
0195 struct nand_pos pos, end;
0196 unsigned int max_bb = 0;
0197
0198 if (!nand->memorg.max_bad_eraseblocks_per_lun)
0199 return -ENOTSUPP;
0200
0201 nanddev_offs_to_pos(nand, offs, &pos);
0202 nanddev_offs_to_pos(nand, offs + len, &end);
0203
0204 for (nanddev_offs_to_pos(nand, offs, &pos);
0205 nanddev_pos_cmp(&pos, &end) < 0;
0206 nanddev_pos_next_lun(nand, &pos))
0207 max_bb += nand->memorg.max_bad_eraseblocks_per_lun;
0208
0209 return max_bb;
0210 }
0211 EXPORT_SYMBOL_GPL(nanddev_mtd_max_bad_blocks);
0212
0213
0214
0215
0216
0217 static int nanddev_get_ecc_engine(struct nand_device *nand)
0218 {
0219 int engine_type;
0220
0221
0222 of_get_nand_ecc_user_config(nand);
0223
0224 engine_type = nand->ecc.user_conf.engine_type;
0225 if (engine_type == NAND_ECC_ENGINE_TYPE_INVALID)
0226 engine_type = nand->ecc.defaults.engine_type;
0227
0228 switch (engine_type) {
0229 case NAND_ECC_ENGINE_TYPE_NONE:
0230 return 0;
0231 case NAND_ECC_ENGINE_TYPE_SOFT:
0232 nand->ecc.engine = nand_ecc_get_sw_engine(nand);
0233 break;
0234 case NAND_ECC_ENGINE_TYPE_ON_DIE:
0235 nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand);
0236 break;
0237 case NAND_ECC_ENGINE_TYPE_ON_HOST:
0238 nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand);
0239 if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER)
0240 return -EPROBE_DEFER;
0241 break;
0242 default:
0243 pr_err("Missing ECC engine type\n");
0244 }
0245
0246 if (!nand->ecc.engine)
0247 return -EINVAL;
0248
0249 return 0;
0250 }
0251
0252
0253
0254
0255
0256 static int nanddev_put_ecc_engine(struct nand_device *nand)
0257 {
0258 switch (nand->ecc.ctx.conf.engine_type) {
0259 case NAND_ECC_ENGINE_TYPE_ON_HOST:
0260 nand_ecc_put_on_host_hw_engine(nand);
0261 break;
0262 case NAND_ECC_ENGINE_TYPE_NONE:
0263 case NAND_ECC_ENGINE_TYPE_SOFT:
0264 case NAND_ECC_ENGINE_TYPE_ON_DIE:
0265 default:
0266 break;
0267 }
0268
0269 return 0;
0270 }
0271
0272
0273
0274
0275
0276 static int nanddev_find_ecc_configuration(struct nand_device *nand)
0277 {
0278 int ret;
0279
0280 if (!nand->ecc.engine)
0281 return -ENOTSUPP;
0282
0283 ret = nand_ecc_init_ctx(nand);
0284 if (ret)
0285 return ret;
0286
0287 if (!nand_ecc_is_strong_enough(nand))
0288 pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n",
0289 nand->mtd.name);
0290
0291 return 0;
0292 }
0293
0294
0295
0296
0297
0298 int nanddev_ecc_engine_init(struct nand_device *nand)
0299 {
0300 int ret;
0301
0302
0303 ret = nanddev_get_ecc_engine(nand);
0304 if (ret) {
0305 if (ret != -EPROBE_DEFER)
0306 pr_err("No ECC engine found\n");
0307
0308 return ret;
0309 }
0310
0311
0312 if (!nand->ecc.engine)
0313 return 0;
0314
0315
0316 ret = nanddev_find_ecc_configuration(nand);
0317 if (ret) {
0318 pr_err("No suitable ECC configuration\n");
0319 nanddev_put_ecc_engine(nand);
0320
0321 return ret;
0322 }
0323
0324 return 0;
0325 }
0326 EXPORT_SYMBOL_GPL(nanddev_ecc_engine_init);
0327
0328
0329
0330
0331
0332 void nanddev_ecc_engine_cleanup(struct nand_device *nand)
0333 {
0334 if (nand->ecc.engine)
0335 nand_ecc_cleanup_ctx(nand);
0336
0337 nanddev_put_ecc_engine(nand);
0338 }
0339 EXPORT_SYMBOL_GPL(nanddev_ecc_engine_cleanup);
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 int nanddev_init(struct nand_device *nand, const struct nand_ops *ops,
0353 struct module *owner)
0354 {
0355 struct mtd_info *mtd = nanddev_to_mtd(nand);
0356 struct nand_memory_organization *memorg = nanddev_get_memorg(nand);
0357
0358 if (!nand || !ops)
0359 return -EINVAL;
0360
0361 if (!ops->erase || !ops->markbad || !ops->isbad)
0362 return -EINVAL;
0363
0364 if (!memorg->bits_per_cell || !memorg->pagesize ||
0365 !memorg->pages_per_eraseblock || !memorg->eraseblocks_per_lun ||
0366 !memorg->planes_per_lun || !memorg->luns_per_target ||
0367 !memorg->ntargets)
0368 return -EINVAL;
0369
0370 nand->rowconv.eraseblock_addr_shift =
0371 fls(memorg->pages_per_eraseblock - 1);
0372 nand->rowconv.lun_addr_shift = fls(memorg->eraseblocks_per_lun - 1) +
0373 nand->rowconv.eraseblock_addr_shift;
0374
0375 nand->ops = ops;
0376
0377 mtd->type = memorg->bits_per_cell == 1 ?
0378 MTD_NANDFLASH : MTD_MLCNANDFLASH;
0379 mtd->flags = MTD_CAP_NANDFLASH;
0380 mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
0381 mtd->writesize = memorg->pagesize;
0382 mtd->writebufsize = memorg->pagesize;
0383 mtd->oobsize = memorg->oobsize;
0384 mtd->size = nanddev_size(nand);
0385 mtd->owner = owner;
0386
0387 return nanddev_bbt_init(nand);
0388 }
0389 EXPORT_SYMBOL_GPL(nanddev_init);
0390
0391
0392
0393
0394
0395
0396
0397 void nanddev_cleanup(struct nand_device *nand)
0398 {
0399 if (nanddev_bbt_is_initialized(nand))
0400 nanddev_bbt_cleanup(nand);
0401 }
0402 EXPORT_SYMBOL_GPL(nanddev_cleanup);
0403
0404 MODULE_DESCRIPTION("Generic NAND framework");
0405 MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
0406 MODULE_LICENSE("GPL v2");