All of lore.kernel.org
 help / color / mirror / Atom feed
From: Manikandan Muralidharan <manikandan.m@microchip.com>
To: <pratyush@kernel.org>, <mwalle@kernel.org>,
	<takahiro.kuwano@infineon.com>, <miquel.raynal@bootlin.com>,
	<richard@nod.at>, <vigneshr@ti.com>, <robh@kernel.org>,
	<krzk+dt@kernel.org>, <conor+dt@kernel.org>, <srini@kernel.org>,
	<nicolas.ferre@microchip.com>, <alexandre.belloni@bootlin.com>,
	<claudiu.beznea@tuxon.dev>, <linux@armlinux.org.uk>,
	<richardcochran@gmail.com>, <linusw@kernel.org>, <arnd@arndb.de>,
	<michael@walle.cc>, <linux-mtd@lists.infradead.org>,
	<devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>, <netdev@vger.kernel.org>
Cc: Manikandan Muralidharan <manikandan.m@microchip.com>
Subject: [PATCH v4 3/7] mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
Date: Tue, 30 Jun 2026 14:54:02 +0530	[thread overview]
Message-ID: <20260630092406.150587-4-manikandan.m@microchip.com> (raw)
In-Reply-To: <20260630092406.150587-1-manikandan.m@microchip.com>

Register the cached SFDP as a read-only NVMEM device rooted at the
flash's "sfdp" child node, exposing it in on-flash byte order. This lets
NVMEM cells reference any SFDP data: a fixed-layout for parameters at a
known offset, or an nvmem-layout parser for vendor data whose location
must be discovered at runtime. The device is only registered when an
"sfdp" node is present in the device tree.

Signed-off-by: Manikandan Muralidharan <manikandan.m@microchip.com>
---
 drivers/mtd/spi-nor/core.c |  5 +++
 drivers/mtd/spi-nor/core.h |  1 +
 drivers/mtd/spi-nor/sfdp.c | 83 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index ccf4396cdcd0..e04ba3e3dee9 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3204,6 +3204,11 @@ static int spi_nor_init_params(struct spi_nor *nor)
 		spi_nor_init_params_deprecated(nor);
 	}
 
+	/* Expose the SFDP as an NVMEM device. */
+	ret = spi_nor_register_sfdp_nvmem(nor);
+	if (ret)
+		return ret;
+
 	ret = spi_nor_late_init_params(nor);
 	if (ret)
 		return ret;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index ba2d1a862c9d..0a6484298c5c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -698,6 +698,7 @@ int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
 
 int spi_nor_check_sfdp_signature(struct spi_nor *nor);
 int spi_nor_parse_sfdp(struct spi_nor *nor);
+int spi_nor_register_sfdp_nvmem(struct spi_nor *nor);
 
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 4600983cb579..2df818bca6b5 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -6,6 +6,8 @@
 
 #include <linux/bitfield.h>
 #include <linux/mtd/spi-nor.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
 
@@ -1612,3 +1614,84 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 	kfree(param_headers);
 	return err;
 }
