All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Marek Behún" <marek.behun@nic.cz>
To: u-boot@lists.denx.de
Cc: "Tom Rini" <trini@konsulko.com>,
	"Jagan Teki" <jagan@amarulasolutions.com>,
	"Priyanka Jain" <priyanka.jain@nxp.com>,
	"Simon Glass" <sjg@chromium.org>, "Heiko Schocher" <hs@denx.de>,
	"Patrick Delaunay" <patrick.delaunay@st.com>,
	"Patrice CHOTARD" <patrice.chotard@foss.st.com>,
	"Miquel Raynal" <miquel.raynal@bootlin.com>,
	"Marek Behún" <marek.behun@nic.cz>
Subject: [PATCH u-boot-dm + u-boot-spi v4 03/10] mtd: add support for parsing partitions defined in OF
Date: Wed, 26 May 2021 14:08:19 +0200	[thread overview]
Message-ID: <20210526120826.8045-4-marek.behun@nic.cz> (raw)
In-Reply-To: <20210526120826.8045-1-marek.behun@nic.cz>

Add support for parsing partitions defined in device-trees via the
`partitions` node with `fixed-partitions` compatible.

The `mtdparts`/`mtdids` mechanism takes precedence. If some partitions
are defined for a MTD device via this mechanism, the code won't register
partitions for that MTD device from OF, even if they are defined.

Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Patrice Chotard <patrice.chotard@foss.st.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Heiko Schocher <hs@denx.de>
Cc: Jagan Teki <jagan@amarulasolutions.com>
Cc: Patrick Delaunay <patrick.delaunay@st.com>
---
 drivers/mtd/mtd_uboot.c | 106 +++++++++++++++++++++++-----------------
 drivers/mtd/mtdpart.c   |  63 ++++++++++++++++++++++++
 include/linux/mtd/mtd.h |  10 ++++
 3 files changed, 135 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/mtd_uboot.c b/drivers/mtd/mtd_uboot.c
index c53ec657a3..4843cf1b84 100644
--- a/drivers/mtd/mtd_uboot.c
+++ b/drivers/mtd/mtd_uboot.c
@@ -198,53 +198,11 @@ static void mtd_del_all_parts(void)
 	} while (ret > 0);
 }
 
-int mtd_probe_devices(void)
+static int parse_mtdparts(const char *mtdparts, const char *mtdids)
 {
-	static char *old_mtdparts;
-	static char *old_mtdids;
-	const char *mtdparts = get_mtdparts();
-	const char *mtdids = get_mtdids();
-	const char *mtdparts_next = mtdparts;
+	const char *mtdparts_next;
 	struct mtd_info *mtd;
 
-	mtd_probe_uclass_mtd_devs();
-
-	/*
-	 * Check if mtdparts/mtdids changed, if the MTD dev list was updated
-	 * or if our previous attempt to delete existing partititions failed.
-	 * In any of these cases we want to update the partitions, otherwise,
-	 * everything is up-to-date and we can return 0 directly.
-	 */
-	if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) ||
-	    (mtdparts && old_mtdparts && mtdids && old_mtdids &&
-	     !mtd_dev_list_updated() && !mtd_del_all_parts_failed &&
-	     !strcmp(mtdparts, old_mtdparts) &&
-	     !strcmp(mtdids, old_mtdids)))
-		return 0;
-
-	/* Update the local copy of mtdparts */
-	free(old_mtdparts);
-	free(old_mtdids);
-	old_mtdparts = strdup(mtdparts);
-	old_mtdids = strdup(mtdids);
-
-	/*
-	 * Remove all old parts. Note that partition removal can fail in case
-	 * one of the partition is still being used by an MTD user, so this
-	 * does not guarantee that all old partitions are gone.
-	 */
-	mtd_del_all_parts();
-
-	/*
-	 * Call mtd_dev_list_updated() to clear updates generated by our own
-	 * parts removal loop.
-	 */
-	mtd_dev_list_updated();
-
-	/* If either mtdparts or mtdids is empty, then exit */
-	if (!mtdparts || !mtdids)
-		return 0;
-
 	/* Start the parsing by ignoring the extra 'mtdparts=' prefix, if any */
 	if (!strncmp(mtdparts, "mtdparts=", sizeof("mtdparts=") - 1))
 		mtdparts += 9;
