Read MAC address from SST vendor specific SFDP region
Subsystems (8)
v8 cover Read MAC address from SST vendor specific SFDP region
Some Microchip/SST QSPI flashes (e.g. the SST26VF064BEUI) are factory programmed with globally unique, write-protected EUI-48 and EUI-64 identifiers stored in a vendor-specific SFDP parameter table. On boards that have no on-board EEPROM (sama5d27_wlsom1, sama5d29 curiosity, sam9x75 curiosity) this is a reliable source for an Ethernet MAC address, instead of relying on a U-Boot-provided or random address.
The series exposes the SFDP as a generic NVMEM framework with no vendor code in the SPI NOR core:
- The SPI NOR core exposes the entire SFDP as a generic read-only NVMEM device, rooted at a new "sfdp" child node of the flash.
- A new NVMEM layout driver (drivers/nvmem/layouts/) locates the Microchip vendor parameter table at runtime and presents the EUI-48 as a "mac-address" cell.
- Arbitrary parameters can be read with a standard fixed-layout (known offset) or with an nvmem-layout parser (location discovered at runtime).
Changes in v8:
- New 3/8 - nvmem: core: take a reference on dev.of_node in
nvmem_register(). v7's 3/8 (now 4/8) called of_node_put() right after devm_nvmem_register(), which left nvmem->dev.of_node backed by no reference at all once the caller's own reference was dropped. Fixing it at the nvmem_register() by taking its own of_node_get() when assigning nvmem->dev.of_node and released in nvmem_release().
- 6/8 - drop the #address-cells/#size-cells from the qspi1_flash node.
Changes in v7:
- 1/7 - Add blank lines in the "sfdp" schema per review;
Add Reviewed-by: Rob Herring.
- 2/7 - Add Reviewed-by: Rob Herring.
- 3/7 - Drop the spi_nor_sfdp_nvmem_put_np() helper and
call of_node_put() right after devm_nvmem_register().
- 6/7 - Note in the commit message that the sama5d27_wlsom1 SoM ships the factory-programmed SST26VF064BEUI, so the EUI-48 "mac-address" cell is always present.
Changes in v6:
- 3/7 - Move the SFDP NVMEM registration from sfdp.c into core.c, since sfdp.c is only for parsing the tables;use of_get_compatible_child() instead of the open-coded child-node lookup.
- 2/7, 6/7, 7/7 - Add Reviewed-by: Linus Walleij.
Changes in v5:
- 1/7 and 5/7 - Add R-b tags
- 3/7- Rework the comments, function name and commit message.Check all the nodes (for_each_available_child) for the right compatible "jedec,sfdp" instead of node name.
Changes in v4:
- Rework per v3 review: remove the vendor-specific SFDP handling from the SPI NOR core; expose the whole SFDP as a generic read-only NVMEM device and move the EUI extraction into an nvmem-layout driver.
- Introduce a new nvmem-layout driver to discover the vendor-table location at runtime; no offset hardcoded in the device tree.
- Describe the SFDP via a dedicated "sfdp" subnode (compatible "jedec,sfdp"), which also resolves the v3 dtbs_check "Unevaluated properties ('nvmem-layout')" warning.
- Reverse the stored EUI bytes into canonical MAC order.
- Enable the layout in sama5_defconfig.
Changes in v3:
- 2/3 - add support to update the QSPI partition into 'fixed-partition' binding in sama5d27_wlsom1
- 3/3 - add nvmem-layout in qspi node for EUI48 MAC Address and nvmem cell properties for macb node in sama5d27_wlsom1
Changes in v2:
- 1/3 - parse the SST vendor table, read and store the addresses into a resource - managed space. Register the addresses into NVMEM framework
- 2/3 - add support to update the QSPI partition into 'fixed-partition' binding
v7: https://lore.kernel.org/all/[email protected]/
Manikandan Muralidharan (8):
dt-bindings: mtd: jedec,spi-nor: allow the SFDP to be exposed via
NVMEM
dt-bindings: nvmem: layouts: add Microchip/SST SFDP EUI layout
nvmem: core: take a reference on dev.of_node in nvmem_register()
mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
nvmem: layouts: add Microchip/SST SFDP EUI layout driver
ARM: dts: microchip: sama5d27_wlsom1: use fixed-partitions for QSPI
flash
ARM: dts: microchip: sama5d27_wlsom1: read MAC address from QSPI SFDP
ARM: configs: sama5: enable Microchip/SST SFDP EUI NVMEM layout
.../bindings/mtd/jedec,spi-nor.yaml | 20 ++ .../layouts/microchip,sst26vf-sfdp-eui.yaml | 60 ++++++ .../bindings/nvmem/layouts/nvmem-layout.yaml | 1 + MAINTAINERS | 6 + .../dts/microchip/at91-sama5d27_wlsom1.dtsi | 63 +++--- .../dts/microchip/at91-sama5d27_wlsom1_ek.dts | 2 + arch/arm/configs/sama5_defconfig | 1 + drivers/mtd/spi-nor/core.c | 78 ++++++++ drivers/nvmem/core.c | 5 +- drivers/nvmem/layouts/Kconfig | 10 + drivers/nvmem/layouts/Makefile | 1 + drivers/nvmem/layouts/sst26vf-sfdp-eui.c | 182 ++++++++++++++++++ 12 files changed, 403 insertions(+), 26 deletions(-) create mode 100644 Documentation/devicetree/bindings/nvmem/layouts/microchip,sst26vf-sfdp-eui.yaml create mode 100644 drivers/nvmem/layouts/sst26vf-sfdp-eui.c
base-commit: 551c722f40809618230001baccf219193e22fc5a --
2.43.0
PATCH v8 1/8 dt-bindings: mtd: jedec,spi-nor: allow the SFDP to be exposed via NVMEM
Add an optional "sfdp" child node (compatible "jedec,sfdp") that describes the SFDP as a read-only NVMEM provider via nvmem.yaml, so its contents (e.g. a vendor EUI-48/EUI-64) can be read through NVMEM cells.
--- .../bindings/mtd/jedec,spi-nor.yaml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+)
Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml +20 -0
@@ -103,6 +103,22 @@ properties: spi-cpol: true spi-cpha: true + sfdp: + $ref: /schemas/nvmem/nvmem.yaml# + unevaluatedProperties: false + description: + The Serial Flash Discoverable Parameters (SFDP) tables exposed as a + read-only NVMEM device. This allows standard or vendor-specific SFDP + data (for example a factory-programmed EUI-48/EUI-64 identifier) to be + consumed through NVMEM cells. + + properties: + compatible: + const: jedec,sfdp + + required: + - compatible + dependencies: spi-cpol: [ spi-cpha ] spi-cpha: [ spi-cpol ]
@@ -122,6 +138,10 @@ examples: spi-max-frequency = <40000000>; m25p,fast-read; reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + + sfdp { + compatible = "jedec,sfdp"; + }; }; }; ...
Signature · 1 line
2.43.0
PATCH v8 2/8 dt-bindings: nvmem: layouts: add Microchip/SST SFDP EUI layout
In reply to Manikandan MuralidharanAdd a binding for the NVMEM layout that exposes the factory-programmed EUI-48 identifier from the Microchip/SST vendor-specific SFDP parameter table (e.g. SST26VF064BEUI) as a "mac-address" NVMEM cell, and reference it from nvmem-layout.yaml.
--- .../layouts/microchip,sst26vf-sfdp-eui.yaml | 60 +++++++++++++++++++ .../bindings/nvmem/layouts/nvmem-layout.yaml | 1 + 2 files changed, 61 insertions(+) create mode 100644 Documentation/devicetree/bindings/nvmem/layouts/microchip,sst26vf-sfdp-eui.yaml
Documentation/devicetree/bindings/nvmem/layouts/microchip,sst26vf-sfdp-eui.yaml new file +60 -0
@@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/nvmem/layouts/microchip,sst26vf-sfdp-eui.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVMEM layout of the Microchip/SST SFDP EUI-48 identifier + +maintainers: + - Manikandan Muralidharan <[email protected]> + +description: + Some Microchip/SST serial flashes (for example the SST26VF064BEUI) are + factory programmed with a globally unique EUI-48 identifier stored in a + vendor-specific SFDP parameter table and permanently write-protected. This + layout locates that table and exposes the EUI-48 as an NVMEM cell so that, + for example, a network driver can use it as a MAC address. The location of + the data is discovered at runtime from the SFDP; no offset is encoded in the + device tree. + +select: false + +properties: + compatible: + const: microchip,sst26vf-sfdp-eui + + mac-address: + type: object + description: + The factory-programmed EUI-48 identifier, usable as a MAC address. + additionalProperties: false + +required: + - compatible + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + + sfdp { + compatible = "jedec,sfdp"; + + nvmem-layout { + compatible = "microchip,sst26vf-sfdp-eui"; + + mac-address { + }; + }; + }; + }; + }; +...
Documentation/devicetree/bindings/nvmem/layouts/nvmem-layout.yaml +1 -0
@@ -20,6 +20,7 @@ description: | oneOf: - $ref: fixed-layout.yaml - $ref: kontron,sl28-vpd.yaml + - $ref: microchip,sst26vf-sfdp-eui.yaml - $ref: onie,tlv-layout.yaml - $ref: u-boot,env.yaml
Signature · 1 line
2.43.0
PATCH v8 3/8 nvmem: core: take a reference on dev.of_node in nvmem_register()
In reply to Manikandan Muralidharannvmem_register() stores config->of_node (or config->dev->of_node) into nvmem->dev.of_node without taking its own reference. Callers that get the node via of_get_compatible_child() etc. and drop their reference right after registering leave nvmem->dev.of_node backed by no reference at all.
Take an of_node_get() when assigning nvmem->dev.of_node and release it in nvmem_release(). Existing callers that hold their own get/put pair around the registration call need no changes, since get/put on a device_node is per-holder and independent of core now also holding one.
--- drivers/nvmem/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/nvmem/core.c +3 -2
@@ -541,6 +541,7 @@ static void nvmem_release(struct device *dev)ida_free (&nvmem_ida, nvmem->id);gpiod_put (nvmem->wp_gpio); +of_node_put (nvmem->dev.of_node);kfree (nvmem->ops);kfree (nvmem); }
@@ -950,9 +951,9 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->keepout = config->keepout; nvmem->nkeepout = config->nkeepout;if (config->of_node) - nvmem->dev.of_node = config->of_node; + nvmem->dev.of_node =of_node_get (config->of_node);else - nvmem->dev.of_node = config->dev->of_node; + nvmem->dev.of_node =of_node_get (config->dev->of_node);switch (config->id) {case NVMEM_DEVID_NONE :
Signature · 1 line
2.43.0
Re: [PATCH v8 3/8] nvmem: core: take a reference on dev.of_node in nvmem_register()
Quoted 6 lines · Manikandan Muralidharan
nvmem_register()storesconfig->of_node(orconfig->dev->of_node) intonvmem->dev.of_nodewithout taking its own reference. Callers that get the node viaof_get_compatible_child()etc. and drop their reference right after registering leavenvmem->dev.of_nodebacked by no reference at all.
Quoted 8 lines
Take an
of_node_get()when assigningnvmem->dev.of_nodeand release it innvmem_release(). Existing callers that hold their own get/put pair around the registration call need no changes, since get/put on adevice_nodeis per-holder and independent of core now also holding one.Suggested-by Michael Walle <[email protected]>Signed-off-by Manikandan Muralidharan <[email protected]>
Re: [PATCH v8 3/8] nvmem: core: take a reference on dev.of_node in nvmem_register()
In reply to Manikandan MuralidharanQuoted 6 lines · Manikandan Muralidharan
nvmem_register()storesconfig->of_node(orconfig->dev->of_node) intonvmem->dev.of_nodewithout taking its own reference. Callers that get the node viaof_get_compatible_child()etc. and drop their reference right after registering leavenvmem->dev.of_nodebacked by no reference at all.
Quoted 8 lines
Take an
of_node_get()when assigningnvmem->dev.of_nodeand release it innvmem_release(). Existing callers that hold their own get/put pair around the registration call need no changes, since get/put on adevice_nodeis per-holder and independent of core now also holding one.Suggested-by Michael Walle <[email protected]>Signed-off-by Manikandan Muralidharan <[email protected]>
Nice!
Did you check if any callers are also taking a reference, which might not be needed anymore now.
-michael
Quoted 18 lines
--- drivers/nvmem/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/nvmem/core.c +1
-0@@ -541,6 +541,7 @@ static void nvmem_release(struct device *dev)ida_free (&nvmem_ida, nvmem->id);gpiod_put (nvmem->wp_gpio); +of_node_put (nvmem->dev.of_node);kfree (nvmem->ops);kfree (nvmem); }@@ -950,9 +951,9 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->keepout = config->keepout;
drivers/nvmem/core.c struct nvmem_device *nvmem_register(const struct nvmem_config *config) · line 959
Quoted 10 lines
drivers/nvmem/core.c +2
-2nvmem->nkeepout = config->nkeepout;if (config->of_node) - nvmem->dev.of_node = config->of_node; + nvmem->dev.of_node =of_node_get (config->of_node);else - nvmem->dev.of_node = config->dev->of_node; + nvmem->dev.of_node =of_node_get (config->dev->of_node);switch (config->id) {case NVMEM_DEVID_NONE :
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
Re: [PATCH v8 3/8] nvmem: core: take a reference on dev.of_node in nvmem_register()
Hi Michael,
Quoted 13 lines · Michael Walle
Quoted 12 lines · Manikandan Muralidharan
nvmem_register()storesconfig->of_node(orconfig->dev->of_node) intonvmem->dev.of_nodewithout taking its own reference. Callers that get the node viaof_get_compatible_child()etc. and drop their reference right after registering leavenvmem->dev.of_nodebacked by no reference at all.Take an
of_node_get()when assigningnvmem->dev.of_nodeand release it innvmem_release(). Existing callers that hold their own get/put pair around the registration call need no changes, since get/put on adevice_nodeis per-holder and independent of core now also holding one.
Quoted 8 lines
Quoted 2 lines
Suggested-by Michael Walle <[email protected]>Signed-off-by Manikandan Muralidharan <[email protected]>Nice!
Did you check if any callers are also taking a reference, which might not be needed anymore now.
Yes, I checked — none of the callers hold a reference beyond the registration call itself. The pattern I verified in each drivers is short-lived, the reference is dropped right after nvmem_register()/devm_nvmem_register() call.
Quoted 33 lines
Reviewed-by Michael Walle <[email protected]>-michael
Quoted 28 lines
--- drivers/nvmem/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/nvmem/core.c +3
-2@@ -541,6 +541,7 @@ static void nvmem_release(struct device *dev)ida_free (&nvmem_ida, nvmem->id);gpiod_put (nvmem->wp_gpio); +of_node_put (nvmem->dev.of_node);kfree (nvmem->ops);kfree (nvmem); }@@ -950,9 +951,9 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->keepout = config->keepout; nvmem->nkeepout = config->nkeepout;if (config->of_node) - nvmem->dev.of_node = config->of_node; + nvmem->dev.of_node =of_node_get (config->of_node);else - nvmem->dev.of_node = config->dev->of_node; + nvmem->dev.of_node =of_node_get (config->dev->of_node);switch (config->id) {case NVMEM_DEVID_NONE :
Signature · 2 lines
Thanks and Regards, Manikandan M.
PATCH v8 4/8 mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
In reply to Manikandan MuralidharanThe SPI NOR core already reads the SFDP tables during enumeration and caches them in nor->sfdp->dwords (see spi_nor_parse_sfdp()). Re-expose that cached data as a read-only NVMEM device, in on-flash byte order, rooted at the flash's SFDP child node (compatible "jedec,sfdp").
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.
--- drivers/mtd/spi-nor/core.c | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+)
drivers/mtd/spi-nor/core.c +78 -0
@@ -17,6 +17,7 @@#include <linux/mtd/mtd.h> #include <linux/mtd/spi-nor.h> #include <linux/mutex.h> +#include <linux/nvmem-provider.h> #include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/sched/task_stack.h>
@@ -3001,6 +3002,75 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor) nor->flags |=SNOR_F_IO_MODE_EN_VOLATILE ; } +static int spi_nor_sfdp_reg_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 ; +} + +/** +* 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 (compatible "jedec,sfdp"). This lets +* generic (fixed-layout) or vendor (nvmem-layout) cells reference any SFDP +* data. The device is only registered when a child node with the "jedec,sfdp" +* compatible is described in the device tree. +* +* Return: 0 on success or if there is nothing to do, -errno otherwise. +*/ +static 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; + +if (!nor->sfdp) +return 0 ; + + np =of_get_compatible_child (dev_of_node (dev),"jedec,sfdp" ); +if (!np) +return 0 ; + + 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_reg_read; + config.priv = nor; + + nvmem =devm_nvmem_register (dev, &config); +of_node_put (np); +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 ; +} +/** * spi_nor_late_init_params() - Late initialization of default flash parameters. * @nor: pointer to a 'struct spi_nor'
@@ -3204,6 +3274,14 @@ static int spi_nor_init_params(struct spi_nor *nor)spi_nor_init_params_deprecated (nor); } +/* +* Expose the SFDP table as an NVMEM device only when +* the flash actually provides one +*/ + ret =spi_nor_register_sfdp_nvmem (nor); +if (ret) +return ret; + ret =spi_nor_late_init_params (nor);if (ret)return ret;
Signature · 1 line
2.43.0
Re: [PATCH v8 4/8] mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
Quoted 11 lines · Manikandan Muralidharan
The SPI NOR core already reads the SFDP tables during enumeration and caches them in
nor->sfdp->dwords(seespi_nor_parse_sfdp()). Re-expose that cached data as a read-only NVMEM device, in on-flash byte order, rooted at the flash's SFDP child node (compatible "jedec,sfdp").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 <[email protected]>
[email protected]
AI reviewRe: [PATCH v8 4/8] mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
In reply to Manikandan MuralidharanThank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] mtd: spi-nor: UAF of SFDP cached data via NVMEM cell consumer after unbind --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] mtd: spi-nor: UAF of SFDP cached data via NVMEM cell consumer after unbind --
commit 27ebe83329cdf6f2e062cc50041bbf3a877fcaba
Author: Manikandan Muralidharan <[email protected]>
mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
This commit exposes the SFDP tables read from the SPI NOR flash as a read-only NVMEM device. The device is conditionally registered when a jedec,sfdp child node is present in the device tree, allowing consumers to reference any SFDP data.
Quoted 3 lines
drivers/mtd/spi-nor/core.c +0
-0
[ ... ]
drivers/mtd/spi-nor/core.c static void spi_nor_init_fixup_flags(struct spi_nor *nor) · line 3016
Quoted 12 lines
drivers/mtd/spi-nor/core.c +12
-0+static int spi_nor_sfdp_reg_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);
[Severity: High]
Does this code introduce a potential use-after-free if the SPI NOR device is unbound while an NVMEM cell consumer still holds a reference?
When an in-kernel consumer driver obtains an NVMEM cell reference to the SFDP device, it increments the nvmem_device reference count. Later, if the SPI NOR device is unbound via sysfs, the devres framework runs devm_nvmem_unregister.
Looking at nvmem_unregister in drivers/nvmem/core.c, it only drops the provider's reference count. It does not explicitly block future reads, clear the operations pointer, or disconnect active consumers. Because the consumer still holds a cell reference, the nvmem_device object and its reg_read ops remain active.
Devres then proceeds to free the nor struct and nor->sfdp->dwords buffers which were allocated earlier in the probe sequence.
If the consumer subsequently calls nvmem_cell_read, the read is forwarded to spi_nor_sfdp_reg_read, which dereferences the already freed nor and sfdp memory.
Quoted 3 lines
drivers/mtd/spi-nor/core.c +3
-0+ +return 0 ; +}
[ ... ]
Quoted 17 lines
drivers/mtd/spi-nor/core.c +17
-0+static 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; + +if (!nor->sfdp) +return 0 ; + + np =of_get_compatible_child (dev_of_node (dev),"jedec,sfdp" ); +if (!np) +return 0 ; + + config.dev = dev; + config.of_node = np; + config.name ="sfdp" ;
drivers/mtd/spi-nor/core.c static void spi_nor_init_fixup_flags(struct spi_nor *nor) · line 3059
Quoted 10 lines
drivers/mtd/spi-nor/core.c +10
-0+ 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_reg_read; + config.priv = nor; + + nvmem =devm_nvmem_register (dev, &config);
[Severity: High]
Is there a risk to binding the NVMEM registration to the devres lifecycle here?
Since devres tears down in reverse order, devm_nvmem_unregister will run before the SFDP memory is freed. But as noted above, this does not safely destroy the NVMEM device if a consumer is holding a cell reference, allowing the operations pointer to outlive the memory it accesses.
Quoted 2 lines
drivers/mtd/spi-nor/core.c +2
-0+of_node_put (np); +if (IS_ERR (nvmem)) {
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Re: [PATCH v8 4/8] mtd: spi-nor: sfdp: expose the SFDP as a read-only NVMEM device
In reply to Manikandan MuralidharanQuoted 62 lines · Manikandan Muralidharan
The SPI NOR core already reads the SFDP tables during enumeration and caches them in
nor->sfdp->dwords(seespi_nor_parse_sfdp()). Re-expose that cached data as a read-only NVMEM device, in on-flash byte order, rooted at the flash's SFDP child node (compatible "jedec,sfdp").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 <[email protected]>--- drivers/mtd/spi-nor/core.c | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+)drivers/mtd/spi-nor/core.c +32
-0@@ -17,6 +17,7 @@#include <linux/mtd/mtd.h> #include <linux/mtd/spi-nor.h> #include <linux/mutex.h> +#include <linux/nvmem-provider.h> #include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/sched/task_stack.h> @@ -3001,6 +3002,75 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor) nor->flags |=SNOR_F_IO_MODE_EN_VOLATILE ; } +static int spi_nor_sfdp_reg_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 ; +} + +/** +* 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 (compatible "jedec,sfdp"). This lets +* generic (fixed-layout) or vendor (nvmem-layout) cells reference any SFDP +* data. The device is only registered when a child node with the "jedec,sfdp" +* compatible is described in the device tree. +* +* Return: 0 on success or if there is nothing to do, -errno otherwise. +*/ +static int spi_nor_register_sfdp_nvmem (struct spi_nor *nor) +{ +struct device *dev = nor->dev;
drivers/mtd/spi-nor/core.c static void spi_nor_init_fixup_flags(struct spi_nor *nor) · line 3045
Quoted 10 lines
drivers/mtd/spi-nor/core.c +10
-0+struct nvmem_config config = { }; +struct nvmem_device *nvmem; +struct device_node *np; + +if (!nor->sfdp) +return 0 ; + + np =of_get_compatible_child (dev_of_node (dev),"jedec,sfdp" ); +if (!np) +return 0 ;
I've missed replying to your former question about this, sorry. Yeah I was implying to always add the nvmem device regardless of the device tree. I don't see a reason why it should only be added if dt node is there. Userspace might still do something useful with it.
So if you'll respin a new version you can remove the check, otherwise it could be a follow-up patch.
-michael
Quoted 46 lines
drivers/mtd/spi-nor/core.c +36
-0+ + 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_reg_read; + config.priv = nor; + + nvmem =devm_nvmem_register (dev, &config); +of_node_put (np); +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 ; +} +/** * spi_nor_late_init_params() - Late initialization of default flash parameters. * @nor: pointer to a 'struct spi_nor' @@ -3204,6 +3274,14 @@ static int spi_nor_init_params(struct spi_nor *nor)spi_nor_init_params_deprecated (nor); } +/* +* Expose the SFDP table as an NVMEM device only when +* the flash actually provides one +*/ + ret =spi_nor_register_sfdp_nvmem (nor); +if (ret) +return ret; + ret =spi_nor_late_init_params (nor);if (ret)return ret;
PATCH v8 5/8 nvmem: layouts: add Microchip/SST SFDP EUI layout driver
In reply to Manikandan MuralidharanAdd an NVMEM layout that exposes the factory-programmed EUI-48 identifier from the Microchip/SST vendor SFDP parameter table (e.g. SST26VF064BEUI) as a "mac-address" cell, for use as a network MAC address. The vendor table is located at runtime via the SFDP NVMEM device (no offset in DT), and a read_post_process callback reverses the LSB-first bytes into canonical MAC order. Binds to an "nvmem-layout" node with compatible "microchip,sst26vf-sfdp-eui".
--- MAINTAINERS | 6 + drivers/nvmem/layouts/Kconfig | 10 ++ drivers/nvmem/layouts/Makefile | 1 + drivers/nvmem/layouts/sst26vf-sfdp-eui.c | 182 +++++++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 drivers/nvmem/layouts/sst26vf-sfdp-eui.c
MAINTAINERS +6 -0
@@ -18001,6 +18001,12 @@ F: Documentation/devicetree/bindings/sound/atmel,at91-ssc.yaml F: drivers/misc/atmel-ssc.c F: include/linux/atmel-ssc.h +MICROCHIP SST SFDP EUI NVMEM LAYOUT DRIVER +M: Manikandan Muralidharan <[email protected]> +S: Maintained +F: Documentation/devicetree/bindings/nvmem/layouts/microchip,sst26vf-sfdp-eui.yaml +F: drivers/nvmem/layouts/sst26vf-sfdp-eui.c + Microchip Timer Counter Block (TCB) Capture Driver M: Kamel Bouhara <[email protected]> L: [email protected] (moderated for non-subscribers)
drivers/nvmem/layouts/Kconfig +10 -0
@@ -26,6 +26,16 @@ config NVMEM_LAYOUT_ONIE_TLV If unsure, say N. +config NVMEM_LAYOUT_SST26VF_SFDP_EUI + tristate "Microchip/SST SFDP EUI-48 layout support" + help + Say Y here if you want to expose the factory-programmed EUI-48 + identifier stored in the Microchip/SST vendor-specific SFDP parameter + table (e.g. SST26VF064BEUI) as NVMEM cells, so that network drivers + can use them as a MAC address. + + If unsure, say N. + config NVMEM_LAYOUT_U_BOOT_ENV tristate "U-Boot environment variables layout" select CRC32
drivers/nvmem/layouts/Makefile +1 -0
@@ -6,4 +6,5 @@ obj-$(CONFIG_NVMEM_LAYOUTS) += fixed-layout.o obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o +obj-$(CONFIG_NVMEM_LAYOUT_SST26VF_SFDP_EUI) += sst26vf-sfdp-eui.o obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o
drivers/nvmem/layouts/sst26vf-sfdp-eui.c new file +182 -0
182 lines not on this page · raw message
Signature · 1 line
2.43.0
Miquel Raynal
maintainerRe: [PATCH v8 5/8] nvmem: layouts: add Microchip/SST SFDP EUI layout driver
Hi,
Quoted 9 lines · Manikandan Muralidharan
Add an NVMEM layout that exposes the factory-programmed EUI-48 identifier from the Microchip/SST vendor SFDP parameter table (e.g. SST26VF064BEUI) as a "mac-address" cell, for use as a network MAC address. The vendor table is located at runtime via the SFDP NVMEM device (no offset in DT), and a
read_post_processcallback reverses the LSB-first bytes into canonical MAC order. Binds to an "nvmem-layout" node with compatible "microchip,sst26vf-sfdp-eui".Signed-off-by Manikandan Muralidharan <[email protected]>
Mostly minor nits, see below.
drivers/nvmem/layouts/Makefile line 10
Quoted 8 lines
drivers/nvmem/layouts/Makefile +1
-0@@ -6,4 +6,5 @@ obj-$(CONFIG_NVMEM_LAYOUTS) += fixed-layout.o obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o +obj-$(CONFIG_NVMEM_LAYOUT_SST26VF_SFDP_EUI) += sst26vf-sfdp-eui.o obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o
Not sure this is ordered alphabetically, so in general add it at the end.
Quoted 14 lines
drivers/nvmem/layouts/Makefile +14
-0+/* SFDP header and parameter header, as laid out on the flash. */ +struct sfdp_header { + u8 signature[4]; + u8 minor; + u8 major; + u8 nph; + u8 unused; +}; + +struct sfdp_parameter_header { + u8 id_lsb; + u8 minor; + u8 major; + u8 length;
drivers/nvmem/layouts/Makefile
Quoted 10 lines
drivers/nvmem/layouts/Makefile +10
-0+ u8 parameter_table_pointer[3]; + u8 id_msb; +}; + +#define SFDP_SIGNATURE 0x50444653U + +#define SFDP_PARAM_HEADER_ID(h) (((h)->id_msb << 8) | (h)->id_lsb) +#define SFDP_PARAM_HEADER_PTP(h) get_unaligned_le24((h)->parameter_table_pointer) + +/* Microchip (vendor) parameter table identifier: id_msb << 8 | id_lsb. */
This is not relevant, we saw it just above ^^^^^^^^^^^^^^^^^^^^^^^
drivers/nvmem/layouts/Makefile
Quoted 13 lines
drivers/nvmem/layouts/Makefile +13
-0+#define SFDP_MCHP_VENDOR_ID 0x01bf + +#define SFDP_MCHP_EUI48_MARKER_OFFSET 0x60 +#define SFDP_MCHP_EUI48_MARKER 0x30 +#define SFDP_MCHP_EUI48_OFFSET 0x61 + +static int sfdp_eui_read_post_process(void *priv, const char *id, int index, + unsigned int offset, void *buf, + size_t bytes) +{ + u8 *data = buf; + int i; +
I believe the if against the length is wrong and should be inverted and placed here:
if (bytes != ETH_ALEN)
return -EINVAL;Since lenght does not change, prefer to bail out early.
drivers/nvmem/layouts/Makefile
Quoted 5 lines
drivers/nvmem/layouts/Makefile +5
-0+ /* SFDP stores the address least-significant octet first; reverse it. */ + for (i = 0; i < bytes / 2; i++) + swap(data[i], data[bytes - 1 - i]); + + if (bytes == ETH_ALEN && !is_valid_ether_addr(buf))
Is bytes != ETH_ALEN a valid use case?
Quoted 10 lines
drivers/nvmem/layouts/Makefile +10
-0+ return -EINVAL; + + return 0; +} + +static int sfdp_eui_find_vendor_table(struct nvmem_device *nvmem, u32 *ptp) +{ + struct sfdp_parameter_header ph; + struct sfdp_header hdr; + int nph, i, ret;
drivers/nvmem/layouts/Makefile
Quoted 10 lines
drivers/nvmem/layouts/Makefile +10
-0+ + ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); + if (ret < 0) + return ret; + + if (get_unaligned_le32(hdr.signature) != SFDP_SIGNATURE) + return -EINVAL; + + /* The number of parameter headers (NPH) field is zero-based. */ + nph = hdr.nph;
nph = hdr.nph + 1 ?
drivers/nvmem/layouts/Makefile
Quoted 2 lines
drivers/nvmem/layouts/Makefile +2
-0+ + for (i = 0; i <= nph; i++) {
and here the usual i < nph?
Quoted 14 lines
drivers/nvmem/layouts/Makefile +14
-0+ ret = nvmem_device_read(nvmem, sizeof(hdr) + i * sizeof(ph), + sizeof(ph), &ph); + if (ret < 0) + return ret; + + if (SFDP_PARAM_HEADER_ID(&ph) != SFDP_MCHP_VENDOR_ID) + continue; + + *ptp = SFDP_PARAM_HEADER_PTP(&ph); + return 0; + } + + return -ENOENT; +}
...
drivers/nvmem/layouts/Makefile
Quoted 11 lines
drivers/nvmem/layouts/Makefile +11
-0+ info.name = "mac-address"; + info.offset = base + SFDP_MCHP_EUI48_OFFSET; + info.bytes = ETH_ALEN; + info.np = of_get_child_by_name(layout_np, "mac-address"); + info.read_post_process = sfdp_eui_read_post_process; + + ret = nvmem_add_one_cell(nvmem, &info); + if (ret) + of_node_put(info.np); + else + dev_dbg(dev, "exposed EUI-48 at SFDP offset 0x%x\n", info.offset);
This one is not really useful anymore.
drivers/nvmem/layouts/Makefile
Quoted 6 lines
drivers/nvmem/layouts/Makefile +6
-0+ + of_node_put(layout_np); + + return ret; +} +
Thanks,
Miquèl
Re: [PATCH v8 5/8] nvmem: layouts: add Microchip/SST SFDP EUI layout driver
Hi Miquel,
Thanks for the review — all valid, I will fix in v9.
Quoted 153 lines · Miquel Raynal
EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
Hi,
Quoted 9 lines · Manikandan Muralidharan
Add an NVMEM layout that exposes the factory-programmed EUI-48 identifier from the Microchip/SST vendor SFDP parameter table (e.g. SST26VF064BEUI) as a "mac-address" cell, for use as a network MAC address. The vendor table is located at runtime via the SFDP NVMEM device (no offset in DT), and a
read_post_processcallback reverses the LSB-first bytes into canonical MAC order. Binds to an "nvmem-layout" node with compatible "microchip,sst26vf-sfdp-eui".Signed-off-by Manikandan Muralidharan <[email protected]>Mostly minor nits, see below.
drivers/nvmem/layouts/Makefile line 10
Quoted 8 lines
drivers/nvmem/layouts/Makefile +1
-0@@ -6,4 +6,5 @@ obj-$(CONFIG_NVMEM_LAYOUTS) += fixed-layout.o obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o +obj-$(CONFIG_NVMEM_LAYOUT_SST26VF_SFDP_EUI) += sst26vf-sfdp-eui.o obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.oNot sure this is ordered alphabetically, so in general add it at the end.
Quoted 14 lines
drivers/nvmem/layouts/Makefile +14
-0+/* SFDP header and parameter header, as laid out on the flash. */ +struct sfdp_header { + u8 signature[4]; + u8 minor; + u8 major; + u8 nph; + u8 unused; +}; + +struct sfdp_parameter_header { + u8 id_lsb; + u8 minor; + u8 major; + u8 length;drivers/nvmem/layouts/Makefile
Quoted 10 lines
drivers/nvmem/layouts/Makefile +10
-0+ u8 parameter_table_pointer[3]; + u8 id_msb; +}; + +#define SFDP_SIGNATURE 0x50444653U + +#define SFDP_PARAM_HEADER_ID(h) (((h)->id_msb << 8) | (h)->id_lsb) +#define SFDP_PARAM_HEADER_PTP(h) get_unaligned_le24((h)->parameter_table_pointer) + +/* Microchip (vendor) parameter table identifier: id_msb << 8 | id_lsb. */This is not relevant, we saw it just above ^^^^^^^^^^^^^^^^^^^^^^^
drivers/nvmem/layouts/Makefile
Quoted 13 lines
drivers/nvmem/layouts/Makefile +13
-0+#define SFDP_MCHP_VENDOR_ID 0x01bf + +#define SFDP_MCHP_EUI48_MARKER_OFFSET 0x60 +#define SFDP_MCHP_EUI48_MARKER 0x30 +#define SFDP_MCHP_EUI48_OFFSET 0x61 + +static int sfdp_eui_read_post_process(void *priv, const char *id, int index, + unsigned int offset, void *buf, + size_t bytes) +{ + u8 *data = buf; + int i; +I believe the if against the length is wrong and should be inverted and placed here:
if (bytes != ETH_ALEN) return -EINVAL;Since lenght does not change, prefer to bail out early.
drivers/nvmem/layouts/Makefile
Quoted 5 lines
drivers/nvmem/layouts/Makefile +5
-0+ /* SFDP stores the address least-significant octet first; reverse it. */ + for (i = 0; i < bytes / 2; i++) + swap(data[i], data[bytes - 1 - i]); + + if (bytes == ETH_ALEN && !is_valid_ether_addr(buf))Is bytes !=
ETH_ALENa valid use case?Quoted 10 lines
drivers/nvmem/layouts/Makefile +10
-0+ return -EINVAL; + + return 0; +} + +static int sfdp_eui_find_vendor_table(struct nvmem_device *nvmem, u32 *ptp) +{ + struct sfdp_parameter_header ph; + struct sfdp_header hdr; + int nph, i, ret;drivers/nvmem/layouts/Makefile
Quoted 10 lines
drivers/nvmem/layouts/Makefile +10
-0+ + ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); + if (ret < 0) + return ret; + + if (get_unaligned_le32(hdr.signature) != SFDP_SIGNATURE) + return -EINVAL; + + /* The number of parameter headers (NPH) field is zero-based. */ + nph = hdr.nph;nph = hdr.nph + 1 ?
drivers/nvmem/layouts/Makefile
Quoted 2 lines
drivers/nvmem/layouts/Makefile +2
-0+ + for (i = 0; i <= nph; i++) {and here the usual i < nph?
Quoted 14 lines
drivers/nvmem/layouts/Makefile +14
-0+ ret = nvmem_device_read(nvmem, sizeof(hdr) + i * sizeof(ph), + sizeof(ph), &ph); + if (ret < 0) + return ret; + + if (SFDP_PARAM_HEADER_ID(&ph) != SFDP_MCHP_VENDOR_ID) + continue; + + *ptp = SFDP_PARAM_HEADER_PTP(&ph); + return 0; + } + + return -ENOENT; +}...
drivers/nvmem/layouts/Makefile
Quoted 11 lines
drivers/nvmem/layouts/Makefile +11
-0+ info.name = "mac-address"; + info.offset = base + SFDP_MCHP_EUI48_OFFSET; + info.bytes = ETH_ALEN; + info.np = of_get_child_by_name(layout_np, "mac-address"); + info.read_post_process = sfdp_eui_read_post_process; + + ret = nvmem_add_one_cell(nvmem, &info); + if (ret) + of_node_put(info.np); + else + dev_dbg(dev, "exposed EUI-48 at SFDP offset 0x%x\n", info.offset);This one is not really useful anymore.
drivers/nvmem/layouts/Makefile
Quoted 6 lines
drivers/nvmem/layouts/Makefile +6
-0+ + of_node_put(layout_np); + + return ret; +} +Thanks,
Miquèl
Signature · 2 lines
Thanks and Regards, Manikandan M.
[email protected]
AI reviewRe: [PATCH v8 5/8] nvmem: layouts: add Microchip/SST SFDP EUI layout driver
In reply to Manikandan MuralidharanThank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] nvmem: use-after-free on layout driver module unload --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] nvmem: use-after-free on layout driver module unload
--
commit 4e7e82e84f19ca0cc7f7eae9477c171b2bdab685
Author: Manikandan Muralidharan <[email protected]>
nvmem: layouts: add Microchip/SST SFDP EUI layout driver
This commit adds an NVMEM layout that exposes the factory-programmed EUI-48 identifier from the Microchip/SST vendor SFDP parameter table as a "mac-address" cell.
Quoted 5 lines
drivers/nvmem/layouts/sst26vf-sfdp-eui.c new file +0
-0
[ ... ]
Quoted 7 lines
drivers/nvmem/layouts/sst26vf-sfdp-eui.c new file +7
-0+ info.name ="mac-address" ; + info.offset = base +SFDP_MCHP_EUI48_OFFSET ; + info.bytes =ETH_ALEN ; + info.np =of_get_child_by_name (layout_np,"mac-address" ); + info.read_post_process = sfdp_eui_read_post_process; + + ret =nvmem_add_one_cell (nvmem, &info);
[ ... ]
drivers/nvmem/layouts/sst26vf-sfdp-eui.c line 162
Quoted 4 lines
drivers/nvmem/layouts/sst26vf-sfdp-eui.c new file +4
-0+static void sfdp_eui_remove (struct nvmem_layout *layout) +{ +nvmem_layout_unregister (layout); +}
[Severity: High]
Does this leave a dangling pointer if the layout module is unloaded?
In sfdp_eui_add_cells(), the driver registers sfdp_eui_read_post_process() as a callback via nvmem_add_one_cell(). However, the NVMEM core tracks the provider device's module, not the layout driver module.
Furthermore, nvmem_layout_unregister() is an empty stub in the NVMEM core. Because the core API does not remove the cells, the cell remains in the NVMEM device's cell list with a dangling read_post_process function pointer.
If the layout module is unloaded and the cell is subsequently read (e.g., via sysfs), could this execute unmapped module memory and cause a use-after-free?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
PATCH v8 6/8 ARM: dts: microchip: sama5d27_wlsom1: use fixed-partitions for QSPI flash
In reply to Manikandan MuralidharanMove the QSPI flash partitions under a "partitions" node with the "fixed-partitions" compatible, as required by the current MTD partition binding, instead of declaring them as direct children of the flash node. No functional change.
--- .../dts/microchip/at91-sama5d27_wlsom1.dtsi | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-)
arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi +29 -25
@@ -229,8 +229,6 @@ &qspi1 { status = "disabled"; qspi1_flash: flash@0 { - #address-cells = <1>; - #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <104000000>;
@@ -240,34 +238,40 @@ qspi1_flash: flash@0 { m25p,fast-read; status = "disabled"; - at91bootstrap@0 { - label = "at91bootstrap"; - reg = <0x0 0x40000>; - }; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - bootloader@40000 { - label = "bootloader"; - reg = <0x40000 0xc0000>; - }; + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x40000>; + }; - bootloaderenvred@100000 { - label = "bootloader env redundant"; - reg = <0x100000 0x40000>; - }; + bootloader@40000 { + label = "bootloader"; + reg = <0x40000 0xc0000>; + }; - bootloaderenv@140000 { - label = "bootloader env"; - reg = <0x140000 0x40000>; - }; + bootloaderenvred@100000 { + label = "bootloader env redundant"; + reg = <0x100000 0x40000>; + }; - dtb@180000 { - label = "device tree"; - reg = <0x180000 0x80000>; - }; + bootloaderenv@140000 { + label = "bootloader env"; + reg = <0x140000 0x40000>; + }; - kernel@200000 { - label = "kernel"; - reg = <0x200000 0x600000>; + dtb@180000 { + label = "device tree"; + reg = <0x180000 0x80000>; + }; + + kernel@200000 { + label = "kernel"; + reg = <0x200000 0x600000>; + }; }; }; };
Signature · 1 line
2.43.0
PATCH v8 7/8 ARM: dts: microchip: sama5d27_wlsom1: read MAC address from QSPI SFDP
In reply to Manikandan MuralidharanDescribe the QSPI flash SFDP as an NVMEM provider with the microchip,sst26vf-sfdp-eui layout, which exposes the factory-programmed EUI-48 as a "mac-address" cell, and point macb0 at it through nvmem-cells. This yields a stable MAC address on boards where U-Boot does not program one, instead of falling back to a random address.
The sama5d27_wlsom1 SoM is fitted with the factory-programmed SST26VF064BEUI, and the QSPI flash node is only enabled on boards carrying that part, so the EUI-48 marker and its "mac-address" cell are always present. Boards without an EUI-programmed part simply do not reference the cell, so macb0 never defers waiting for it.
--- arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi | 11 +++++++++++ .../boot/dts/microchip/at91-sama5d27_wlsom1_ek.dts | 2 ++ 2 files changed, 13 insertions(+)
arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1.dtsi +11 -0
@@ -238,6 +238,17 @@ qspi1_flash: flash@0 { m25p,fast-read; status = "disabled"; + sfdp { + compatible = "jedec,sfdp"; + + nvmem-layout { + compatible = "microchip,sst26vf-sfdp-eui"; + + mac_address_eui48: mac-address { + }; + }; + }; + partitions { compatible = "fixed-partitions"; #address-cells = <1>;
arch/arm/boot/dts/microchip/at91-sama5d27_wlsom1_ek.dts +2 -0
@@ -97,6 +97,8 @@ uart6: serial@200 { &macb0 { status = "okay"; + nvmem-cells = <&mac_address_eui48>; + nvmem-cell-names = "mac-address"; }; &pioA {
Signature · 1 line
2.43.0
PATCH v8 8/8 ARM: configs: sama5: enable Microchip/SST SFDP EUI NVMEM layout
In reply to Manikandan MuralidharanEnable CONFIG_NVMEM_LAYOUT_SST26VF_SFDP_EUI so the factory EUI-48 stored in the SST26VF QSPI flash SFDP can be used as a MAC address on boards such as the sama5d27_wlsom1.
--- arch/arm/configs/sama5_defconfig | 1 + 1 file changed, 1 insertion(+)
arch/arm/configs/sama5_defconfig +1 -0
@@ -219,6 +219,7 @@ CONFIG_PWM=y CONFIG_PWM_ATMEL=y CONFIG_PWM_ATMEL_HLCDC_PWM=y CONFIG_PWM_ATMEL_TCB=y +CONFIG_NVMEM_LAYOUT_SST26VF_SFDP_EUI=y CONFIG_EXT4_FS=y CONFIG_FANOTIFY=y CONFIG_AUTOFS_FS=m
Signature · 1 line
2.43.0