Lines Matching full:mtd
3 * Core registration and callback routines for MTD
35 #include <linux/mtd/mtd.h>
36 #include <linux/mtd/partitions.h>
37 #include <linux/mtd/concat.h>
47 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_cls_suspend() local
49 return mtd ? mtd_suspend(mtd) : 0; in mtd_cls_suspend()
54 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_cls_resume() local
56 if (mtd) in mtd_cls_resume()
57 mtd_resume(mtd); in mtd_cls_resume()
68 .name = "mtd",
90 /* REVISIT once MTD uses the driver model better, whoever allocates
95 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_release() local
96 dev_t index = MTD_DEVT(mtd->index); in mtd_release()
98 idr_remove(&mtd_idr, mtd->index); in mtd_release()
99 of_node_put(mtd_get_of_node(mtd)); in mtd_release()
101 if (mtd_is_partition(mtd)) in mtd_release()
102 release_mtd_partition(mtd); in mtd_release()
119 struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt); in mtd_device_release() local
120 bool is_partition = mtd_is_partition(mtd); in mtd_device_release()
122 debugfs_remove_recursive(mtd->dbg.dfs_dir); in mtd_device_release()
125 nvmem_unregister(mtd->nvmem); in mtd_device_release()
127 device_unregister(&mtd->dev); in mtd_device_release()
130 * Clear dev so mtd can be safely re-registered later if desired. in mtd_device_release()
135 memset(&mtd->dev, 0, sizeof(mtd->dev)); in mtd_device_release()
149 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_type_show() local
152 switch (mtd->type) { in mtd_type_show()
188 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_flags_show() local
190 return sysfs_emit(buf, "0x%lx\n", (unsigned long)mtd->flags); in mtd_flags_show()
197 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_size_show() local
199 return sysfs_emit(buf, "%llu\n", (unsigned long long)mtd->size); in mtd_size_show()
206 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_erasesize_show() local
208 return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->erasesize); in mtd_erasesize_show()
215 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_writesize_show() local
217 return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->writesize); in mtd_writesize_show()
224 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_subpagesize_show() local
225 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; in mtd_subpagesize_show()
234 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_oobsize_show() local
236 return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->oobsize); in mtd_oobsize_show()
243 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_oobavail_show() local
245 return sysfs_emit(buf, "%u\n", mtd->oobavail); in mtd_oobavail_show()
252 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_numeraseregions_show() local
254 return sysfs_emit(buf, "%u\n", mtd->numeraseregions); in mtd_numeraseregions_show()
261 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_name_show() local
263 return sysfs_emit(buf, "%s\n", mtd->name); in mtd_name_show()
270 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_ecc_strength_show() local
272 return sysfs_emit(buf, "%u\n", mtd->ecc_strength); in mtd_ecc_strength_show()
280 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_bitflip_threshold_show() local
282 return sysfs_emit(buf, "%u\n", mtd->bitflip_threshold); in mtd_bitflip_threshold_show()
289 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_bitflip_threshold_store() local
297 mtd->bitflip_threshold = bitflip_threshold; in mtd_bitflip_threshold_store()
305 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_ecc_step_size_show() local
307 return sysfs_emit(buf, "%u\n", mtd->ecc_step_size); in mtd_ecc_step_size_show()
315 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_corrected_bits_show() local
316 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_corrected_bits_show()
325 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_ecc_failures_show() local
326 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_ecc_failures_show()
335 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_bad_blocks_show() local
336 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_bad_blocks_show()
345 struct mtd_info *mtd = dev_get_drvdata(dev); in mtd_bbt_blocks_show() local
346 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_bbt_blocks_show()
372 ATTRIBUTE_GROUPS(mtd);
375 .name = "mtd",
401 struct mtd_info *mtd = s->private; in mtd_ooblayout_show() local
408 err = iter(mtd, section, ®ion); in mtd_ooblayout_show()
435 static void mtd_debugfs_populate(struct mtd_info *mtd) in mtd_debugfs_populate() argument
437 struct device *dev = &mtd->dev; in mtd_debugfs_populate()
443 mtd->dbg.dfs_dir = debugfs_create_dir(dev_name(dev), dfs_dir_mtd); in mtd_debugfs_populate()
444 if (IS_ERR_OR_NULL(mtd->dbg.dfs_dir)) in mtd_debugfs_populate()
448 if (mtd_ooblayout_ecc(mtd, 0, ®ion) == 0) in mtd_debugfs_populate()
449 debugfs_create_file("ooblayout_ecc", 0444, mtd->dbg.dfs_dir, in mtd_debugfs_populate()
450 mtd, &mtd_ooblayout_ecc_fops); in mtd_debugfs_populate()
452 if (mtd_ooblayout_free(mtd, 0, ®ion) == 0) in mtd_debugfs_populate()
453 debugfs_create_file("ooblayout_free", 0444, mtd->dbg.dfs_dir, in mtd_debugfs_populate()
454 mtd, &mtd_ooblayout_free_fops); in mtd_debugfs_populate()
458 unsigned mtd_mmap_capabilities(struct mtd_info *mtd) in mtd_mmap_capabilities() argument
460 switch (mtd->type) { in mtd_mmap_capabilities()
477 struct mtd_info *mtd; in mtd_reboot_notifier() local
479 mtd = container_of(n, struct mtd_info, reboot_notifier); in mtd_reboot_notifier()
480 mtd->_reboot(mtd); in mtd_reboot_notifier()
487 * @mtd: pointer to new MTD device info structure
502 * From the pairing info the MTD user can find all the wunits paired with
505 * for (i = 0; i < mtd_pairing_groups(mtd); i++) {
507 * mtd_pairing_info_to_wunit(mtd, &info);
511 int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, in mtd_wunit_to_pairing_info() argument
514 struct mtd_info *master = mtd_get_master(mtd); in mtd_wunit_to_pairing_info()
532 * @mtd: pointer to new MTD device info structure
547 * npairs = mtd_wunit_per_eb(mtd) / mtd_pairing_groups(mtd);
549 * wunit = mtd_pairing_info_to_wunit(mtd, &info);
550 * mtd_write(mtd, mtd_wunit_to_offset(mtd, blkoffs, wunit),
551 * mtd->writesize, &retlen, buf + (i * mtd->writesize));
554 int mtd_pairing_info_to_wunit(struct mtd_info *mtd, in mtd_pairing_info_to_wunit() argument
557 struct mtd_info *master = mtd_get_master(mtd); in mtd_pairing_info_to_wunit()
566 return mtd->pairing->get_wunit(master, info); in mtd_pairing_info_to_wunit()
574 * @mtd: pointer to new MTD device info structure
582 int mtd_pairing_groups(struct mtd_info *mtd) in mtd_pairing_groups() argument
584 struct mtd_info *master = mtd_get_master(mtd); in mtd_pairing_groups()
596 struct mtd_info *mtd = priv; in mtd_nvmem_reg_read() local
600 err = mtd_read(mtd, offset, bytes, &retlen, val); in mtd_nvmem_reg_read()
607 static int mtd_nvmem_add(struct mtd_info *mtd) in mtd_nvmem_add() argument
609 struct device_node *node = mtd_get_of_node(mtd); in mtd_nvmem_add()
613 config.dev = &mtd->dev; in mtd_nvmem_add()
614 config.name = dev_name(&mtd->dev); in mtd_nvmem_add()
618 config.size = mtd->size; in mtd_nvmem_add()
624 config.priv = mtd; in mtd_nvmem_add()
626 mtd->nvmem = nvmem_register(&config); in mtd_nvmem_add()
627 if (IS_ERR(mtd->nvmem)) { in mtd_nvmem_add()
629 if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) in mtd_nvmem_add()
630 mtd->nvmem = NULL; in mtd_nvmem_add()
632 return dev_err_probe(&mtd->dev, PTR_ERR(mtd->nvmem), in mtd_nvmem_add()
639 static void mtd_check_of_node(struct mtd_info *mtd) in mtd_check_of_node() argument
645 /* Check if MTD already has a device node */ in mtd_check_of_node()
646 if (mtd_get_of_node(mtd)) in mtd_check_of_node()
649 if (!mtd_is_partition(mtd)) in mtd_check_of_node()
652 parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); in mtd_check_of_node()
656 if (mtd_is_partition(mtd->parent)) in mtd_check_of_node()
664 mtd_name_len = strlen(mtd->name); in mtd_check_of_node()
682 !strncmp(mtd->name, pname + offset, plen)) { in mtd_check_of_node()
683 mtd_set_of_node(mtd, mtd_dn); in mtd_check_of_node()
695 * add_mtd_device - register an MTD device
696 * @mtd: pointer to new MTD device info structure
698 * Add a device to the list of MTD devices present in the system, and
699 * notify each currently active MTD 'user' of its arrival. Returns
703 int add_mtd_device(struct mtd_info *mtd) in add_mtd_device() argument
705 struct device_node *np = mtd_get_of_node(mtd); in add_mtd_device()
706 struct mtd_info *master = mtd_get_master(mtd); in add_mtd_device()
712 * mtd_device_parse_register() multiple times on the same master MTD, in add_mtd_device()
715 if (WARN_ONCE(mtd->dev.type, "MTD already registered\n")) in add_mtd_device()
718 BUG_ON(mtd->writesize == 0); in add_mtd_device()
721 * MTD drivers should implement ->_{write,read}() or in add_mtd_device()
724 if (WARN_ON((mtd->_write && mtd->_write_oob) || in add_mtd_device()
725 (mtd->_read && mtd->_read_oob))) in add_mtd_device()
728 if (WARN_ON((!mtd->erasesize || !master->_erase) && in add_mtd_device()
729 !(mtd->flags & MTD_NO_ERASE))) in add_mtd_device()
740 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION && in add_mtd_device()
741 (!mtd_is_partition(mtd) || master->type != MTD_MLCNANDFLASH || in add_mtd_device()
749 ofidx = of_alias_get_id(np, "mtd"); in add_mtd_device()
751 i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); in add_mtd_device()
753 i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); in add_mtd_device()
759 mtd->index = i; in add_mtd_device()
760 kref_init(&mtd->refcnt); in add_mtd_device()
763 if (mtd->bitflip_threshold == 0) in add_mtd_device()
764 mtd->bitflip_threshold = mtd->ecc_strength; in add_mtd_device()
766 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in add_mtd_device()
769 mtd->erasesize /= ngroups; in add_mtd_device()
770 mtd->size = (u64)mtd_div_by_eb(mtd->size, master) * in add_mtd_device()
771 mtd->erasesize; in add_mtd_device()
774 if (is_power_of_2(mtd->erasesize)) in add_mtd_device()
775 mtd->erasesize_shift = ffs(mtd->erasesize) - 1; in add_mtd_device()
777 mtd->erasesize_shift = 0; in add_mtd_device()
779 if (is_power_of_2(mtd->writesize)) in add_mtd_device()
780 mtd->writesize_shift = ffs(mtd->writesize) - 1; in add_mtd_device()
782 mtd->writesize_shift = 0; in add_mtd_device()
784 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; in add_mtd_device()
785 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; in add_mtd_device()
788 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { in add_mtd_device()
789 error = mtd_unlock(mtd, 0, mtd->size); in add_mtd_device()
793 mtd->name); in add_mtd_device()
801 mtd->dev.type = &mtd_devtype; in add_mtd_device()
802 mtd->dev.class = &mtd_class; in add_mtd_device()
803 mtd->dev.devt = MTD_DEVT(i); in add_mtd_device()
804 error = dev_set_name(&mtd->dev, "mtd%d", i); in add_mtd_device()
807 dev_set_drvdata(&mtd->dev, mtd); in add_mtd_device()
808 mtd_check_of_node(mtd); in add_mtd_device()
809 of_node_get(mtd_get_of_node(mtd)); in add_mtd_device()
810 error = device_register(&mtd->dev); in add_mtd_device()
815 error = mtd_nvmem_add(mtd); in add_mtd_device()
819 mtd_debugfs_populate(mtd); in add_mtd_device()
821 device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, in add_mtd_device()
822 "mtd%dro", i); in add_mtd_device()
824 pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name); in add_mtd_device()
828 not->add(mtd); in add_mtd_device()
832 if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) { in add_mtd_device()
834 pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); in add_mtd_device()
835 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); in add_mtd_device()
837 pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", in add_mtd_device()
838 mtd->index, mtd->name); in add_mtd_device()
850 device_del(&mtd->dev); in add_mtd_device()
854 * release_mtd_partition() -> free_partition() from freeing mtd. in add_mtd_device()
857 mtd->dev.type = NULL; in add_mtd_device()
858 mtd->dev.release = mtd_dev_release_nop; in add_mtd_device()
859 put_device(&mtd->dev); in add_mtd_device()
860 of_node_put(mtd_get_of_node(mtd)); in add_mtd_device()
869 * del_mtd_device - unregister an MTD device
870 * @mtd: pointer to MTD device info structure
872 * Remove a device from the list of MTD devices present in the system,
873 * and notify each currently active MTD 'user' of its departure.
878 int del_mtd_device(struct mtd_info *mtd) in del_mtd_device() argument
885 if (idr_find(&mtd_idr, mtd->index) != mtd) { in del_mtd_device()
893 not->remove(mtd); in del_mtd_device()
895 kref_put(&mtd->refcnt, mtd_device_release); in del_mtd_device()
907 static void mtd_set_dev_defaults(struct mtd_info *mtd) in mtd_set_dev_defaults() argument
909 if (mtd->dev.parent) { in mtd_set_dev_defaults()
910 if (!mtd->owner && mtd->dev.parent->driver) in mtd_set_dev_defaults()
911 mtd->owner = mtd->dev.parent->driver->owner; in mtd_set_dev_defaults()
912 if (!mtd->name) in mtd_set_dev_defaults()
913 mtd->name = dev_name(mtd->dev.parent); in mtd_set_dev_defaults()
915 pr_debug("mtd device won't show a device symlink in sysfs\n"); in mtd_set_dev_defaults()
918 INIT_LIST_HEAD(&mtd->partitions); in mtd_set_dev_defaults()
919 mutex_init(&mtd->master.partitions_lock); in mtd_set_dev_defaults()
920 mutex_init(&mtd->master.chrdev_lock); in mtd_set_dev_defaults()
923 static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user) in mtd_otp_size() argument
936 ret = mtd_get_user_prot_info(mtd, PAGE_SIZE, &retlen, info); in mtd_otp_size()
938 ret = mtd_get_fact_prot_info(mtd, PAGE_SIZE, &retlen, info); in mtd_otp_size()
955 static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, in mtd_otp_nvmem_register() argument
965 np = of_get_compatible_child(mtd->dev.of_node, compatible); in mtd_otp_nvmem_register()
968 config.dev = mtd->dev.parent; in mtd_otp_nvmem_register()
972 config.add_legacy_fixed_of_cells = !mtd_type_is_nand(mtd); in mtd_otp_nvmem_register()
979 config.priv = mtd; in mtd_otp_nvmem_register()
994 struct mtd_info *mtd = priv; in mtd_nvmem_user_otp_reg_read() local
998 ret = mtd_read_user_prot_reg(mtd, offset, bytes, &retlen, val); in mtd_nvmem_user_otp_reg_read()
1008 struct mtd_info *mtd = priv; in mtd_nvmem_fact_otp_reg_read() local
1012 ret = mtd_read_fact_prot_reg(mtd, offset, bytes, &retlen, val); in mtd_nvmem_fact_otp_reg_read()
1019 static int mtd_otp_nvmem_add(struct mtd_info *mtd) in mtd_otp_nvmem_add() argument
1021 struct device *dev = mtd->dev.parent; in mtd_otp_nvmem_add()
1026 if (mtd->_get_user_prot_info && mtd->_read_user_prot_reg) { in mtd_otp_nvmem_add()
1027 size = mtd_otp_size(mtd, true); in mtd_otp_nvmem_add()
1034 nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, in mtd_otp_nvmem_add()
1040 mtd->otp_user_nvmem = nvmem; in mtd_otp_nvmem_add()
1044 if (mtd->_get_fact_prot_info && mtd->_read_fact_prot_reg) { in mtd_otp_nvmem_add()
1045 size = mtd_otp_size(mtd, false); in mtd_otp_nvmem_add()
1064 err = mtd_nvmem_fact_otp_reg_read(mtd, 0, otp, size); in mtd_otp_nvmem_add()
1072 nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, in mtd_otp_nvmem_add()
1078 mtd->otp_factory_nvmem = nvmem; in mtd_otp_nvmem_add()
1085 nvmem_unregister(mtd->otp_user_nvmem); in mtd_otp_nvmem_add()
1086 mtd->otp_user_nvmem = NULL; in mtd_otp_nvmem_add()
1094 * mtd_device_parse_register - parse partitions and register an MTD device.
1096 * @mtd: the MTD device to register
1097 * @types: the list of MTD partition probes to try, see
1099 * @parser_data: MTD partition parser-specific data
1103 * MTD device is registered if no partition info is found
1105 * This function aggregates MTD partitions parsing (done by
1106 * 'parse_mtd_partitions()') and MTD device and partitions registering. It
1107 * basically follows the most common pattern found in many MTD drivers:
1111 * * Then It tries to probe partitions on MTD device @mtd using parsers
1116 * * If no partitions were found this function just registers the MTD device
1117 * @mtd and exits.
1121 int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, in mtd_device_parse_register() argument
1128 mtd_set_dev_defaults(mtd); in mtd_device_parse_register()
1130 ret = mtd_otp_nvmem_add(mtd); in mtd_device_parse_register()
1135 ret = add_mtd_device(mtd); in mtd_device_parse_register()
1147 ret = parse_mtd_partitions(mtd, types, parser_data); in mtd_device_parse_register()
1154 ret = add_mtd_partitions(mtd, parts, nr_parts); in mtd_device_parse_register()
1155 else if (!device_is_registered(&mtd->dev)) in mtd_device_parse_register()
1156 ret = add_mtd_device(mtd); in mtd_device_parse_register()
1176 WARN_ONCE(mtd->_reboot && mtd->reboot_notifier.notifier_call, in mtd_device_parse_register()
1177 "MTD already registered\n"); in mtd_device_parse_register()
1178 if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) { in mtd_device_parse_register()
1179 mtd->reboot_notifier.notifier_call = mtd_reboot_notifier; in mtd_device_parse_register()
1180 register_reboot_notifier(&mtd->reboot_notifier); in mtd_device_parse_register()
1185 nvmem_unregister(mtd->otp_user_nvmem); in mtd_device_parse_register()
1186 nvmem_unregister(mtd->otp_factory_nvmem); in mtd_device_parse_register()
1189 if (ret && device_is_registered(&mtd->dev)) { in mtd_device_parse_register()
1190 err = del_mtd_device(mtd); in mtd_device_parse_register()
1192 pr_err("Error when deleting MTD device (%d)\n", err); in mtd_device_parse_register()
1200 * mtd_device_unregister - unregister an existing MTD device.
1202 * @master: the MTD device to unregister. This will unregister both the master
1234 * register_mtd_user - register a 'user' of MTD devices.
1238 * or removal of MTD devices. Causes the 'add' callback to be immediately
1239 * invoked for each MTD device currently present in the system.
1243 struct mtd_info *mtd; in register_mtd_user() local
1251 mtd_for_each_device(mtd) in register_mtd_user()
1252 new->add(mtd); in register_mtd_user()
1259 * unregister_mtd_user - unregister a 'user' of MTD devices.
1263 * notified upon addition or removal of MTD devices. Causes the
1264 * 'remove' callback to be immediately invoked for each MTD device
1269 struct mtd_info *mtd; in unregister_mtd_user() local
1275 mtd_for_each_device(mtd) in unregister_mtd_user()
1276 old->remove(mtd); in unregister_mtd_user()
1285 * get_mtd_device - obtain a validated handle for an MTD device
1286 * @mtd: last known address of the required MTD device
1287 * @num: internal device number of the required MTD device
1295 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) in get_mtd_device() argument
1304 if (other == mtd) { in get_mtd_device()
1305 ret = mtd; in get_mtd_device()
1311 if (mtd && mtd != ret) in get_mtd_device()
1330 int __get_mtd_device(struct mtd_info *mtd) in __get_mtd_device() argument
1332 struct mtd_info *master = mtd_get_master(mtd); in __get_mtd_device()
1347 while (mtd) { in __get_mtd_device()
1348 if (mtd != master) in __get_mtd_device()
1349 kref_get(&mtd->refcnt); in __get_mtd_device()
1350 mtd = mtd->parent; in __get_mtd_device()
1361 * of_get_mtd_device_by_node - obtain an MTD device associated with a given node
1367 struct mtd_info *mtd = NULL; in of_get_mtd_device_by_node() local
1376 mtd = tmp; in of_get_mtd_device_by_node()
1377 err = __get_mtd_device(mtd); in of_get_mtd_device_by_node()
1384 return err ? ERR_PTR(err) : mtd; in of_get_mtd_device_by_node()
1389 * get_mtd_device_nm - obtain a validated handle for an MTD device by
1391 * @name: MTD device name to open
1393 * This function returns MTD device description structure in case of
1399 struct mtd_info *mtd = NULL, *other; in get_mtd_device_nm() local
1405 mtd = other; in get_mtd_device_nm()
1410 if (!mtd) in get_mtd_device_nm()
1413 err = __get_mtd_device(mtd); in get_mtd_device_nm()
1418 return mtd; in get_mtd_device_nm()
1426 void put_mtd_device(struct mtd_info *mtd) in put_mtd_device() argument
1429 __put_mtd_device(mtd); in put_mtd_device()
1435 void __put_mtd_device(struct mtd_info *mtd) in __put_mtd_device() argument
1437 struct mtd_info *master = mtd_get_master(mtd); in __put_mtd_device()
1439 while (mtd) { in __put_mtd_device()
1440 /* kref_put() can relese mtd, so keep a reference mtd->parent */ in __put_mtd_device()
1441 struct mtd_info *parent = mtd->parent; in __put_mtd_device()
1443 if (mtd != master) in __put_mtd_device()
1444 kref_put(&mtd->refcnt, mtd_device_release); in __put_mtd_device()
1445 mtd = parent; in __put_mtd_device()
1464 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) in mtd_erase() argument
1466 struct mtd_info *master = mtd_get_master(mtd); in mtd_erase()
1467 u64 mst_ofs = mtd_get_master_ofs(mtd, 0); in mtd_erase()
1474 if (!mtd->erasesize || !master->_erase) in mtd_erase()
1477 if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr) in mtd_erase()
1479 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_erase()
1487 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_erase()
1488 adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) * in mtd_erase()
1490 adjinstr.len = ((u64)mtd_div_by_eb(instr->addr + instr->len, mtd) * in mtd_erase()
1501 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_erase()
1504 instr->fail_addr *= mtd->erasesize; in mtd_erase()
1516 int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, in mtd_point() argument
1519 struct mtd_info *master = mtd_get_master(mtd); in mtd_point()
1527 if (from < 0 || from >= mtd->size || len > mtd->size - from) in mtd_point()
1532 from = mtd_get_master_ofs(mtd, from); in mtd_point()
1538 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) in mtd_unpoint() argument
1540 struct mtd_info *master = mtd_get_master(mtd); in mtd_unpoint()
1544 if (from < 0 || from >= mtd->size || len > mtd->size - from) in mtd_unpoint()
1548 return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len); in mtd_unpoint()
1557 unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, in mtd_get_unmapped_area() argument
1564 ret = mtd_point(mtd, offset, len, &retlen, &virt, NULL); in mtd_get_unmapped_area()
1568 mtd_unpoint(mtd, offset, retlen); in mtd_get_unmapped_area()
1575 static void mtd_update_ecc_stats(struct mtd_info *mtd, struct mtd_info *master, in mtd_update_ecc_stats() argument
1580 if (master == mtd) in mtd_update_ecc_stats()
1587 while (mtd->parent) { in mtd_update_ecc_stats()
1588 mtd->ecc_stats.failed += diff.failed; in mtd_update_ecc_stats()
1589 mtd->ecc_stats.corrected += diff.corrected; in mtd_update_ecc_stats()
1590 mtd = mtd->parent; in mtd_update_ecc_stats()
1594 int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, in mtd_read() argument
1603 ret = mtd_read_oob(mtd, from, &ops); in mtd_read()
1613 int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, in mtd_write() argument
1622 ret = mtd_write_oob(mtd, to, &ops); in mtd_write()
1637 int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, in mtd_panic_write() argument
1640 struct mtd_info *master = mtd_get_master(mtd); in mtd_panic_write()
1645 if (to < 0 || to >= mtd->size || len > mtd->size - to) in mtd_panic_write()
1647 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_panic_write()
1654 return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len, in mtd_panic_write()
1659 static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs, in mtd_check_oob_ops() argument
1673 if (offs < 0 || offs + ops->len > mtd->size) in mtd_check_oob_ops()
1679 if (ops->ooboffs >= mtd_oobavail(mtd, ops)) in mtd_check_oob_ops()
1682 maxooblen = ((size_t)(mtd_div_by_ws(mtd->size, mtd) - in mtd_check_oob_ops()
1683 mtd_div_by_ws(offs, mtd)) * in mtd_check_oob_ops()
1684 mtd_oobavail(mtd, ops)) - ops->ooboffs; in mtd_check_oob_ops()
1692 static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from, in mtd_read_oob_std() argument
1695 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_oob_std()
1698 from = mtd_get_master_ofs(mtd, from); in mtd_read_oob_std()
1708 static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to, in mtd_write_oob_std() argument
1711 struct mtd_info *master = mtd_get_master(mtd); in mtd_write_oob_std()
1714 to = mtd_get_master_ofs(mtd, to); in mtd_write_oob_std()
1724 static int mtd_io_emulated_slc(struct mtd_info *mtd, loff_t start, bool read, in mtd_io_emulated_slc() argument
1727 struct mtd_info *master = mtd_get_master(mtd); in mtd_io_emulated_slc()
1737 ebofs = mtd_mod_by_eb(start, mtd); in mtd_io_emulated_slc()
1738 base = (loff_t)mtd_div_by_eb(start, mtd) * master->erasesize; in mtd_io_emulated_slc()
1740 info.pair = mtd_div_by_ws(ebofs, mtd); in mtd_io_emulated_slc()
1741 pageofs = mtd_mod_by_ws(ebofs, mtd); in mtd_io_emulated_slc()
1742 oobavail = mtd_oobavail(mtd, ops); in mtd_io_emulated_slc()
1753 pos = mtd_wunit_to_offset(mtd, base, wunit); in mtd_io_emulated_slc()
1756 if (adjops.len > mtd->writesize - pageofs) in mtd_io_emulated_slc()
1757 adjops.len = mtd->writesize - pageofs; in mtd_io_emulated_slc()
1764 ret = mtd_read_oob_std(mtd, pos + pageofs, &adjops); in mtd_io_emulated_slc()
1768 ret = mtd_write_oob_std(mtd, pos + pageofs, &adjops); in mtd_io_emulated_slc()
1787 int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) in mtd_read_oob() argument
1789 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_oob()
1795 ret_code = mtd_check_oob_ops(mtd, from, ops); in mtd_read_oob()
1801 /* Check the validity of a potential fallback on mtd->_read */ in mtd_read_oob()
1808 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_read_oob()
1809 ret_code = mtd_io_emulated_slc(mtd, from, true, ops); in mtd_read_oob()
1811 ret_code = mtd_read_oob_std(mtd, from, ops); in mtd_read_oob()
1813 mtd_update_ecc_stats(mtd, master, &old_stats); in mtd_read_oob()
1816 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics in mtd_read_oob()
1817 * similar to mtd->_read(), returning a non-negative integer in mtd_read_oob()
1818 * representing max bitflips. In other cases, mtd->_read_oob() may in mtd_read_oob()
1823 if (mtd->ecc_strength == 0) in mtd_read_oob()
1827 return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; in mtd_read_oob()
1831 int mtd_write_oob(struct mtd_info *mtd, loff_t to, in mtd_write_oob() argument
1834 struct mtd_info *master = mtd_get_master(mtd); in mtd_write_oob()
1839 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_write_oob()
1842 ret = mtd_check_oob_ops(mtd, to, ops); in mtd_write_oob()
1848 /* Check the validity of a potential fallback on mtd->_write */ in mtd_write_oob()
1852 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_write_oob()
1853 return mtd_io_emulated_slc(mtd, to, false, ops); in mtd_write_oob()
1855 return mtd_write_oob_std(mtd, to, ops); in mtd_write_oob()
1861 * @mtd: MTD device structure
1871 * mtd_ooblayout_ecc(mtd, section++, oobecc) until it returns -ERANGE.
1875 int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, in mtd_ooblayout_ecc() argument
1878 struct mtd_info *master = mtd_get_master(mtd); in mtd_ooblayout_ecc()
1895 * @mtd: MTD device structure
1905 * mtd_ooblayout_free(mtd, section++, oobfree) until it returns -ERANGE.
1909 int mtd_ooblayout_free(struct mtd_info *mtd, int section, in mtd_ooblayout_free() argument
1912 struct mtd_info *master = mtd_get_master(mtd); in mtd_ooblayout_free()
1928 * @mtd: mtd info structure
1939 * mtd_ooblayout_find_region(mtd, 3, §ion, &oobregion, mtd_ooblayout_ecc);
1943 static int mtd_ooblayout_find_region(struct mtd_info *mtd, int byte, in mtd_ooblayout_find_region() argument
1954 ret = iter(mtd, section, oobregion); in mtd_ooblayout_find_region()
1979 * @mtd: mtd info structure
1989 int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, in mtd_ooblayout_find_eccregion() argument
1993 return mtd_ooblayout_find_region(mtd, eccbyte, section, oobregion, in mtd_ooblayout_find_eccregion()
2000 * @mtd: mtd info structure
2012 static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf, in mtd_ooblayout_get_bytes() argument
2021 ret = mtd_ooblayout_find_region(mtd, start, §ion, in mtd_ooblayout_get_bytes()
2035 ret = iter(mtd, ++section, &oobregion); in mtd_ooblayout_get_bytes()
2043 * @mtd: mtd info structure
2055 static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf, in mtd_ooblayout_set_bytes() argument
2064 ret = mtd_ooblayout_find_region(mtd, start, §ion, in mtd_ooblayout_set_bytes()
2078 ret = iter(mtd, ++section, &oobregion); in mtd_ooblayout_set_bytes()
2086 * @mtd: mtd info structure
2093 static int mtd_ooblayout_count_bytes(struct mtd_info *mtd, in mtd_ooblayout_count_bytes() argument
2102 ret = iter(mtd, section++, &oobregion); in mtd_ooblayout_count_bytes()
2117 * @mtd: mtd info structure
2127 int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, in mtd_ooblayout_get_eccbytes() argument
2130 return mtd_ooblayout_get_bytes(mtd, eccbuf, oobbuf, start, nbytes, in mtd_ooblayout_get_eccbytes()
2137 * @mtd: mtd info structure
2147 int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, in mtd_ooblayout_set_eccbytes() argument
2150 return mtd_ooblayout_set_bytes(mtd, eccbuf, oobbuf, start, nbytes, in mtd_ooblayout_set_eccbytes()
2157 * @mtd: mtd info structure
2167 int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, in mtd_ooblayout_get_databytes() argument
2170 return mtd_ooblayout_get_bytes(mtd, databuf, oobbuf, start, nbytes, in mtd_ooblayout_get_databytes()
2177 * @mtd: mtd info structure
2187 int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, in mtd_ooblayout_set_databytes() argument
2190 return mtd_ooblayout_set_bytes(mtd, databuf, oobbuf, start, nbytes, in mtd_ooblayout_set_databytes()
2197 * @mtd: mtd info structure
2203 int mtd_ooblayout_count_freebytes(struct mtd_info *mtd) in mtd_ooblayout_count_freebytes() argument
2205 return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_free); in mtd_ooblayout_count_freebytes()
2211 * @mtd: mtd info structure
2217 int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd) in mtd_ooblayout_count_eccbytes() argument
2219 return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_ecc); in mtd_ooblayout_count_eccbytes()
2228 int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, in mtd_get_fact_prot_info() argument
2231 struct mtd_info *master = mtd_get_master(mtd); in mtd_get_fact_prot_info()
2241 int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, in mtd_read_fact_prot_reg() argument
2244 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_fact_prot_reg()
2255 int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, in mtd_get_user_prot_info() argument
2258 struct mtd_info *master = mtd_get_master(mtd); in mtd_get_user_prot_info()
2268 int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, in mtd_read_user_prot_reg() argument
2271 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_user_prot_reg()
2282 int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, in mtd_write_user_prot_reg() argument
2285 struct mtd_info *master = mtd_get_master(mtd); in mtd_write_user_prot_reg()
2305 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) in mtd_lock_user_prot_reg() argument
2307 struct mtd_info *master = mtd_get_master(mtd); in mtd_lock_user_prot_reg()
2317 int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) in mtd_erase_user_prot_reg() argument
2319 struct mtd_info *master = mtd_get_master(mtd); in mtd_erase_user_prot_reg()
2330 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) in mtd_lock() argument
2332 struct mtd_info *master = mtd_get_master(mtd); in mtd_lock()
2336 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) in mtd_lock()
2341 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_lock()
2342 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_lock()
2343 len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize; in mtd_lock()
2346 return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len); in mtd_lock()
2350 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) in mtd_unlock() argument
2352 struct mtd_info *master = mtd_get_master(mtd); in mtd_unlock()
2356 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) in mtd_unlock()
2361 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_unlock()
2362 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_unlock()
2363 len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize; in mtd_unlock()
2366 return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len); in mtd_unlock()
2370 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) in mtd_is_locked() argument
2372 struct mtd_info *master = mtd_get_master(mtd); in mtd_is_locked()
2376 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) in mtd_is_locked()
2381 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_is_locked()
2382 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_is_locked()
2383 len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize; in mtd_is_locked()
2386 return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len); in mtd_is_locked()
2390 int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs) in mtd_block_isreserved() argument
2392 struct mtd_info *master = mtd_get_master(mtd); in mtd_block_isreserved()
2394 if (ofs < 0 || ofs >= mtd->size) in mtd_block_isreserved()
2399 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_block_isreserved()
2400 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_block_isreserved()
2402 return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs)); in mtd_block_isreserved()
2406 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) in mtd_block_isbad() argument
2408 struct mtd_info *master = mtd_get_master(mtd); in mtd_block_isbad()
2410 if (ofs < 0 || ofs >= mtd->size) in mtd_block_isbad()
2415 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_block_isbad()
2416 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_block_isbad()
2418 return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs)); in mtd_block_isbad()
2422 int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) in mtd_block_markbad() argument
2424 struct mtd_info *master = mtd_get_master(mtd); in mtd_block_markbad()
2430 if (ofs < 0 || ofs >= mtd->size) in mtd_block_markbad()
2432 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_block_markbad()
2435 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_block_markbad()
2436 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_block_markbad()
2438 moffs = mtd_get_master_ofs(mtd, ofs); in mtd_block_markbad()
2450 while (mtd->parent) { in mtd_block_markbad()
2451 mtd->ecc_stats.badblocks++; in mtd_block_markbad()
2452 mtd = mtd->parent; in mtd_block_markbad()
2462 * @mtd: mtd device description object pointer
2465 * @to: the MTD device offset to write to
2466 * @retlen: on exit contains the count of bytes written to the MTD device.
2471 static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, in default_mtd_writev() argument
2481 ret = mtd_write(mtd, to, vecs[i].iov_len, &thislen, in default_mtd_writev()
2493 * mtd_writev - the vector-based MTD write method
2494 * @mtd: mtd device description object pointer
2497 * @to: the MTD device offset to write to
2498 * @retlen: on exit contains the count of bytes written to the MTD device.
2503 int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, in mtd_writev() argument
2506 struct mtd_info *master = mtd_get_master(mtd); in mtd_writev()
2509 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_writev()
2513 return default_mtd_writev(mtd, vecs, count, to, retlen); in mtd_writev()
2516 mtd_get_master_ofs(mtd, to), retlen); in mtd_writev()
2522 * @mtd: mtd device description object pointer
2535 * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
2544 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) in mtd_kmalloc_up_to() argument
2547 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); in mtd_kmalloc_up_to()
2558 *size = ALIGN(*size, mtd->writesize); in mtd_kmalloc_up_to()
2572 /* Support for /proc/mtd */
2576 struct mtd_info *mtd; in mtd_proc_show() local
2580 mtd_for_each_device(mtd) { in mtd_proc_show()
2581 seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n", in mtd_proc_show()
2582 mtd->index, (unsigned long long)mtd->size, in mtd_proc_show()
2583 mtd->erasesize, mtd->name); in mtd_proc_show()
2625 mtd_bdi = mtd_bdi_init("mtd"); in init_mtd()
2631 proc_mtd = proc_create_single("mtd", 0, NULL, mtd_proc_show); in init_mtd()
2637 dfs_dir_mtd = debugfs_create_dir("mtd", NULL); in init_mtd()
2645 remove_proc_entry("mtd", NULL); in init_mtd()
2651 pr_err("Error registering mtd class or bdi: %d\n", ret); in init_mtd()
2664 remove_proc_entry("mtd", NULL); in cleanup_mtd()
2676 MODULE_DESCRIPTION("Core MTD registration and access routines");