Skip to content

Commit c4dfa25

Browse files
AlbanBedelgregkh
authored andcommitted
mtd: add support for reading MTD devices via the nvmem API
Allow drivers that use the nvmem API to read data stored on MTD devices. For this the mtd devices are registered as read-only NVMEM providers. We don't support device tree systems for now. Signed-off-by: Alban Bedel <albeu@free.fr> [Bartosz: - include linux/nvmem-provider.h - set the name of the nvmem provider - set no_of_node to true in nvmem_config - don't check the return value of nvmem_unregister() - it cannot fail - tweaked the commit message] Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Acked-by: Boris Brezillon <boris.brezillon@bootlin.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 517f14d commit c4dfa25

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

drivers/mtd/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
menuconfig MTD
22
tristate "Memory Technology Device (MTD) support"
3+
imply NVMEM
34
help
45
Memory Technology Devices are flash, RAM and similar chips, often
56
used for solid state file systems on embedded devices. This option

drivers/mtd/mtdcore.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/reboot.h>
4242
#include <linux/leds.h>
4343
#include <linux/debugfs.h>
44+
#include <linux/nvmem-provider.h>
4445

4546
#include <linux/mtd/mtd.h>
4647
#include <linux/mtd/partitions.h>
@@ -488,6 +489,50 @@ int mtd_pairing_groups(struct mtd_info *mtd)
488489
}
489490
EXPORT_SYMBOL_GPL(mtd_pairing_groups);
490491

492+
static int mtd_nvmem_reg_read(void *priv, unsigned int offset,
493+
void *val, size_t bytes)
494+
{
495+
struct mtd_info *mtd = priv;
496+
size_t retlen;
497+
int err;
498+
499+
err = mtd_read(mtd, offset, bytes, &retlen, val);
500+
if (err && err != -EUCLEAN)
501+
return err;
502+
503+
return retlen == bytes ? 0 : -EIO;
504+
}
505+
506+
static int mtd_nvmem_add(struct mtd_info *mtd)
507+
{
508+
struct nvmem_config config = {};
509+
510+
config.dev = &mtd->dev;
511+
config.name = mtd->name;
512+
config.owner = THIS_MODULE;
513+
config.reg_read = mtd_nvmem_reg_read;
514+
config.size = mtd->size;
515+
config.word_size = 1;
516+
config.stride = 1;
517+
config.read_only = true;
518+
config.root_only = true;
519+
config.no_of_node = true;
520+
config.priv = mtd;
521+
522+
mtd->nvmem = nvmem_register(&config);
523+
if (IS_ERR(mtd->nvmem)) {
524+
/* Just ignore if there is no NVMEM support in the kernel */
525+
if (PTR_ERR(mtd->nvmem) == -ENOSYS) {
526+
mtd->nvmem = NULL;
527+
} else {
528+
dev_err(&mtd->dev, "Failed to register NVMEM device\n");
529+
return PTR_ERR(mtd->nvmem);
530+
}
531+
}
532+
533+
return 0;
534+
}
535+
491536
static struct dentry *dfs_dir_mtd;
492537

493538
/**
@@ -570,6 +615,11 @@ int add_mtd_device(struct mtd_info *mtd)
570615
if (error)
571616
goto fail_added;
572617

618+
/* Add the nvmem provider */
619+
error = mtd_nvmem_add(mtd);
620+
if (error)
621+
goto fail_nvmem_add;
622+
573623
if (!IS_ERR_OR_NULL(dfs_dir_mtd)) {
574624
mtd->dbg.dfs_dir = debugfs_create_dir(dev_name(&mtd->dev), dfs_dir_mtd);
575625
if (IS_ERR_OR_NULL(mtd->dbg.dfs_dir)) {
@@ -595,6 +645,8 @@ int add_mtd_device(struct mtd_info *mtd)
595645
__module_get(THIS_MODULE);
596646
return 0;
597647

648+
fail_nvmem_add:
649+
device_unregister(&mtd->dev);
598650
fail_added:
599651
of_node_put(mtd_get_of_node(mtd));
600652
idr_remove(&mtd_idr, i);
@@ -637,6 +689,10 @@ int del_mtd_device(struct mtd_info *mtd)
637689
mtd->index, mtd->name, mtd->usecount);
638690
ret = -EBUSY;
639691
} else {
692+
/* Try to remove the NVMEM provider */
693+
if (mtd->nvmem)
694+
nvmem_unregister(mtd->nvmem);
695+
640696
device_unregister(&mtd->dev);
641697

642698
idr_remove(&mtd_idr, mtd->index);

include/linux/mtd/mtd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/notifier.h>
2626
#include <linux/device.h>
2727
#include <linux/of.h>
28+
#include <linux/nvmem-provider.h>
2829

2930
#include <mtd/mtd-abi.h>
3031

@@ -341,6 +342,7 @@ struct mtd_info {
341342
struct device dev;
342343
int usecount;
343344
struct mtd_debug_info dbg;
345+
struct nvmem_device *nvmem;
344346
};
345347

346348
int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,

0 commit comments

Comments
 (0)