# CONFIG_BLK_DEV_UBLK is not set
# CONFIG_BLK_DEV_ZONED is not set
# CONFIG_BLK_INLINE_ENCRYPTION is not set
-# CONFIG_BLK_NVMEM is not set
+# CONFIG_BLOCK_NOTIFIERS is not set
# CONFIG_BLK_SED_OPAL is not set
# CONFIG_BLK_WBT is not set
CONFIG_BLOCK=y
# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set
# CONFIG_NVMEM is not set
# CONFIG_NVMEM_BCM_OCOTP is not set
+# CONFIG_NVMEM_BLOCK is not set
# CONFIG_NVMEM_IMX_OCOTP is not set
# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
+++ /dev/null
-From 9ffc1d7d73609a89eb264d6066340f8b7b3b0ebe Mon Sep 17 00:00:00 2001
-Date: Mon, 7 Aug 2023 21:19:45 +0100
-Subject: [PATCH 08/15] dt-bindings: block: add basic bindings for block
- devices
-
-Add bindings for block devices which are used to allow referencing
-nvmem bits on them.
-
----
- .../bindings/block/block-device.yaml | 22 ++++++++
- .../devicetree/bindings/block/partition.yaml | 50 +++++++++++++++++++
- .../devicetree/bindings/block/partitions.yaml | 20 ++++++++
- 3 files changed, 92 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/block/block-device.yaml
- create mode 100644 Documentation/devicetree/bindings/block/partition.yaml
- create mode 100644 Documentation/devicetree/bindings/block/partitions.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/block/block-device.yaml
-@@ -0,0 +1,22 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/block/block-device.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: block storage device
-+
-+description: |
-+ This binding is generic and describes a block-oriented storage device.
-+
-+maintainers:
-+
-+properties:
-+ partitions:
-+ $ref: /schemas/block/partitions.yaml
-+
-+ nvmem-layout:
-+ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml#
-+
-+unevaluatedProperties: false
---- /dev/null
-+++ b/Documentation/devicetree/bindings/block/partition.yaml
-@@ -0,0 +1,50 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/block/partition.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Partition on a block device
-+
-+description: |
-+ This binding describes a partition on a block device.
-+ Partitions may be matched by a combination of partition number, name,
-+ and UUID.
-+
-+maintainers:
-+
-+properties:
-+ $nodename:
-+ pattern: '^block-partition-.+$'
-+
-+ partnum:
-+ description:
-+ Matches partition by number if present.
-+
-+ partname:
-+ "$ref": "/schemas/types.yaml#/definitions/string"
-+ description:
-+ Matches partition by PARTNAME if present.
-+
-+ uuid:
-+ "$ref": "/schemas/types.yaml#/definitions/string"
-+ description:
-+ Matches partition by PARTUUID if present.
-+
-+ nvmem-layout:
-+ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml#
-+ description:
-+ This container may reference an NVMEM layout parser.
-+
-+anyOf:
-+ - required:
-+ - partnum
-+
-+ - required:
-+ - partname
-+
-+ - required:
-+ - uuid
-+
-+unevaluatedProperties: false
---- /dev/null
-+++ b/Documentation/devicetree/bindings/block/partitions.yaml
-@@ -0,0 +1,20 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/block/partitions.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Partitions on block devices
-+
-+description: |
-+ This binding is generic and describes the content of the partitions container
-+ node.
-+
-+maintainers:
-+
-+patternProperties:
-+ "^block-partition-.+$":
-+ $ref: partition.yaml
-+
-+unevaluatedProperties: false
+++ /dev/null
-From 614f4f6fdda09e30ecf7ef6c8091579db15018cb Mon Sep 17 00:00:00 2001
-Date: Fri, 21 Jul 2023 17:51:03 +0100
-Subject: [PATCH 09/15] block: partitions: populate fwnode
-
-Let block partitions to be represented by a firmware node and hence
-allow them to being referenced e.g. for use with blk-nvmem.
-
----
- block/partitions/core.c | 41 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 41 insertions(+)
-
---- a/block/partitions/core.c
-+++ b/block/partitions/core.c
-@@ -10,6 +10,8 @@
- #include <linux/ctype.h>
- #include <linux/vmalloc.h>
- #include <linux/raid/detect.h>
-+#include <linux/property.h>
-+
- #include "check.h"
-
- static int (*const check_part[])(struct parsed_partitions *) = {
-@@ -292,6 +294,43 @@ static ssize_t whole_disk_show(struct de
- }
- static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);
-
-+static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev)
-+{
-+ struct fwnode_handle *fw_parts, *fw_part;
-+ struct device *ddev = disk_to_dev(bdev->bd_disk);
-+ const char *partname, *uuid;
-+ u32 partno;
-+
-+ fw_parts = device_get_named_child_node(ddev, "partitions");
-+ if (!fw_parts)
-+ fw_parts = device_get_named_child_node(ddev->parent, "partitions");
-+
-+ if (!fw_parts)
-+ return NULL;
-+
-+ fwnode_for_each_child_node(fw_parts, fw_part) {
-+ if (!fwnode_property_read_string(fw_part, "uuid", &uuid) &&
-+ (!bdev->bd_meta_info || strncmp(uuid,
-+ bdev->bd_meta_info->uuid,
-+ PARTITION_META_INFO_UUIDLTH)))
-+ continue;
-+
-+ if (!fwnode_property_read_string(fw_part, "partname", &partname) &&
-+ (!bdev->bd_meta_info || strncmp(partname,
-+ bdev->bd_meta_info->volname,
-+ PARTITION_META_INFO_VOLNAMELTH)))
-+ continue;
-+
-+ if (!fwnode_property_read_u32(fw_part, "partno", &partno) &&
-+ bdev->bd_partno != partno)
-+ continue;
-+
-+ return fw_part;
-+ }
-+
-+ return NULL;
-+}
-+
- /*
- * Must be called either with open_mutex held, before a disk can be opened or
- * after all disk users are gone.
-@@ -374,6 +413,8 @@ static struct block_device *add_partitio
- goto out_put;
- }
-
-+ device_set_node(pdev, find_partition_fwnode(bdev));
-+
- /* delay uevent until 'holders' subdir is created */
- dev_set_uevent_suppress(pdev, 1);
- err = device_add(pdev);
+++ /dev/null
-From 65f3ff9672ccd5ee78937047e7a2fc696eee1c8f Mon Sep 17 00:00:00 2001
-Date: Thu, 13 Jul 2023 04:07:16 +0100
-Subject: [PATCH 10/15] block: add new genhd flag GENHD_FL_NVMEM
-
-Add new flag to destinguish block devices which may act as an NVMEM
-provider.
-
----
- include/linux/blkdev.h | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/include/linux/blkdev.h
-+++ b/include/linux/blkdev.h
-@@ -80,11 +80,13 @@ struct partition_meta_info {
- * ``GENHD_FL_NO_PART``: partition support is disabled. The kernel will not
- * scan for partitions from add_disk, and users can't add partitions manually.
- *
-+ * ``GENHD_FL_NVMEM``: the block device should be considered as NVMEM provider.
- */
- enum {
- GENHD_FL_REMOVABLE = 1 << 0,
- GENHD_FL_HIDDEN = 1 << 1,
- GENHD_FL_NO_PART = 1 << 2,
-+ GENHD_FL_NVMEM = 1 << 3,
- };
-
- enum {
+++ /dev/null
-From b9936aa8a3775c2027f655d91a206d0e6e1c7ec0 Mon Sep 17 00:00:00 2001
-Date: Tue, 11 Jul 2023 00:17:31 +0100
-Subject: [PATCH 11/15] block: implement NVMEM provider
-
-On embedded devices using an eMMC it is common that one or more partitions
-on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM
-data. Allow referencing the partition in device tree for the kernel and
-Wi-Fi drivers accessing it via the NVMEM layer.
-
----
- block/Kconfig | 9 +++
- block/Makefile | 1 +
- block/blk-nvmem.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 196 insertions(+)
- create mode 100644 block/blk-nvmem.c
-
---- a/block/Kconfig
-+++ b/block/Kconfig
-@@ -208,6 +208,15 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
- by falling back to the kernel crypto API when inline
- encryption hardware is not present.
-
-+config BLK_NVMEM
-+ bool "Block device NVMEM provider"
-+ depends on OF
-+ depends on NVMEM
-+ help
-+ Allow block devices (or partitions) to act as NVMEM prodivers,
-+ typically used with eMMC to store MAC addresses or Wi-Fi
-+ calibration data on embedded devices.
-+
- source "block/partitions/Kconfig"
-
- config BLK_MQ_PCI
---- a/block/Makefile
-+++ b/block/Makefile
-@@ -34,6 +34,7 @@ obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned
- obj-$(CONFIG_BLK_WBT) += blk-wbt.o
- obj-$(CONFIG_BLK_DEBUG_FS) += blk-mq-debugfs.o
- obj-$(CONFIG_BLK_DEBUG_FS_ZONED)+= blk-mq-debugfs-zoned.o
-+obj-$(CONFIG_BLK_NVMEM) += blk-nvmem.o
- obj-$(CONFIG_BLK_SED_OPAL) += sed-opal.o
- obj-$(CONFIG_BLK_PM) += blk-pm.o
- obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += blk-crypto.o blk-crypto-profile.o \
---- /dev/null
-+++ b/block/blk-nvmem.c
-@@ -0,0 +1,186 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * block device NVMEM provider
-+ *
-+ *
-+ * Useful on devices using a partition on an eMMC for MAC addresses or
-+ * Wi-Fi calibration EEPROM data.
-+ */
-+
-+#include "blk.h"
-+#include <linux/nvmem-provider.h>
-+#include <linux/of.h>
-+#include <linux/pagemap.h>
-+#include <linux/property.h>
-+
-+/* List of all NVMEM devices */
-+static LIST_HEAD(nvmem_devices);
-+static DEFINE_MUTEX(devices_mutex);
-+
-+struct blk_nvmem {
-+ struct nvmem_device *nvmem;
-+ struct block_device *bdev;
-+ struct list_head list;
-+};
-+
-+static int blk_nvmem_reg_read(void *priv, unsigned int from,
-+ void *val, size_t bytes)
-+{
-+ unsigned long offs = from & ~PAGE_MASK, to_read;
-+ pgoff_t f_index = from >> PAGE_SHIFT;
-+ struct address_space *mapping;
-+ struct blk_nvmem *bnv = priv;
-+ size_t bytes_left = bytes;
-+ struct folio *folio;
-+ void *p;
-+ int ret;
-+
-+ if (!bnv->bdev)
-+ return -ENODEV;
-+
-+ if (!bnv->bdev->bd_disk)
-+ return -EINVAL;
-+
-+ if (!bnv->bdev->bd_disk->fops)
-+ return -EIO;
-+
-+ if (!bnv->bdev->bd_disk->fops->open)
-+ return -EIO;
-+
-+ ret = bnv->bdev->bd_disk->fops->open(bnv->bdev->bd_disk, BLK_OPEN_READ);
-+ if (ret)
-+ return ret;
-+
-+ mapping = bnv->bdev->bd_inode->i_mapping;
-+
-+ while (bytes_left) {
-+ folio = read_mapping_folio(mapping, f_index++, NULL);
-+ if (IS_ERR(folio)) {
-+ ret = PTR_ERR(folio);
-+ goto err_release_bdev;
-+ }
-+ to_read = min_t(unsigned long, bytes_left, PAGE_SIZE - offs);
-+ p = folio_address(folio) + offset_in_folio(folio, offs);
-+ memcpy(val, p, to_read);
-+ offs = 0;
-+ bytes_left -= to_read;
-+ val += to_read;
-+ folio_put(folio);
-+ }
-+
-+err_release_bdev:
-+ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk);
-+
-+ return ret;
-+}
-+
-+static int blk_nvmem_register(struct device *dev)
-+{
-+ struct device_node *np = dev_of_node(dev);
-+ struct block_device *bdev = dev_to_bdev(dev);
-+ struct nvmem_config config = {};
-+ struct blk_nvmem *bnv;
-+
-+ /* skip devices which do not have a device tree node */
-+ if (!np)
-+ return 0;
-+
-+ /* skip devices without an nvmem layout defined */
-+ if (!of_get_child_by_name(np, "nvmem-layout"))
-+ return 0;
-+
-+ /*
-+ * skip devices which don't have GENHD_FL_NVMEM set
-+ *
-+ * This flag is used for mtdblock and ubiblock devices because
-+ * both, MTD and UBI already implement their own NVMEM provider.
-+ * To avoid registering multiple NVMEM providers for the same
-+ * device node, don't register the block NVMEM provider for them.
-+ */
-+ if (!(bdev->bd_disk->flags & GENHD_FL_NVMEM))
-+ return 0;
-+
-+ /*
-+ * skip block device too large to be represented as NVMEM devices
-+ * which are using an 'int' as address
-+ */
-+ if (bdev_nr_bytes(bdev) > INT_MAX)
-+ return -EFBIG;
-+
-+ bnv = kzalloc(sizeof(struct blk_nvmem), GFP_KERNEL);
-+ if (!bnv)
-+ return -ENOMEM;
-+
-+ config.id = NVMEM_DEVID_NONE;
-+ config.dev = &bdev->bd_device;
-+ config.name = dev_name(&bdev->bd_device);
-+ config.owner = THIS_MODULE;
-+ config.priv = bnv;
-+ config.reg_read = blk_nvmem_reg_read;
-+ config.size = bdev_nr_bytes(bdev);
-+ config.word_size = 1;
-+ config.stride = 1;
-+ config.read_only = true;
-+ config.root_only = true;
-+ config.ignore_wp = true;
-+ config.of_node = to_of_node(dev->fwnode);
-+
-+ bnv->bdev = bdev;
-+ bnv->nvmem = nvmem_register(&config);
-+ if (IS_ERR(bnv->nvmem)) {
-+ dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem),
-+ "Failed to register NVMEM device\n");
-+
-+ kfree(bnv);
-+ return PTR_ERR(bnv->nvmem);
-+ }
-+
-+ mutex_lock(&devices_mutex);
-+ list_add_tail(&bnv->list, &nvmem_devices);
-+ mutex_unlock(&devices_mutex);
-+
-+ return 0;
-+}
-+
-+static void blk_nvmem_unregister(struct device *dev)
-+{
-+ struct block_device *bdev = dev_to_bdev(dev);
-+ struct blk_nvmem *bnv_c, *bnv = NULL;
-+
-+ mutex_lock(&devices_mutex);
-+ list_for_each_entry(bnv_c, &nvmem_devices, list) {
-+ if (bnv_c->bdev == bdev) {
-+ bnv = bnv_c;
-+ break;
-+ }
-+ }
-+
-+ if (!bnv) {
-+ mutex_unlock(&devices_mutex);
-+ return;
-+ }
-+
-+ list_del(&bnv->list);
-+ mutex_unlock(&devices_mutex);
-+ nvmem_unregister(bnv->nvmem);
-+ kfree(bnv);
-+}
-+
-+static struct class_interface blk_nvmem_bus_interface __refdata = {
-+ .class = &block_class,
-+ .add_dev = &blk_nvmem_register,
-+ .remove_dev = &blk_nvmem_unregister,
-+};
-+
-+static int __init blk_nvmem_init(void)
-+{
-+ int ret;
-+
-+ ret = class_interface_register(&blk_nvmem_bus_interface);
-+ if (ret)
-+ return ret;
-+
-+ return 0;
-+}
-+device_initcall(blk_nvmem_init);
+++ /dev/null
-From 86864bf8f40e84dc881c197ef470a88668329dbf Mon Sep 17 00:00:00 2001
-Date: Mon, 7 Aug 2023 21:21:45 +0100
-Subject: [PATCH 12/15] dt-bindings: mmc: mmc-card: add block device nodes
-
-Add nodes representing the block devices exposed by an MMC device
-including an example involving nvmem-cells.
-
----
- .../devicetree/bindings/mmc/mmc-card.yaml | 45 +++++++++++++++++++
- 1 file changed, 45 insertions(+)
-
---- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml
-+++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
-@@ -26,6 +26,18 @@ properties:
- Use this to indicate that the mmc-card has a broken hpi
- implementation, and that hpi should not be used.
-
-+ block:
-+ $ref: /schemas/block/block-device.yaml#
-+ description:
-+ Represents the block storage provided by an SD card or the
-+ main hardware partition of an eMMC.
-+
-+patternProperties:
-+ '^boot[0-9]+':
-+ $ref: /schemas/block/block-device.yaml#
-+ description:
-+ Represents a boot hardware partition on an eMMC.
-+
- required:
- - compatible
- - reg
-@@ -42,6 +54,39 @@ examples:
- compatible = "mmc-card";
- reg = <0>;
- broken-hpi;
-+
-+ block {
-+ partitions {
-+ cal_data: block-partition-rf {
-+ partnum = <3>;
-+ partname = "rf";
-+
-+ nvmem-layout {
-+ compatible = "fixed-layout";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ eeprom@0 {
-+ reg = <0x0 0x1000>;
-+ };
-+ };
-+ };
-+ };
-+ };
-+
-+ boot1 {
-+ nvmem-layout {
-+ compatible = "fixed-layout";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+
-+ macaddr: macaddr@a {
-+ compatible = "mac-base";
-+ reg = <0xa 0x6>;
-+ #nvmem-cell-cells = <1>;
-+ };
-+ };
-+ };
- };
- };
-
+++ /dev/null
-From 644942a31719de674e2aa68f83d66bd8ae7e4fb7 Mon Sep 17 00:00:00 2001
-Date: Thu, 13 Jul 2023 04:12:21 +0100
-Subject: [PATCH 13/15] mmc: core: set card fwnode_handle
-
-Set fwnode in case it isn't set yet and of_node is present.
-
----
- drivers/mmc/core/bus.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/mmc/core/bus.c
-+++ b/drivers/mmc/core/bus.c
-@@ -364,6 +364,8 @@ int mmc_add_card(struct mmc_card *card)
-
- mmc_add_card_debugfs(card);
- card->dev.of_node = mmc_of_find_child_device(card->host, 0);
-+ if (card->dev.of_node && !card->dev.fwnode)
-+ card->dev.fwnode = &card->dev.of_node->fwnode;
-
- device_enable_async_suspend(&card->dev);
-
+++ /dev/null
-From d9143f86330dd038fc48878558dd287ceee5d3d4 Mon Sep 17 00:00:00 2001
-Date: Thu, 13 Jul 2023 04:13:04 +0100
-Subject: [PATCH 14/15] mmc: block: set fwnode of disk devices
-
-Set fwnode of disk devices to 'block', 'boot0' and 'boot1' subnodes of
-the mmc-card. This is done in preparation for having the eMMC act as
-NVMEM provider.
-
----
- drivers/mmc/core/block.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/mmc/core/block.c
-+++ b/drivers/mmc/core/block.c
-@@ -2463,6 +2463,8 @@ static struct mmc_blk_data *mmc_blk_allo
- int area_type,
- unsigned int part_type)
- {
-+ struct fwnode_handle *fwnode;
-+ struct device *ddev;
- struct mmc_blk_data *md;
- int devidx, ret;
- char cap_str[10];
-@@ -2559,6 +2561,13 @@ static struct mmc_blk_data *mmc_blk_allo
-
- blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);
-
-+ ddev = disk_to_dev(md->disk);
-+ fwnode = device_get_named_child_node(subname ? md->parent->parent :
-+ md->parent,
-+ subname ? subname : "block");
-+ if (fwnode)
-+ device_set_node(ddev, fwnode);
-+
- string_get_size((u64)size, 512, STRING_UNITS_2,
- cap_str, sizeof(cap_str));
- pr_info("%s: %s %s %s%s\n",
+++ /dev/null
-From 322035ab2b0113d98b6c0ea788d971e0df2952a4 Mon Sep 17 00:00:00 2001
-Date: Thu, 20 Jul 2023 17:36:44 +0100
-Subject: [PATCH 15/15] mmc: block: set GENHD_FL_NVMEM
-
-Set flag to consider MMC block devices as NVMEM providers.
-
----
- drivers/mmc/core/block.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mmc/core/block.c
-+++ b/drivers/mmc/core/block.c
-@@ -2517,6 +2517,7 @@ static struct mmc_blk_data *mmc_blk_allo
- md->disk->major = MMC_BLOCK_MAJOR;
- md->disk->minors = perdev_minors;
- md->disk->first_minor = devidx * perdev_minors;
-+ md->disk->flags = GENHD_FL_NVMEM;
- md->disk->fops = &mmc_bdops;
- md->disk->private_data = md;
- md->parent = parent;
--- /dev/null
+From 3245921a87154bdfbe7a55d743ea62dd559a8fb0 Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:13:09 +0100
+Subject: [PATCH 1/9] dt-bindings: block: add basic bindings for block devices
+
+Add bindings for block devices which are used to allow referencing
+nvmem bits on them.
+
+---
+ .../bindings/block/block-device.yaml | 22 ++++++++
+ .../devicetree/bindings/block/partition.yaml | 51 +++++++++++++++++++
+ .../devicetree/bindings/block/partitions.yaml | 20 ++++++++
+ 3 files changed, 93 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/block/block-device.yaml
+ create mode 100644 Documentation/devicetree/bindings/block/partition.yaml
+ create mode 100644 Documentation/devicetree/bindings/block/partitions.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/block/block-device.yaml
+@@ -0,0 +1,22 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/block/block-device.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: block storage device
++
++description: |
++ This binding is generic and describes a block-oriented storage device.
++
++maintainers:
++
++properties:
++ partitions:
++ $ref: /schemas/block/partitions.yaml
++
++ nvmem-layout:
++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml#
++
++unevaluatedProperties: false
+--- /dev/null
++++ b/Documentation/devicetree/bindings/block/partition.yaml
+@@ -0,0 +1,51 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/block/partition.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Partition on a block device
++
++description: |
++ This binding describes a partition on a block device.
++ Partitions may be matched by a combination of partition number, name,
++ and UUID.
++
++maintainers:
++
++properties:
++ $nodename:
++ pattern: '^block-partition-.+$'
++
++ partnum:
++ $ref: /schemas/types.yaml#/definitions/uint32
++ description:
++ Matches partition by number if present.
++
++ partname:
++ $ref: /schemas/types.yaml#/definitions/string
++ description:
++ Matches partition by PARTNAME if present.
++
++ partuuid:
++ $ref: /schemas/types.yaml#/definitions/string
++ description:
++ Matches partition by PARTUUID if present.
++
++ nvmem-layout:
++ $ref: /schemas/nvmem/layouts/nvmem-layout.yaml#
++ description:
++ This container may reference an NVMEM layout parser.
++
++anyOf:
++ - required:
++ - partnum
++
++ - required:
++ - partname
++
++ - required:
++ - partuuid
++
++unevaluatedProperties: false
+--- /dev/null
++++ b/Documentation/devicetree/bindings/block/partitions.yaml
+@@ -0,0 +1,20 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/block/partitions.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Partitions on block devices
++
++description: |
++ This binding is generic and describes the content of the partitions container
++ node.
++
++maintainers:
++
++patternProperties:
++ "^block-partition-.+$":
++ $ref: partition.yaml
++
++unevaluatedProperties: false
--- /dev/null
+From 7f4c9c534aabe1315669e076d3fe0af0fd374cda Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:13:19 +0100
+Subject: [PATCH 2/9] block: partitions: populate fwnode
+
+Let block partitions to be represented by a firmware node and hence
+allow them to being referenced e.g. for use with blk-nvmem.
+
+---
+ block/partitions/core.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+--- a/block/partitions/core.c
++++ b/block/partitions/core.c
+@@ -10,6 +10,8 @@
+ #include <linux/ctype.h>
+ #include <linux/vmalloc.h>
+ #include <linux/raid/detect.h>
++#include <linux/property.h>
++
+ #include "check.h"
+
+ static int (*const check_part[])(struct parsed_partitions *) = {
+@@ -292,6 +294,40 @@ static ssize_t whole_disk_show(struct de
+ }
+ static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL);
+
++static struct fwnode_handle *find_partition_fwnode(struct block_device *bdev)
++{
++ struct fwnode_handle *fw_parts, *fw_part;
++ struct device *ddev = disk_to_dev(bdev->bd_disk);
++ const char *partname, *uuid;
++ u32 partno;
++
++ fw_parts = device_get_named_child_node(ddev, "partitions");
++ if (!fw_parts)
++ return NULL;
++
++ fwnode_for_each_child_node(fw_parts, fw_part) {
++ if (!fwnode_property_read_string(fw_part, "uuid", &uuid) &&
++ (!bdev->bd_meta_info || strncmp(uuid,
++ bdev->bd_meta_info->uuid,
++ PARTITION_META_INFO_UUIDLTH)))
++ continue;
++
++ if (!fwnode_property_read_string(fw_part, "partname", &partname) &&
++ (!bdev->bd_meta_info || strncmp(partname,
++ bdev->bd_meta_info->volname,
++ PARTITION_META_INFO_VOLNAMELTH)))
++ continue;
++
++ if (!fwnode_property_read_u32(fw_part, "partno", &partno) &&
++ bdev->bd_partno != partno)
++ continue;
++
++ return fw_part;
++ }
++
++ return NULL;
++}
++
+ /*
+ * Must be called either with open_mutex held, before a disk can be opened or
+ * after all disk users are gone.
+@@ -374,6 +410,8 @@ static struct block_device *add_partitio
+ goto out_put;
+ }
+
++ device_set_node(pdev, find_partition_fwnode(bdev));
++
+ /* delay uevent until 'holders' subdir is created */
+ dev_set_uevent_suppress(pdev, 1);
+ err = device_add(pdev);
--- /dev/null
+From e07ace307ce598847074a096f408bec0e3a392ed Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:14:34 +0100
+Subject: [PATCH 3/9] block: add support for notifications
+
+Add notifier block to notify other subsystems about the addition or
+removal of block devices.
+
+---
+ block/Kconfig | 6 +++
+ block/Makefile | 1 +
+ block/blk-notify.c | 88 ++++++++++++++++++++++++++++++++++++++++++
+ include/linux/blkdev.h | 8 ++++
+ 4 files changed, 103 insertions(+)
+ create mode 100644 block/blk-notify.c
+
+--- a/block/Kconfig
++++ b/block/Kconfig
+@@ -208,6 +208,12 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
+ by falling back to the kernel crypto API when inline
+ encryption hardware is not present.
+
++config BLOCK_NOTIFIERS
++ bool "Enable support for notifications in block layer"
++ help
++ Enable this option to provide notifiers for other subsystems
++ upon addition or removal of block devices.
++
+ source "block/partitions/Kconfig"
+
+ config BLK_MQ_PCI
+--- a/block/Makefile
++++ b/block/Makefile
+@@ -40,3 +40,4 @@ obj-$(CONFIG_BLK_INLINE_ENCRYPTION) += b
+ blk-crypto-sysfs.o
+ obj-$(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) += blk-crypto-fallback.o
+ obj-$(CONFIG_BLOCK_HOLDER_DEPRECATED) += holder.o
++obj-$(CONFIG_BLOCK_NOTIFIERS) += blk-notify.o
+--- /dev/null
++++ b/block/blk-notify.c
+@@ -0,0 +1,88 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Notifiers for addition and removal of block devices
++ *
++ */
++
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/notifier.h>
++
++#include "blk.h"
++
++struct blk_device_list {
++ struct device *dev;
++ struct list_head list;
++};
++
++static RAW_NOTIFIER_HEAD(blk_notifier_list);
++static DEFINE_MUTEX(blk_notifier_lock);
++static LIST_HEAD(blk_devices);
++
++void blk_register_notify(struct notifier_block *nb)
++{
++ struct blk_device_list *existing_blkdev;
++
++ mutex_lock(&blk_notifier_lock);
++ raw_notifier_chain_register(&blk_notifier_list, nb);
++
++ list_for_each_entry(existing_blkdev, &blk_devices, list)
++ nb->notifier_call(nb, BLK_DEVICE_ADD, existing_blkdev->dev);
++
++ mutex_unlock(&blk_notifier_lock);
++}
++EXPORT_SYMBOL_GPL(blk_register_notify);
++
++void blk_unregister_notify(struct notifier_block *nb)
++{
++ mutex_lock(&blk_notifier_lock);
++ raw_notifier_chain_unregister(&blk_notifier_list, nb);
++ mutex_unlock(&blk_notifier_lock);
++}
++EXPORT_SYMBOL_GPL(blk_unregister_notify);
++
++static int blk_call_notifier_add(struct device *dev)
++{
++ struct blk_device_list *new_blkdev;
++
++ new_blkdev = kmalloc(sizeof(*new_blkdev), GFP_KERNEL);
++ if (!new_blkdev)
++ return -ENOMEM;
++
++ new_blkdev->dev = dev;
++ mutex_lock(&blk_notifier_lock);
++ list_add_tail(&new_blkdev->list, &blk_devices);
++ raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_ADD, dev);
++ mutex_unlock(&blk_notifier_lock);
++
++ return 0;
++}
++
++static void blk_call_notifier_remove(struct device *dev)
++{
++ struct blk_device_list *old_blkdev, *tmp;
++
++ mutex_lock(&blk_notifier_lock);
++ list_for_each_entry_safe(old_blkdev, tmp, &blk_devices, list) {
++ if (old_blkdev->dev != dev)
++ continue;
++
++ list_del(&old_blkdev->list);
++ kfree(old_blkdev);
++ }
++ raw_notifier_call_chain(&blk_notifier_list, BLK_DEVICE_REMOVE, dev);
++ mutex_unlock(&blk_notifier_lock);
++}
++
++static struct class_interface blk_notifications_bus_interface __refdata = {
++ .class = &block_class,
++ .add_dev = &blk_call_notifier_add,
++ .remove_dev = &blk_call_notifier_remove,
++};
++
++static int __init blk_notifications_init(void)
++{
++ return class_interface_register(&blk_notifications_bus_interface);
++}
++device_initcall(blk_notifications_init);
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -1564,4 +1564,12 @@ struct io_comp_batch {
+
+ #define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { }
+
++
++#ifdef CONFIG_BLOCK_NOTIFIERS
++#define BLK_DEVICE_ADD 1
++#define BLK_DEVICE_REMOVE 2
++void blk_register_notify(struct notifier_block *nb);
++void blk_unregister_notify(struct notifier_block *nb);
++#endif
++
+ #endif /* _LINUX_BLKDEV_H */
--- /dev/null
+From f4487fa1cb7e55b3c17a33f41b9c9d66f4f853b7 Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:14:49 +0100
+Subject: [PATCH 4/9] block: add new genhd flag GENHD_FL_NVMEM
+
+Add new flag to destinguish block devices which may act as an NVMEM
+provider.
+
+---
+ include/linux/blkdev.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -80,11 +80,13 @@ struct partition_meta_info {
+ * ``GENHD_FL_NO_PART``: partition support is disabled. The kernel will not
+ * scan for partitions from add_disk, and users can't add partitions manually.
+ *
++ * ``GENHD_FL_NVMEM``: the block device should be considered as NVMEM provider.
+ */
+ enum {
+ GENHD_FL_REMOVABLE = 1 << 0,
+ GENHD_FL_HIDDEN = 1 << 1,
+ GENHD_FL_NO_PART = 1 << 2,
++ GENHD_FL_NVMEM = 1 << 3,
+ };
+
+ enum {
--- /dev/null
+From 9703951cdfe868b130e64d6122420396c2807be8 Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:15:02 +0100
+Subject: [PATCH 5/9] nvmem: implement block NVMEM provider
+
+On embedded devices using an eMMC it is common that one or more partitions
+on the eMMC are used to store MAC addresses and Wi-Fi calibration EEPROM
+data. Allow referencing any block device or partition in Device Tree to
+allow e.g. Ethernet and Wi-Fi drivers accessing them via the NVMEM layer.
+
+---
+ drivers/nvmem/Kconfig | 11 +++
+ drivers/nvmem/Makefile | 2 +
+ drivers/nvmem/block.c | 197 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 210 insertions(+)
+ create mode 100644 drivers/nvmem/block.c
+
+--- a/drivers/nvmem/Kconfig
++++ b/drivers/nvmem/Kconfig
+@@ -40,6 +40,17 @@ config NVMEM_APPLE_EFUSES
+ This driver can also be built as a module. If so, the module will
+ be called nvmem-apple-efuses.
+
++config NVMEM_BLOCK
++ tristate "Block device NVMEM provider"
++ depends on BLOCK
++ depends on OF
++ depends on NVMEM
++ select BLOCK_NOTIFIERS
++ help
++ Allow block devices (or partitions) to act as NVMEM prodivers,
++ typically used with eMMC to store MAC addresses or Wi-Fi
++ calibration data on embedded devices.
++
+ config NVMEM_BCM_OCOTP
+ tristate "Broadcom On-Chip OTP Controller support"
+ depends on ARCH_BCM_IPROC || COMPILE_TEST
+--- a/drivers/nvmem/Makefile
++++ b/drivers/nvmem/Makefile
+@@ -14,6 +14,8 @@ obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvme
+ nvmem-apple-efuses-y := apple-efuses.o
+ obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o
+ nvmem-bcm-ocotp-y := bcm-ocotp.o
++obj-$(CONFIG_NVMEM_BLOCK) += nvmem-block.o
++nvmem-block-y := block.o
+ obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o
+ nvmem_brcm_nvram-y := brcm_nvram.o
+ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
+--- /dev/null
++++ b/drivers/nvmem/block.c
+@@ -0,0 +1,208 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * block device NVMEM provider
++ *
++ *
++ * Useful on devices using a partition on an eMMC for MAC addresses or
++ * Wi-Fi calibration EEPROM data.
++ */
++
++#include <linux/blkdev.h>
++#include <linux/nvmem-provider.h>
++#include <linux/of.h>
++#include <linux/pagemap.h>
++#include <linux/property.h>
++
++/* List of all NVMEM devices */
++static LIST_HEAD(nvmem_devices);
++static DEFINE_MUTEX(devices_mutex);
++
++struct blk_nvmem {
++ struct nvmem_device *nvmem;
++ struct block_device *bdev;
++ struct list_head list;
++};
++
++static int blk_nvmem_reg_read(void *priv, unsigned int from,
++ void *val, size_t bytes)
++{
++ unsigned long offs = from & ~PAGE_MASK, to_read;
++ pgoff_t f_index = from >> PAGE_SHIFT;
++ struct address_space *mapping;
++ struct blk_nvmem *bnv = priv;
++ size_t bytes_left = bytes;
++ struct folio *folio;
++ void *p;
++ int ret;
++
++ if (!bnv->bdev)
++ return -ENODEV;
++
++ if (!bnv->bdev->bd_disk)
++ return -EINVAL;
++
++ if (!bnv->bdev->bd_disk->fops)
++ return -EIO;
++
++ if (!bnv->bdev->bd_disk->fops->open)
++ return -EIO;
++
++ ret = bnv->bdev->bd_disk->fops->open(bnv->bdev->bd_disk, BLK_OPEN_READ);
++ if (ret)
++ return ret;
++
++ mapping = bnv->bdev->bd_inode->i_mapping;
++
++ while (bytes_left) {
++ folio = read_mapping_folio(mapping, f_index++, NULL);
++ if (IS_ERR(folio)) {
++ ret = PTR_ERR(folio);
++ goto err_release_bdev;
++ }
++ to_read = min_t(unsigned long, bytes_left, PAGE_SIZE - offs);
++ p = folio_address(folio) + offset_in_folio(folio, offs);
++ memcpy(val, p, to_read);
++ offs = 0;
++ bytes_left -= to_read;
++ val += to_read;
++ folio_put(folio);
++ }
++
++err_release_bdev:
++ bnv->bdev->bd_disk->fops->release(bnv->bdev->bd_disk);
++
++ return ret;
++}
++
++static int blk_nvmem_register(struct device *dev)
++{
++ struct device_node *np = dev_of_node(dev);
++ struct block_device *bdev = dev_to_bdev(dev);
++ struct nvmem_config config = {};
++ struct blk_nvmem *bnv;
++
++ /* skip devices which do not have a device tree node */
++ if (!np)
++ return 0;
++
++ /* skip devices without an nvmem layout defined */
++ if (!of_get_child_by_name(np, "nvmem-layout"))
++ return 0;
++
++ /*
++ * skip devices which don't have GENHD_FL_NVMEM set
++ *
++ * This flag is used for mtdblock and ubiblock devices because
++ * both, MTD and UBI already implement their own NVMEM provider.
++ * To avoid registering multiple NVMEM providers for the same
++ * device node, don't register the block NVMEM provider for them.
++ */
++ if (!(bdev->bd_disk->flags & GENHD_FL_NVMEM))
++ return 0;
++
++ /*
++ * skip block device too large to be represented as NVMEM devices
++ * which are using an 'int' as address
++ */
++ if (bdev_nr_bytes(bdev) > INT_MAX)
++ return -EFBIG;
++
++ bnv = kzalloc(sizeof(struct blk_nvmem), GFP_KERNEL);
++ if (!bnv)
++ return -ENOMEM;
++
++ config.id = NVMEM_DEVID_NONE;
++ config.dev = &bdev->bd_device;
++ config.name = dev_name(&bdev->bd_device);
++ config.owner = THIS_MODULE;
++ config.priv = bnv;
++ config.reg_read = blk_nvmem_reg_read;
++ config.size = bdev_nr_bytes(bdev);
++ config.word_size = 1;
++ config.stride = 1;
++ config.read_only = true;
++ config.root_only = true;
++ config.ignore_wp = true;
++ config.of_node = to_of_node(dev->fwnode);
++
++ bnv->bdev = bdev;
++ bnv->nvmem = nvmem_register(&config);
++ if (IS_ERR(bnv->nvmem)) {
++ dev_err_probe(&bdev->bd_device, PTR_ERR(bnv->nvmem),
++ "Failed to register NVMEM device\n");
++
++ kfree(bnv);
++ return PTR_ERR(bnv->nvmem);
++ }
++
++ mutex_lock(&devices_mutex);
++ list_add_tail(&bnv->list, &nvmem_devices);
++ mutex_unlock(&devices_mutex);
++
++ return 0;
++}
++
++static void blk_nvmem_unregister(struct device *dev)
++{
++ struct block_device *bdev = dev_to_bdev(dev);
++ struct blk_nvmem *bnv_c, *bnv = NULL;
++
++ mutex_lock(&devices_mutex);
++ list_for_each_entry(bnv_c, &nvmem_devices, list) {
++ if (bnv_c->bdev == bdev) {
++ bnv = bnv_c;
++ break;
++ }
++ }
++
++ if (!bnv) {
++ mutex_unlock(&devices_mutex);
++ return;
++ }
++
++ list_del(&bnv->list);
++ mutex_unlock(&devices_mutex);
++ nvmem_unregister(bnv->nvmem);
++ kfree(bnv);
++}
++
++static int blk_nvmem_handler(struct notifier_block *this, unsigned long code, void *obj)
++{
++ struct device *dev = (struct device *)obj;
++
++ switch (code) {
++ case BLK_DEVICE_ADD:
++ return blk_nvmem_register(dev);
++ case BLK_DEVICE_REMOVE:
++ blk_nvmem_unregister(dev);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static struct notifier_block blk_nvmem_notifier = {
++ .notifier_call = blk_nvmem_handler,
++};
++
++static int __init blk_nvmem_init(void)
++{
++ blk_register_notify(&blk_nvmem_notifier);
++
++ return 0;
++}
++
++static void __exit blk_nvmem_exit(void)
++{
++ blk_unregister_notify(&blk_nvmem_notifier);
++}
++
++module_init(blk_nvmem_init);
++module_exit(blk_nvmem_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("block device NVMEM provider");
--- /dev/null
+From f7ec19b34d1b7e934a58ceb102369bbd30b2631d Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:15:11 +0100
+Subject: [PATCH 6/9] dt-bindings: mmc: mmc-card: add block device nodes
+
+Add nodes representing the block devices exposed by an MMC device
+including an example involving nvmem-cells.
+
+---
+ .../devicetree/bindings/mmc/mmc-card.yaml | 45 +++++++++++++++++++
+ 1 file changed, 45 insertions(+)
+
+--- a/Documentation/devicetree/bindings/mmc/mmc-card.yaml
++++ b/Documentation/devicetree/bindings/mmc/mmc-card.yaml
+@@ -26,6 +26,18 @@ properties:
+ Use this to indicate that the mmc-card has a broken hpi
+ implementation, and that hpi should not be used.
+
++ block:
++ $ref: /schemas/block/block-device.yaml#
++ description:
++ Represents the block storage provided by an SD card or the
++ main hardware partition of an eMMC.
++
++patternProperties:
++ '^boot[0-9]+':
++ $ref: /schemas/block/block-device.yaml#
++ description:
++ Represents a boot hardware partition on an eMMC.
++
+ required:
+ - compatible
+ - reg
+@@ -42,6 +54,39 @@ examples:
+ compatible = "mmc-card";
+ reg = <0>;
+ broken-hpi;
++
++ block {
++ partitions {
++ cal_data: block-partition-rf {
++ partnum = <3>;
++ partname = "rf";
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom@0 {
++ reg = <0x0 0x1000>;
++ };
++ };
++ };
++ };
++ };
++
++ boot1 {
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ macaddr: macaddr@a {
++ compatible = "mac-base";
++ reg = <0xa 0x6>;
++ #nvmem-cell-cells = <1>;
++ };
++ };
++ };
+ };
+ };
+
--- /dev/null
+From 043c4f88476cc0f29c9bf82a8a516f58d848e1cd Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:15:25 +0100
+Subject: [PATCH 7/9] mmc: core: set card fwnode_handle
+
+Set fwnode in case it isn't set yet and of_node is present.
+
+---
+ drivers/mmc/core/bus.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/mmc/core/bus.c
++++ b/drivers/mmc/core/bus.c
+@@ -364,6 +364,8 @@ int mmc_add_card(struct mmc_card *card)
+
+ mmc_add_card_debugfs(card);
+ card->dev.of_node = mmc_of_find_child_device(card->host, 0);
++ if (card->dev.of_node && !card->dev.fwnode)
++ card->dev.fwnode = &card->dev.of_node->fwnode;
+
+ device_enable_async_suspend(&card->dev);
+
--- /dev/null
+From ef3e38fec26901b71975d7e810a2df6b8bd54a8e Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:15:36 +0100
+Subject: [PATCH 8/9] mmc: block: set fwnode of disk devices
+
+Set fwnode of disk devices to 'block', 'boot0' and 'boot1' subnodes of
+the mmc-card. This is done in preparation for having the eMMC act as
+NVMEM provider.
+
+---
+ drivers/mmc/core/block.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -2463,6 +2463,7 @@ static struct mmc_blk_data *mmc_blk_allo
+ int area_type,
+ unsigned int part_type)
+ {
++ struct fwnode_handle *fwnode;
+ struct mmc_blk_data *md;
+ int devidx, ret;
+ char cap_str[10];
+@@ -2559,6 +2560,12 @@ static struct mmc_blk_data *mmc_blk_allo
+
+ blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled);
+
++ fwnode = device_get_named_child_node(subname ? md->parent->parent :
++ md->parent,
++ subname ? subname : "block");
++ if (fwnode)
++ device_set_node(disk_to_dev(md->disk), fwnode);
++
+ string_get_size((u64)size, 512, STRING_UNITS_2,
+ cap_str, sizeof(cap_str));
+ pr_info("%s: %s %s %s%s\n",
--- /dev/null
+From 7903b50441000365a6fe5badb39735889f562252 Mon Sep 17 00:00:00 2001
+Date: Thu, 30 May 2024 03:15:46 +0100
+Subject: [PATCH 9/9] mmc: block: set GENHD_FL_NVMEM
+
+Set flag to consider MMC block devices as NVMEM providers.
+
+---
+ drivers/mmc/core/block.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -2516,6 +2516,7 @@ static struct mmc_blk_data *mmc_blk_allo
+ md->disk->major = MMC_BLOCK_MAJOR;
+ md->disk->minors = perdev_minors;
+ md->disk->first_minor = devidx * perdev_minors;
++ md->disk->flags = GENHD_FL_NVMEM;
+ md->disk->fops = &mmc_bdops;
+ md->disk->private_data = md;
+ md->parent = parent;
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_MQ_PCI=y
-CONFIG_BLK_NVMEM=y
CONFIG_BLK_PM=y
+CONFIG_BLOCK_NOTIFIERS=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_BUFFER_HEAD=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_NVMEM=y
+CONFIG_NVMEM_BLOCK=y
CONFIG_NVMEM_LAYOUTS=y
CONFIG_NVMEM_MTK_EFUSE=y
CONFIG_NVMEM_SYSFS=y
#ifdef CONFIG_SGI_PARTITION
sgi_partition,
#endif
-@@ -433,6 +439,11 @@ static struct block_device *add_partitio
+@@ -430,6 +436,11 @@ static struct block_device *add_partitio
goto out_del;
}
/* everything is up and running, commence */
err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL);
if (err)
-@@ -625,6 +636,11 @@ static bool blk_add_partition(struct gen
+@@ -622,6 +633,11 @@ static bool blk_add_partition(struct gen
(state->parts[p].flags & ADDPART_FLAG_RAID))
md_autodetect_dev(part->bd_dev);