107 lines
3.3 KiB
Diff
107 lines
3.3 KiB
Diff
From ad9b10d1eaada169bd764abcab58f08538877e26 Mon Sep 17 00:00:00 2001
|
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
|
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 <ansuelsmth@gmail.com>
|
|
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
|
|
Link: https://lore.kernel.org/linux-mtd/20220622010628.30414-4-ansuelsmth@gmail.com
|
|
---
|
|
drivers/mtd/mtdcore.c | 61 +++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 61 insertions(+)
|
|
|
|
--- a/drivers/mtd/mtdcore.c
|
|
+++ b/drivers/mtd/mtdcore.c
|
|
@@ -589,6 +589,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_get_master(mtd);
|
|
+ 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
|
|
@@ -672,6 +732,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) {
|