Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2017 Free Electrons
0004  *
0005  * Authors:
0006  *  Boris Brezillon <boris.brezillon@free-electrons.com>
0007  *  Peter Pan <peterpandong@micron.com>
0008  */
0009 
0010 #define pr_fmt(fmt) "nand: " fmt
0011 
0012 #include <linux/module.h>
0013 #include <linux/mtd/nand.h>
0014 
0015 /**
0016  * nanddev_isbad() - Check if a block is bad
0017  * @nand: NAND device
0018  * @pos: position pointing to the block we want to check
0019  *
0020  * Return: true if the block is bad, false otherwise.
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         /* Lazy block status retrieval */
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  * nanddev_markbad() - Mark a block as bad
0056  * @nand: NAND device
0057  * @pos: position of the block to mark bad
0058  *
0059  * Mark a block bad. This function is updating the BBT if available and
0060  * calls the low-level markbad hook (nand->ops->markbad()).
0061  *
0062  * Return: 0 in case of success, a negative error code otherwise.
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  * nanddev_isreserved() - Check whether an eraseblock is reserved or not
0098  * @nand: NAND device
0099  * @pos: NAND position to test
0100  *
0101  * Checks whether the eraseblock pointed by @pos is reserved or not.
0102  *
0103  * Return: true if the eraseblock is reserved, false otherwise.
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     /* Return info from the table */
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  * nanddev_erase() - Erase a NAND portion
0122  * @nand: NAND device
0123  * @pos: position of the block to erase
0124  *
0125  * Erases the block if it's not bad.
0126  *
0127  * Return: 0 in case of success, a negative error code otherwise.
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  * nanddev_mtd_erase() - Generic mtd->_erase() implementation for NAND devices
0143  * @mtd: MTD device
0144  * @einfo: erase request
0145  *
0146  * This is a simple mtd->_erase() implementation iterating over all blocks
0147  * concerned by @einfo and calling nand->ops->erase() on each of them.
0148  *
0149  * Note that mtd->_erase should not be directly assigned to this helper,
0150  * because there's no locking here. NAND specialized layers should instead
0151  * implement there own wrapper around nanddev_mtd_erase() taking the
0152  * appropriate lock before calling nanddev_mtd_erase().
0153  *
0154  * Return: 0 in case of success, a negative error code otherwise.
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  * nanddev_mtd_max_bad_blocks() - Get the maximum number of bad eraseblock on
0181  *                a specific region of the NAND device
0182  * @mtd: MTD device
0183  * @offs: offset of the NAND region
0184  * @len: length of the NAND region
0185  *
0186  * Default implementation for mtd->_max_bad_blocks(). Only works if
0187  * nand->memorg.max_bad_eraseblocks_per_lun is > 0.
0188  *
0189  * Return: a positive number encoding the maximum number of eraseblocks on a
0190  * portion of memory, a negative error code otherwise.
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  * nanddev_get_ecc_engine() - Find and get a suitable ECC engine
0215  * @nand: NAND device
0216  */
0217 static int nanddev_get_ecc_engine(struct nand_device *nand)
0218 {
0219     int engine_type;
0220 
0221     /* Read the user desires in terms of ECC engine/configuration */
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  * nanddev_put_ecc_engine() - Dettach and put the in-use ECC engine
0254  * @nand: NAND device
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  * nanddev_find_ecc_configuration() - Find a suitable ECC configuration
0274  * @nand: NAND device
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  * nanddev_ecc_engine_init() - Initialize an ECC engine for the chip
0296  * @nand: NAND device
0297  */
0298 int nanddev_ecc_engine_init(struct nand_device *nand)
0299 {
0300     int ret;
0301 
0302     /* Look for the ECC engine to use */
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     /* No ECC engine requested */
0312     if (!nand->ecc.engine)
0313         return 0;
0314 
0315     /* Configure the engine: balance user input and chip requirements */
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  * nanddev_ecc_engine_cleanup() - Cleanup ECC engine initializations
0330  * @nand: NAND device
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  * nanddev_init() - Initialize a NAND device
0343  * @nand: NAND device
0344  * @ops: NAND device operations
0345  * @owner: NAND device owner
0346  *
0347  * Initializes a NAND device object. Consistency checks are done on @ops and
0348  * @nand->memorg. Also takes care of initializing the BBT.
0349  *
0350  * Return: 0 in case of success, a negative error code otherwise.
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  * nanddev_cleanup() - Release resources allocated in nanddev_init()
0393  * @nand: NAND device
0394  *
0395  * Basically undoes what has been done in nanddev_init().
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");