+
+static int spi_nor_sfdp_nvmem_read(void *priv, unsigned int offset,
+				   void *val, size_t bytes)
+{
+	struct spi_nor *nor = priv;
+	struct sfdp *sfdp = nor->sfdp;
+	size_t sfdp_size = sfdp->num_dwords * sizeof(*sfdp->dwords);
+
+	if (offset >= sfdp_size || bytes > sfdp_size - offset)
+		return -EINVAL;
+
+	/* The cached SFDP is kept in on-flash (little-endian) byte order. */
+	memcpy(val, (u8 *)sfdp->dwords + offset, bytes);
+
+	return 0;
+}
+
+static void spi_nor_sfdp_nvmem_put_np(void *data)
+{
+	of_node_put(data);
+}
+
+/**
+ * spi_nor_register_sfdp_nvmem() - expose the SFDP as a read-only NVMEM device
+ * @nor:	pointer to a 'struct spi_nor'
+ *
+ * Expose the whole SFDP, in on-flash byte order, as a read-only NVMEM device
+ * rooted at the flash's "sfdp" child node. This lets generic (fixed-layout) or
+ * vendor (nvmem-layout) cells reference any SFDP data. The device is only
+ * registered when an "sfdp" node is described in the device tree.
+ *
+ * Return: 0 on success or if there is nothing to do, -errno otherwise.
+ */
+int spi_nor_register_sfdp_nvmem(struct spi_nor *nor)
+{
+	struct device *dev = nor->dev;
+	struct nvmem_config config = { };
+	struct nvmem_device *nvmem;
+	struct device_node *np;
+	int ret;
+
+	if (!nor->sfdp)
+		return 0;
+
+	np = of_get_child_by_name(dev_of_node(dev), "sfdp");
+	if (!np)
+		return 0;
+
+	/*
+	 * Register the put before devm_nvmem_register() so it runs last on
+	 * detach, after the NVMEM device that uses the node is gone.
+	 */
+	ret = devm_add_action_or_reset(dev, spi_nor_sfdp_nvmem_put_np, np);
+	if (ret)
+		return ret;
+
+	config.dev = dev;
+	config.of_node = np;
+	config.name = "sfdp";
+	config.id = NVMEM_DEVID_AUTO;
+	config.owner = THIS_MODULE;
+	config.read_only = true;
+	config.word_size = 1;
+	config.stride = 1;
+	config.size = (int)(nor->sfdp->num_dwords * sizeof(*nor->sfdp->dwords));
+	config.reg_read = spi_nor_sfdp_nvmem_read;
+	config.priv = nor;
+
+	nvmem = devm_nvmem_register(dev, &config);
+	if (IS_ERR(nvmem)) {
+		/* NVMEM support is optional. */
+		if (PTR_ERR(nvmem) == -EOPNOTSUPP)
+			return 0;
+		return dev_err_probe(dev, PTR_ERR(nvmem),
+				     "failed to register SFDP NVMEM device\n");
+	}
+
+	dev_dbg(dev, "exposed %d-byte SFDP as an NVMEM device\n", config.size);
+
+	return 0;
+}
-- 
2.43.0


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

WARNING: multiple messages have this Message-ID (diff)
From: Manikandan Muralidharan <manikandan.m@microchip.com>
To: <pratyush@kernel.org>, <mwalle@kernel.org>,
	<takahiro.kuwano@infineon.com>, <miquel.raynal@bootlin.com>,
	<richard@nod.at>, <vigneshr@ti.com>, <robh@kernel.org>,
	<krzk+dt@kernel.org>, <conor+dt@kernel.org>, <srini@kernel.org>,
	<nicolas.ferre@microchip.com>, <alexandre.belloni@bootlin.com>,
	<claudiu.beznea@tuxon.dev>, <linux@armlinux.org.uk>,
	<richardcochran@gmail.com>, <linusw@kernel.org>, <arnd@arndb.de>,
	<michael@walle.cc>, <linux-mtd@lists.infradead.org>,
	<devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>, <netdev@vger.kernel.org>
Cc: Manikandan Muralidharan <manikandan.m@microchip.com>
Subject: [PATCH v4 3/7] mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
Date: Tue, 30 Jun 2026 14:54:02 +0530	[thread overview]
Message-ID: <20260630092406.150587-4-manikandan.m@microchip.com> (raw)
In-Reply-To: <20260630092406.150587-1-manikandan.m@microchip.com>

Register the cached SFDP as a read-only NVMEM device rooted at the
flash's "sfdp" child node, exposing it in on-flash byte order. This lets
NVMEM cells reference any SFDP data: a fixed-layout for parameters at a
known offset, or an nvmem-layout parser for vendor data whose location
must be discovered at runtime. The device is only registered when an
"sfdp" node is present in the device tree.

Signed-off-by: Manikandan Muralidharan <manikandan.m@microchip.com>
---
 drivers/mtd/spi-nor/core.c |  5 +++
 drivers/mtd/spi-nor/core.h |  1 +
 drivers/mtd/spi-nor/sfdp.c | 83 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index ccf4396cdcd0..e04ba3e3dee9 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3204,6 +3204,11 @@ static int spi_nor_init_params(struct spi_nor *nor)
 		spi_nor_init_params_deprecated(nor);
 	}
 
