|
|
@@ -0,0 +1,106 @@
|
|
|
+From ad9b10d1eaada169bd764abcab58f08538877e26 Mon Sep 17 00:00:00 2001
|
|
|
+From: Christian Marangi <[email protected]>
|
|
|
+Date: Wed, 22 Jun 2022 03:06:28 +0200
|
|
|
+Subject: mtd: core: introduce of support for dynamic partitions
|
|
|
+
|
|
|
+We have many parser that register mtd partitions at runtime. One example
|
|
|
+is the cmdlinepart or the smem-part parser where the compatible is defined
|
|
|
+in the dts and the partitions gets detected and registered by the
|
|
|
+parser. This is problematic for the NVMEM subsystem that requires an OF
|
|
|
+node to detect NVMEM cells.
|
|
|
+
|
|
|
+To fix this problem, introduce an additional logic that will try to
|
|
|
+assign an OF node to the MTD if declared.
|
|
|
+
|
|
|
+On MTD addition, it will be checked if the MTD has an OF node and if
|
|
|
+not declared will check if a partition with the same label / node name is
|
|
|
+declared in DTS. If an exact match is found, the partition dynamically
|
|
|
+allocated by the parser will have a connected OF node.
|
|
|
+
|
|
|
+The NVMEM subsystem will detect the OF node and register any NVMEM cells
|
|
|
+declared statically in the DTS.
|
|
|
+
|
|
|
+Signed-off-by: Christian Marangi <[email protected]>
|
|
|
+Signed-off-by: Miquel Raynal <[email protected]>
|
|
|
+Link: https://lore.kernel.org/linux-mtd/[email protected]
|
|
|
+---
|
|
|
+ drivers/mtd/mtdcore.c | 61 +++++++++++++++++++++++++++++++++++++++++++
|
|
|
+ 1 file changed, 61 insertions(+)
|
|
|
+
|
|
|
+--- a/drivers/mtd/mtdcore.c
|
|
|
++++ b/drivers/mtd/mtdcore.c
|
|
|
+@@ -561,6 +561,66 @@ static int mtd_nvmem_add(struct mtd_info
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
++static void mtd_check_of_node(struct mtd_info *mtd)
|
|
|
++{
|
|
|
++ struct device_node *partitions, *parent_dn, *mtd_dn = NULL;
|
|
|
++ const char *pname, *prefix = "partition-";
|
|
|
++ int plen, mtd_name_len, offset, prefix_len;
|
|
|
++ struct mtd_info *parent;
|
|
|
++ bool found = false;
|
|
|
++
|
|
|
++ /* Check if MTD already has a device node */
|
|
|
++ if (dev_of_node(&mtd->dev))
|
|
|
++ return;
|
|
|
++
|
|
|
++ /* Check if a partitions node exist */
|
|
|
++ parent = mtd->parent;
|
|
|
++ parent_dn = dev_of_node(&parent->dev);
|
|
|
++ if (!parent_dn)
|
|
|
++ return;
|
|
|
++
|
|
|
++ partitions = of_get_child_by_name(parent_dn, "partitions");
|
|
|
++ if (!partitions)
|
|
|
++ goto exit_parent;
|
|
|
++
|
|
|
++ prefix_len = strlen(prefix);
|
|
|
++ mtd_name_len = strlen(mtd->name);
|
|
|
++
|
|
|
++ /* Search if a partition is defined with the same name */
|
|
|
++ for_each_child_of_node(partitions, mtd_dn) {
|
|
|
++ offset = 0;
|
|
|
++
|
|
|
++ /* Skip partition with no/wrong prefix */
|
|
|
++ if (!of_node_name_prefix(mtd_dn, "partition-"))
|
|
|
++ continue;
|
|
|
++
|
|
|
++ /* Label have priority. Check that first */
|
|
|
++ if (of_property_read_string(mtd_dn, "label", &pname)) {
|
|
|
++ of_property_read_string(mtd_dn, "name", &pname);
|
|
|
++ offset = prefix_len;
|
|
|
++ }
|
|
|
++
|
|
|
++ plen = strlen(pname) - offset;
|
|
|
++ if (plen == mtd_name_len &&
|
|
|
++ !strncmp(mtd->name, pname + offset, plen)) {
|
|
|
++ found = true;
|
|
|
++ break;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ if (!found)
|
|
|
++ 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(partitions);
|
|
|
++exit_parent:
|
|
|
++ of_node_put(parent_dn);
|
|
|
++}
|
|
|
++
|
|
|
+ /**
|
|
|
+ * add_mtd_device - register an MTD device
|
|
|
+ * @mtd: pointer to new MTD device info structure
|
|
|
+@@ -666,6 +726,7 @@ int add_mtd_device(struct mtd_info *mtd)
|
|
|
+ mtd->dev.devt = MTD_DEVT(i);
|
|
|
+ dev_set_name(&mtd->dev, "mtd%d", i);
|
|
|
+ dev_set_drvdata(&mtd->dev, mtd);
|
|
|
++ mtd_check_of_node(mtd);
|
|
|
+ of_node_get(mtd_get_of_node(mtd));
|
|
|
+ error = device_register(&mtd->dev);
|
|
|
+ if (error)
|