@@ -343,6 +301,66 @@ int mtd_probe_devices(void)
 		put_mtd_device(mtd);
 	}
 
+	return 0;
+}
+
+int mtd_probe_devices(void)
+{
+	static char *old_mtdparts;
+	static char *old_mtdids;
+	const char *mtdparts = get_mtdparts();
+	const char *mtdids = get_mtdids();
+	struct mtd_info *mtd;
+
+	mtd_probe_uclass_mtd_devs();
+
+	/*
+	 * Check if mtdparts/mtdids changed, if the MTD dev list was updated
+	 * or if our previous attempt to delete existing partititions failed.
+	 * In any of these cases we want to update the partitions, otherwise,
+	 * everything is up-to-date and we can return 0 directly.
+	 */
+	if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) ||
+	    (mtdparts && old_mtdparts && mtdids && old_mtdids &&
+	     !mtd_dev_list_updated() && !mtd_del_all_parts_failed &&
+	     !strcmp(mtdparts, old_mtdparts) &&
+	     !strcmp(mtdids, old_mtdids)))
+		return 0;
+
+	/* Update the local copy of mtdparts */
+	free(old_mtdparts);
+	free(old_mtdids);
+	old_mtdparts = strdup(mtdparts);
+	old_mtdids = strdup(mtdids);
+
+	/*
+	 * Remove all old parts. Note that partition removal can fail in case
+	 * one of the partition is still being used by an MTD user, so this
+	 * does not guarantee that all old partitions are gone.
+	 */
+	mtd_del_all_parts();
+
+	/*
+	 * Call mtd_dev_list_updated() to clear updates generated by our own
+	 * parts removal loop.
+	 */
+	mtd_dev_list_updated();
+
+	/* If both mtdparts and mtdids are non-empty, parse */
+	if (mtdparts && mtdids) {
+		if (parse_mtdparts(mtdparts, mtdids) < 0)
+			printf("Failed parsing MTD partitions from mtdparts!\n");
+	}
+
+	/* Fallback to OF partitions */
+	mtd_for_each_device(mtd) {
+		if (list_empty(&mtd->partitions)) {
+			if (add_mtd_partitions_of(mtd) < 0)
+				printf("Failed parsing MTD %s OF partitions!\n",
+					mtd->name);
+		}
+	}
+
 	/*
 	 * Call mtd_dev_list_updated() to clear updates generated by our own
 	 * parts registration loop.
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index d064ac3048..aa58f722da 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -892,6 +892,69 @@ int add_mtd_partitions(struct mtd_info *master,
 	return 0;
 }
 
+#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(OF_CONTROL)
+int add_mtd_partitions_of(struct mtd_info *master)
+{
+	ofnode parts, child;
+	int i = 0;
+
+	if (!master->dev)
+		return 0;
+
+	parts = ofnode_find_subnode(mtd_get_ofnode(master), "partitions");
+	if (!ofnode_valid(parts) || !ofnode_is_available(parts) ||
+	    !ofnode_device_is_compatible(parts, "fixed-partitions"))
+		return 0;
+
+	ofnode_for_each_subnode(child, parts) {
+		struct mtd_partition part = { 0 };
+		struct mtd_info *slave;
+		fdt_addr_t offset, size;
+
+		if (!ofnode_is_available(child))
+			continue;
+
+		offset = ofnode_get_addr_size_index_notrans(child, 0, &size);
+		if (offset == FDT_ADDR_T_NONE || !size) {
+			debug("Missing partition offset/size on \"%s\" partition\n",
+			      master->name);
+			continue;
+		}
+
+		part.name = ofnode_read_string(child, "label");
+		if (!part.name)
+			part.name = ofnode_read_string(child, "name");
+
+		/*
+		 * .mask_flags is used to remove flags in allocate_partition(),
+		 * so when "read-only" is present, we add MTD_WRITABLE to the
+		 * mask, and so MTD_WRITABLE will be removed on partition
+		 * allocation
+		 */
+		if (ofnode_read_bool(child, "read-only"))
+			part.mask_flags |= MTD_WRITEABLE;
+		if (ofnode_read_bool(child, "lock"))
+			part.mask_flags |= MTD_POWERUP_LOCK;
+
+		part.offset = offset;
+		part.size = size;
+		part.ecclayout = master->ecclayout;
+
+		slave = allocate_partition(master, &part, i++, 0);
+		if (IS_ERR(slave))
+			return PTR_ERR(slave);
+
+		mutex_lock(&mtd_partitions_mutex);
+		list_add_tail(&slave->node, &master->partitions);
+		mutex_unlock(&mtd_partitions_mutex);
+
+		add_mtd_device(slave);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(OF_CONTROL) */
+
 #ifndef __UBOOT__
 static DEFINE_SPINLOCK(part_parser_lock);
 static LIST_HEAD(part_parsers);
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 927854950a..3b302fb8c3 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -581,6 +581,16 @@ static inline int del_mtd_partitions(struct mtd_info *mtd)
 }
 #endif
 