+	/* Expose the SFDP as an NVMEM device. */
+	ret = spi_nor_register_sfdp_nvmem(nor);
+	if (ret)
+		return ret;
+
 	ret = spi_nor_late_init_params(nor);
 	if (ret)
 		return ret;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index ba2d1a862c9d..0a6484298c5c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -698,6 +698,7 @@ int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
 
 int spi_nor_check_sfdp_signature(struct spi_nor *nor);
 int spi_nor_parse_sfdp(struct spi_nor *nor);
+int spi_nor_register_sfdp_nvmem(struct spi_nor *nor);
 
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 4600983cb579..2df818bca6b5 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -6,6 +6,8 @@
 
 #include <linux/bitfield.h>
 #include <linux/mtd/spi-nor.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
 
@@ -1612,3 +1614,84 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 	kfree(param_headers);
 	return err;
 }
+
+static int spi_nor_sfdp_nvmem_read(void *priv, unsigned int offset,
+				   void *val, size_t bytes)
+{
+	struct spi_nor *nor = priv;
+	struct sfdp *sfdp = nor->sfdp;
+	size_t sfdp_size = sfdp->num_dwords * sizeof(*sfdp->dwords);
+
+	if (offset >= sfdp_size || bytes > sfdp_size - offset)
+		return -EINVAL;
+
+	/* The cached SFDP is kept in on-flash (little-endian) byte order. */
+	memcpy(val, (u8 *)sfdp->dwords + offset, bytes);
+
+	return 0;
+}
+
+static void spi_nor_sfdp_nvmem_put_np(void *data)
+{
+	of_node_put(data);
+}
+
+/**
+ * spi_nor_register_sfdp_nvmem() - expose the SFDP as a read-only NVMEM device
+ * @nor:	pointer to a 'struct spi_nor'
+ *
+ * Expose the whole SFDP, in on-flash byte order, as a read-only NVMEM device
+ * rooted at the flash's "sfdp" child node. This lets generic (fixed-layout) or
+ * vendor (nvmem-layout) cells reference any SFDP data. The device is only
+ * registered when an "sfdp" node is described in the device tree.
+ *
+ * Return: 0 on success or if there is nothing to do, -errno otherwise.
+ */
+int spi_nor_register_sfdp_nvmem(struct spi_nor *nor)
+{
+	struct device *dev = nor->dev;
+	struct nvmem_config config = { };
+	struct nvmem_device *nvmem;
+	struct device_node *np;
+	int ret;
+
+	if (!nor->sfdp)
+		return 0;
+
+	np = of_get_child_by_name(dev_of_node(dev), "sfdp");
+	if (!np)
+		return 0;
+
+	/*
+	 * Register the put before devm_nvmem_register() so it runs last on
+	 * detach, after the NVMEM device that uses the node is gone.
+	 */
+	ret = devm_add_action_or_reset(dev, spi_nor_sfdp_nvmem_put_np, np);
+	if (ret)
+		return ret;
+
+	config.dev = dev;
+	config.of_node = np;
+	config.name = "sfdp";
+	config.id = NVMEM_DEVID_AUTO;
+	config.owner = THIS_MODULE;
+	config.read_only = true;
+	config.word_size = 1;
+	config.stride = 1;
+	config.size = (int)(nor->sfdp->num_dwords * sizeof(*nor->sfdp->dwords));
+	config.reg_read = spi_nor_sfdp_nvmem_read;
+	config.priv = nor;
+
+	nvmem = devm_nvmem_register(dev, &config);
+	if (IS_ERR(nvmem)) {
+		/* NVMEM support is optional. */
+		if (PTR_ERR(nvmem) == -EOPNOTSUPP)
+			return 0;
+		return dev_err_probe(dev, PTR_ERR(nvmem),
+				     "failed to register SFDP NVMEM device\n");
+	}
+
+	dev_dbg(dev, "exposed %d-byte SFDP as an NVMEM device\n", config.size);
+
+	return 0;
+}
-- 
2.43.0


  parent reply	other threads:[~2026-06-30  9:25 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-30  9:23 [PATCH v4 0/7] Read MAC address from SST vendor specific SFDP region Manikandan Muralidharan
2026-06-30  9:23 ` Manikandan Muralidharan
2026-06-30  9:24 ` [PATCH v4 1/7] dt-bindings: mtd: jedec,spi-nor: allow the SFDP to be exposed via NVMEM Manikandan Muralidharan
2026-06-30  9:24   ` Manikandan Muralidharan
2026-06-30 22:12   ` Linus Walleij
2026-06-30 22:12     ` Linus Walleij
2026-07-01  8:34     ` Michael Walle
2026-07-01  8:34       ` Michael Walle
2026-07-01 10:53       ` Linus Walleij
2026-07-01 10:53         ` Linus Walleij
2026-07-02  6:13         ` Manikandan.M
2026-07-02  6:13           ` Manikandan.M
2026-07-02  6:16   ` Krzysztof Kozlowski
2026-07-02  6:16     ` Krzysztof Kozlowski
2026-07-02  6:55     ` Manikandan.M
2026-07-02  6:55       ` Manikandan.M
2026-07-02 16:37       ` Rob Herring
2026-07-02 16:37         ` Rob Herring
2026-07-03 10:10         ` Miquel Raynal
2026-07-03 10:10           ` Miquel Raynal
2026-07-03 13:05           ` Michael Walle
2026-07-03 13:05             ` Michael Walle
2026-06-30  9:24 ` [PATCH v4 2/7] dt-bindings: nvmem: layouts: add Microchip/SST SFDP EUI layout Manikandan Muralidharan
2026-06-30  9:24   ` Manikandan Muralidharan
2026-06-30  9:24 ` Manikandan Muralidharan [this message]
2026-06-30  9:24   ` [PATCH v4 3/7] mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device Manikandan Muralidharan
2026-06-30 22:25   ` Linus Walleij
2026-06-30 22:25     ` Linus Walleij
2026-07-03  5:35   ` Takahiro.Kuwano
2026-07-03  5:35     ` Takahiro.Kuwano
2026-07-03  9:21     ` Takahiro.Kuwano
2026-07-03  9:21       ` Takahiro.Kuwano
2026-06-30  9:24 ` [PATCH v4 4/7] nvmem: layouts: add Microchip/SST SFDP EUI layout driver Manikandan Muralidharan
2026-06-30  9:24   ` Manikandan Muralidharan
2026-06-30  9:24 ` [PATCH v4 5/7] ARM: dts: microchip: sama5d27_wlsom1: use fixed-partitions for QSPI flash Manikandan Muralidharan
2026-06-30  9:24   ` Manikandan Muralidharan
2026-06-30 22:27   ` Linus Walleij
2026-06-30 22:27     ` Linus Walleij
2026-06-30  9:24 ` [PATCH v4 6/7] ARM: dts: microchip: sama5d27_wlsom1: read MAC address from QSPI SFDP Manikandan Muralidharan
2026-06-30  9:24   ` Manikandan Muralidharan
2026-06-30  9:24 ` [PATCH v4 7/7] ARM: configs: sama5: enable Microchip/SST SFDP EUI NVMEM layout Manikandan Muralidharan
2026-06-30  9:24   ` Manikandan Muralidharan

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=20260630092406.150587-4-manikandan.m@microchip.com \
    --to=manikandan.m@microchip.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=arnd@arndb.de \
    --cc=claudiu.beznea@tuxon.dev \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linusw@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux@armlinux.org.uk \
    --cc=michael@walle.cc \
    --cc=miquel.raynal@bootlin.com \
    --cc=mwalle@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=nicolas.ferre@microchip.com \
    --cc=pratyush@kernel.org \
    --cc=richard@nod.at \
    --cc=richardcochran@gmail.com \
    --cc=robh@kernel.org \
    --cc=srini@kernel.org \
    --cc=takahiro.kuwano@infineon.com \
    --cc=vigneshr@ti.com \
    /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.