[RFC PATCH 2/2] mtd: core: introduce of support for dynamic partitions

From: Ansuel Smith
Date: Thu Jan 20 2022 - 15:26:35 EST


We have many parser that register mtd partitions at runtime. One example
is the cmdlinepart or the smem partition where the compatible is defined
in the dts and the partitions gets detected and registered by the
parser. This is problematic for the Nvmem system that requires an of node
to detect nvmem cells. To fix this problem, introduce an additional node
called "dynamic-partitions" that must be defined at the same level of
the "partitions" node that will contain all the required partitions
where a nvmem cell has to be declared. When a mtd_get_of_node() is
called, the function will first check the default dev_of_node() and then
check this alternative partitions node and optionally if a "nvmem-cells"
compatible is detected, sets the of node for the mtd.

The "dynamic-partitions" requires the label set to the mtd name from the
dynamic partition. All the nvmem-cells will be declared in this node and
nvmem will use this node to register the nvmem cells.

Signed-off-by: Ansuel Smith <ansuelsmth@xxxxxxxxx>
---
drivers/mtd/mtdcore.c | 45 +++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/mtd.h | 6 +-----
2 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 9186268d361b..ccf350337811 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -563,6 +563,51 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
return 0;
}

+struct device_node *mtd_get_of_node(struct mtd_info *mtd)
+{
+ struct device_node *dynamic_partitions, *parent_dn, *dn, *mtd_dn = NULL;
+ struct mtd_info *parent;
+ const char *mtd_name;
+ int plen;
+
+ /* Check if mtd has a device node */
+ dn = dev_of_node(&mtd->dev);
+ if (dn)
+ return dn;
+
+ /* Check if a dynamic-partitions node exist */
+ parent = mtd->parent;
+ parent_dn = dev_of_node(&parent->dev);
+ if (!parent_dn)
+ return NULL;
+
+ dynamic_partitions = of_get_compatible_child(parent_dn, "dynamic-partitions");
+ if (!dynamic_partitions)
+ goto exit_parent;
+
+ /* Search if a dynamic partition is defined with the same name */
+ for_each_child_of_node(dynamic_partitions, dn) {
+ mtd_name = of_get_property(dn, "label", &plen);
+ if (!strncmp(mtd->name, mtd_name, plen)) {
+ mtd_dn = dn;
+ break;
+ }
+ }
+
+ if (!mtd_dn)
+ goto exit_partitions;
+
+ /* Set of_node only for nvmem */
+ if (of_device_is_compatible(mtd_dn, "nvmem-cells"))
+ mtd_set_of_node(mtd, mtd_dn);
+
+exit_partitions:
+ of_node_put(dynamic_partitions);
+exit_parent:
+ of_node_put(parent_dn);
+ return mtd_dn;
+}
+
/**
* add_mtd_device - register an MTD device
* @mtd: pointer to new MTD device info structure
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index f5e7dfc2e4e9..f73d65817468 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -464,11 +464,6 @@ static inline void mtd_set_of_node(struct mtd_info *mtd,
of_property_read_string(np, "label", &mtd->name);
}

-static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
-{
- return dev_of_node(&mtd->dev);
-}
-
static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
{
return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
@@ -489,6 +484,7 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
len);
}

+struct device_node *mtd_get_of_node(struct mtd_info *mtd);
int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
struct mtd_pairing_info *info);
int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
--
2.33.1