+#if defined(CONFIG_MTD_PARTITIONS) && CONFIG_IS_ENABLED(DM) && \
+    CONFIG_IS_ENABLED(OF_CONTROL)
+int add_mtd_partitions_of(struct mtd_info *master);
+#else
+static inline int add_mtd_partitions_of(struct mtd_info *master)
+{
+	return 0;
+}
+#endif
+
 struct mtd_info *__mtd_next_device(int i);
 #define mtd_for_each_device(mtd)			\
 	for ((mtd) = __mtd_next_device(0);		\
-- 
2.26.3


  parent reply	other threads:[~2021-05-26 12:09 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-26 12:08 [PATCH u-boot-dm + u-boot-spi v4 00/10] Support SPI NORs and OF partitions in `mtd list` Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 01/10] dm: core: add non-translating version of ofnode_get_addr_size_index() Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 02/10] dm: core: add ofnode_get_path() Marek Behún
2021-05-26 12:08 ` Marek Behún [this message]
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 04/10] mtd: spi-nor: allow registering multiple MTDs when DM is enabled Marek Behún
2021-07-07 23:54   ` Masami Hiramatsu
2021-07-08 14:15     ` Marek Behún
2021-07-08 14:56       ` Tom Rini
2021-07-09  0:19       ` Masami Hiramatsu
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 05/10] mtd: spi-nor: fill-in mtd->dev member Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 06/10] mtd: remove mtd_probe() function Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 07/10] mtd: probe SPI NOR devices in mtd_probe_devices() Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 08/10] cmd: mtd: print device OF path in listing Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 09/10] mtd: compare also with OF path and device name in get_mtd_device_nm() Marek Behún
2021-05-26 12:08 ` [PATCH u-boot-dm + u-boot-spi v4 10/10] cmd: mtd: expand <name> argument definition in command help Marek Behún
2021-05-26 16:58 ` [PATCH u-boot-dm + u-boot-spi v4 00/10] Support SPI NORs and OF partitions in `mtd list` Jagan Teki
2021-05-26 17:54   ` Marek Behún
2021-05-26 18:04     ` Jagan Teki
2021-06-02 14:03       ` Marek Behún
2021-06-24 11:36 ` Jagan Teki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210526120826.8045-4-marek.behun@nic.cz \
    --to=marek.behun@nic.cz \
    --cc=hs@denx.de \
    --cc=jagan@amarulasolutions.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=patrice.chotard@foss.st.com \
    --cc=patrick.delaunay@st.com \
    --cc=priyanka.jain@nxp.com \
    --cc=sjg@chromium.org \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.