2024-02-24 11:45:55

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 00/11] nvmem: patches(set 1) for 6.9

From: Srinivas Kandagatla <[email protected]>

Hi Greg,

Here are few patches in nvmem for 6.9 that includes
- make nvmem bus const
- few dt schema enhancements
- add Xilinx socinfo driver from nvmem provider.
- add xilink: Zynqmp write support
- few enhancements to mtk-fuse provider

Can you please queue them up for 6.9.

Thanks,
Srini

MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit


Chen-Yu Tsai (1):
nvmem: mtk-efuse: Drop NVMEM device name

Krzysztof Kozlowski (1):
dt-bindings: nvmem: add common definition of nvmem-cell-cells

Markus Schneider-Pargmann (1):
nvmem: core: Print error on wrong bits DT property

Praveen Teja Kundanala (5):
dt-bindings: nvmem: Convert xlnx,zynqmp-nvmem.txt to yaml
firmware: xilinx: Add ZynqMP efuse access API
nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup
nvmem: zynqmp_nvmem: Add support to access efuse
MAINTAINERS: Add maintainers for ZynqMP NVMEM driver

Ricardo B. Marliere (1):
nvmem: core: make nvmem_layout_bus_type const

Rob Herring (1):
nvmem: fixed-cell: Simplify nested if/then schema

William-tw Lin (1):
nvmem: mtk-efuse: Register MediaTek socinfo driver from efuse

.../bindings/nvmem/layouts/fixed-cell.yaml | 22 +-
.../bindings/nvmem/nvmem-provider.yaml | 18 ++
.../bindings/nvmem/xlnx,zynqmp-nvmem.txt | 46 ----
.../bindings/nvmem/xlnx,zynqmp-nvmem.yaml | 42 ++++
MAINTAINERS | 8 +
drivers/firmware/xilinx/zynqmp.c | 25 ++
drivers/nvmem/core.c | 5 +
drivers/nvmem/layouts.c | 2 +-
drivers/nvmem/mtk-efuse.c | 20 +-
drivers/nvmem/zynqmp_nvmem.c | 215 +++++++++++++++---
include/linux/firmware/xlnx-zynqmp.h | 8 +
11 files changed, 320 insertions(+), 91 deletions(-)
create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml
delete mode 100644 Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
create mode 100644 Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml

--
2.25.1



2024-02-24 11:46:02

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 01/11] nvmem: fixed-cell: Simplify nested if/then schema

From: Rob Herring <[email protected]>

There's no reason to have a nested if/then schema as checking for compatible
being present and containing 'mac-base' can all be done in one 'if' schema.

Signed-off-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../bindings/nvmem/layouts/fixed-cell.yaml | 22 +++++++++----------
1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml b/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml
index ac2381e66027..8b3826243ddd 100644
--- a/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml
+++ b/Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml
@@ -36,20 +36,18 @@ properties:

allOf:
- if:
+ properties:
+ compatible:
+ contains:
+ const: mac-base
required: [ compatible ]
then:
- if:
- properties:
- compatible:
- contains:
- const: mac-base
- then:
- properties:
- "#nvmem-cell-cells":
- description: The first argument is a MAC address offset.
- const: 1
- required:
- - "#nvmem-cell-cells"
+ properties:
+ "#nvmem-cell-cells":
+ description: The first argument is a MAC address offset.
+ const: 1
+ required:
+ - "#nvmem-cell-cells"

required:
- reg
--
2.25.1


2024-02-24 11:46:16

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 02/11] nvmem: mtk-efuse: Register MediaTek socinfo driver from efuse

From: William-tw Lin <[email protected]>

The socinfo driver reads chip information from eFuses and does not need
any devicetree node. Register it from mtk-efuse.

While at it, also add the name for this driver's nvmem_config.

Signed-off-by: William-tw Lin <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/mtk-efuse.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index 84f05b40a411..f5bebcecf9bd 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -68,6 +68,7 @@ static int mtk_efuse_probe(struct platform_device *pdev)
struct nvmem_config econfig = {};
struct mtk_efuse_priv *priv;
const struct mtk_efuse_pdata *pdata;
+ struct platform_device *socinfo;

priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -85,11 +86,20 @@ static int mtk_efuse_probe(struct platform_device *pdev)
econfig.size = resource_size(res);
econfig.priv = priv;
econfig.dev = dev;
+ econfig.name = "mtk-efuse";
if (pdata->uses_post_processing)
econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info;
nvmem = devm_nvmem_register(dev, &econfig);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);

- return PTR_ERR_OR_ZERO(nvmem);
+ socinfo = platform_device_register_data(&pdev->dev, "mtk-socinfo",
+ PLATFORM_DEVID_AUTO, NULL, 0);
+ if (IS_ERR(socinfo))
+ dev_info(dev, "MediaTek SoC Information will be unavailable\n");
+
+ platform_set_drvdata(pdev, socinfo);
+ return 0;
}

static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = {
@@ -108,8 +118,17 @@ static const struct of_device_id mtk_efuse_of_match[] = {
};
MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);

+static void mtk_efuse_remove(struct platform_device *pdev)
+{
+ struct platform_device *socinfo = platform_get_drvdata(pdev);
+
+ if (!IS_ERR_OR_NULL(socinfo))
+ platform_device_unregister(socinfo);
+}
+
static struct platform_driver mtk_efuse_driver = {
.probe = mtk_efuse_probe,
+ .remove_new = mtk_efuse_remove,
.driver = {
.name = "mediatek,efuse",
.of_match_table = mtk_efuse_of_match,
--
2.25.1


2024-02-24 11:46:33

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 03/11] dt-bindings: nvmem: Convert xlnx,zynqmp-nvmem.txt to yaml

From: Praveen Teja Kundanala <[email protected]>

Convert the xlnx,zynqmp-nvmem.txt to yaml.

Signed-off-by: Praveen Teja Kundanala <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../bindings/nvmem/xlnx,zynqmp-nvmem.txt | 46 -------------------
.../bindings/nvmem/xlnx,zynqmp-nvmem.yaml | 42 +++++++++++++++++
2 files changed, 42 insertions(+), 46 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
create mode 100644 Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml

diff --git a/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt b/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
deleted file mode 100644
index 4881561b3a02..000000000000
--- a/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
+++ /dev/null
@@ -1,46 +0,0 @@
---------------------------------------------------------------------------
-= Zynq UltraScale+ MPSoC nvmem firmware driver binding =
---------------------------------------------------------------------------
-The nvmem_firmware node provides access to the hardware related data
-like soc revision, IDCODE... etc, By using the firmware interface.
-
-Required properties:
-- compatible: should be "xlnx,zynqmp-nvmem-fw"
-
-= Data cells =
-Are child nodes of silicon id, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
--------
- Example
--------
-firmware {
- zynqmp_firmware: zynqmp-firmware {
- compatible = "xlnx,zynqmp-firmware";
- method = "smc";
-
- nvmem_firmware {
- compatible = "xlnx,zynqmp-nvmem-fw";
- #address-cells = <1>;
- #size-cells = <1>;
-
- /* Data cells */
- soc_revision: soc_revision {
- reg = <0x0 0x4>;
- };
- };
- };
-};
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-For example:
- pcap {
- ...
-
- nvmem-cells = <&soc_revision>;
- nvmem-cell-names = "soc_revision";
-
- ...
- };
diff --git a/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml b/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml
new file mode 100644
index 000000000000..917c40d5c382
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/xlnx,zynqmp-nvmem.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zynq UltraScale+ MPSoC Non Volatile Memory interface
+
+description: |
+ The ZynqMP MPSoC provides access to the hardware related data
+ like SOC revision, IDCODE and specific purpose efuses.
+
+maintainers:
+ - Kalyani Akula <[email protected]>
+ - Praveen Teja Kundanala <[email protected]>
+
+allOf:
+ - $ref: nvmem.yaml#
+
+properties:
+ compatible:
+ const: xlnx,zynqmp-nvmem-fw
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ nvmem {
+ compatible = "xlnx,zynqmp-nvmem-fw";
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc_revision: soc-revision@0 {
+ reg = <0x0 0x4>;
+ };
+ };
+ };
--
2.25.1


2024-02-24 11:46:37

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 04/11] dt-bindings: nvmem: add common definition of nvmem-cell-cells

From: Krzysztof Kozlowski <[email protected]>

Linux kernel NVMEM consumer bindings define phandle to NVMEM cells
("nvmem-cells"), thus we also want the common definition of property
defining number of cells encoding that specifier, so the

Suggested-by: Rob Herring <[email protected]>
Reported-by: Michael Walle <[email protected]>
Closes: https://github.com/devicetree-org/dt-schema/pull/89
Reported-by: Rafał Miłecki <[email protected]>
Closes: https://lore.kernel.org/linux-arm-kernel/[email protected]/#r
Closes: https://lore.kernel.org/all/[email protected]/
Signed-off-by: Krzysztof Kozlowski <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../bindings/nvmem/nvmem-provider.yaml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml

diff --git a/Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml b/Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml
new file mode 100644
index 000000000000..4009a9a03841
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/nvmem-provider.yaml#
+$schema: http://devicetree.org/meta-schemas/base.yaml#
+
+title: NVMEM (Non Volatile Memory) Provider
+
+maintainers:
+ - Srinivas Kandagatla <[email protected]>
+
+select: true
+
+properties:
+ '#nvmem-cell-cells':
+ enum: [0, 1]
+
+additionalProperties: true
--
2.25.1


2024-02-24 11:46:54

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 05/11] firmware: xilinx: Add ZynqMP efuse access API

From: Praveen Teja Kundanala <[email protected]>

Add zynqmp_pm_efuse_access API in the ZynqMP
firmware for read/write access of efuse memory.

Signed-off-by: Praveen Teja Kundanala <[email protected]>
Acked-by: Michal Simek <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/firmware/xilinx/zynqmp.c | 25 +++++++++++++++++++++++++
include/linux/firmware/xlnx-zynqmp.h | 8 ++++++++
2 files changed, 33 insertions(+)

diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 79789f0563f6..9bc45357e1a8 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -3,6 +3,7 @@
* Xilinx Zynq MPSoC Firmware layer
*
* Copyright (C) 2014-2022 Xilinx, Inc.
+ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
*
* Michal Simek <[email protected]>
* Davorin Mista <[email protected]>
@@ -1384,6 +1385,30 @@ int zynqmp_pm_aes_engine(const u64 address, u32 *out)
}
EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);

+/**
+ * zynqmp_pm_efuse_access - Provides access to efuse memory.
+ * @address: Address of the efuse params structure
+ * @out: Returned output value
+ *
+ * Return: Returns status, either success or error code.
+ */
+int zynqmp_pm_efuse_access(const u64 address, u32 *out)
+{
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ int ret;
+
+ if (!out)
+ return -EINVAL;
+
+ ret = zynqmp_pm_invoke_fn(PM_EFUSE_ACCESS, ret_payload, 2,
+ upper_32_bits(address),
+ lower_32_bits(address));
+ *out = ret_payload[1];
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_efuse_access);
+
/**
* zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
* @address: Address of the data/ Address of output buffer where
diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h
index 9a7e52739251..1a069a56c961 100644
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -3,6 +3,7 @@
* Xilinx Zynq MPSoC Firmware layer
*
* Copyright (C) 2014-2021 Xilinx
+ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
*
* Michal Simek <[email protected]>
* Davorin Mista <[email protected]>
@@ -171,6 +172,7 @@ enum pm_api_id {
PM_CLOCK_GETPARENT = 44,
PM_FPGA_READ = 46,
PM_SECURE_AES = 47,
+ PM_EFUSE_ACCESS = 53,
PM_FEATURE_CHECK = 63,
};

@@ -562,6 +564,7 @@ int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
const u32 qos,
const enum zynqmp_pm_request_ack ack);
int zynqmp_pm_aes_engine(const u64 address, u32 *out);
+int zynqmp_pm_efuse_access(const u64 address, u32 *out);
int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags);
int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags);
int zynqmp_pm_fpga_get_status(u32 *value);
@@ -749,6 +752,11 @@ static inline int zynqmp_pm_aes_engine(const u64 address, u32 *out)
return -ENODEV;
}

+static inline int zynqmp_pm_efuse_access(const u64 address, u32 *out)
+{
+ return -ENODEV;
+}
+
static inline int zynqmp_pm_sha_hash(const u64 address, const u32 size,
const u32 flags)
{
--
2.25.1


2024-02-24 11:47:10

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 06/11] nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup

From: Praveen Teja Kundanala <[email protected]>

- Remove static nvmem_config declaration
- Remove zynqmp_nvmem_data

Signed-off-by: Praveen Teja Kundanala <[email protected]>
Acked-by: Kalyani Akula <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/zynqmp_nvmem.c | 37 ++++++++++++------------------------
1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index 7f15aa89a9d0..391d8e88b270 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019 Xilinx, Inc.
+ * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
*/

#include <linux/module.h>
@@ -11,36 +12,25 @@

#define SILICON_REVISION_MASK 0xF

-struct zynqmp_nvmem_data {
- struct device *dev;
- struct nvmem_device *nvmem;
-};

static int zynqmp_nvmem_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
+ struct device *dev = context;
int ret;
- int idcode, version;
- struct zynqmp_nvmem_data *priv = context;
+ int idcode;
+ int version;

ret = zynqmp_pm_get_chipid(&idcode, &version);
if (ret < 0)
return ret;

- dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version);
+ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version);
*(int *)val = version & SILICON_REVISION_MASK;

return 0;
}

-static struct nvmem_config econfig = {
- .name = "zynqmp-nvmem",
- .owner = THIS_MODULE,
- .word_size = 1,
- .size = 1,
- .read_only = true,
-};
-
static const struct of_device_id zynqmp_nvmem_match[] = {
{ .compatible = "xlnx,zynqmp-nvmem-fw", },
{ /* sentinel */ },
@@ -50,21 +40,18 @@ MODULE_DEVICE_TABLE(of, zynqmp_nvmem_match);
static int zynqmp_nvmem_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct zynqmp_nvmem_data *priv;
+ struct nvmem_config econfig = {};

- priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->dev = dev;
+ econfig.name = "zynqmp-nvmem";
+ econfig.owner = THIS_MODULE;
+ econfig.word_size = 1;
+ econfig.size = 1;
econfig.dev = dev;
econfig.add_legacy_fixed_of_cells = true;
+ econfig.read_only = true;
econfig.reg_read = zynqmp_nvmem_read;
- econfig.priv = priv;
-
- priv->nvmem = devm_nvmem_register(dev, &econfig);

- return PTR_ERR_OR_ZERO(priv->nvmem);
+ return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig));
}

static struct platform_driver zynqmp_nvmem_driver = {
--
2.25.1


2024-02-24 11:47:29

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 07/11] nvmem: zynqmp_nvmem: Add support to access efuse

From: Praveen Teja Kundanala <[email protected]>

Add support to read/write efuse memory map of ZynqMP.
Below are the offsets of ZynqMP efuse memory map
0 - SOC version(read only)
0xC - 0xFC -ZynqMP specific purpose efuses
0x100 - 0x17F - Physical Unclonable Function(PUF)
efuses repurposed as user efuses

Signed-off-by: Praveen Teja Kundanala <[email protected]>
Acked-by: Kalyani Akula <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/zynqmp_nvmem.c | 186 +++++++++++++++++++++++++++++++++--
1 file changed, 176 insertions(+), 10 deletions(-)

diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index 391d8e88b270..8682adaacd69 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -4,6 +4,7 @@
* Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
*/

+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
@@ -11,24 +12,189 @@
#include <linux/firmware/xlnx-zynqmp.h>

#define SILICON_REVISION_MASK 0xF
+#define P_USER_0_64_UPPER_MASK GENMASK(31, 16)
+#define P_USER_127_LOWER_4_BIT_MASK GENMASK(3, 0)
+#define WORD_INBYTES 4
+#define SOC_VER_SIZE 0x4
+#define EFUSE_MEMORY_SIZE 0x177
+#define UNUSED_SPACE 0x8
+#define ZYNQMP_NVMEM_SIZE (SOC_VER_SIZE + UNUSED_SPACE + \
+ EFUSE_MEMORY_SIZE)
+#define SOC_VERSION_OFFSET 0x0
+#define EFUSE_START_OFFSET 0xC
+#define EFUSE_END_OFFSET 0xFC
+#define EFUSE_PUF_START_OFFSET 0x100
+#define EFUSE_PUF_MID_OFFSET 0x140
+#define EFUSE_PUF_END_OFFSET 0x17F
+#define EFUSE_NOT_ENABLED 29

+/*
+ * efuse access type
+ */
+enum efuse_access {
+ EFUSE_READ = 0,
+ EFUSE_WRITE
+};
+
+/**
+ * struct xilinx_efuse - the basic structure
+ * @src: address of the buffer to store the data to be write/read
+ * @size: read/write word count
+ * @offset: read/write offset
+ * @flag: 0 - represents efuse read and 1- represents efuse write
+ * @pufuserfuse:0 - represents non-puf efuses, offset is used for read/write
+ * 1 - represents puf user fuse row number.
+ *
+ * this structure stores all the required details to
+ * read/write efuse memory.
+ */
+struct xilinx_efuse {
+ u64 src;
+ u32 size;
+ u32 offset;
+ enum efuse_access flag;
+ u32 pufuserfuse;
+};
+
+static int zynqmp_efuse_access(void *context, unsigned int offset,
+ void *val, size_t bytes, enum efuse_access flag,
+ unsigned int pufflag)
+{
+ struct device *dev = context;
+ struct xilinx_efuse *efuse;
+ dma_addr_t dma_addr;
+ dma_addr_t dma_buf;
+ size_t words = bytes / WORD_INBYTES;
+ int ret;
+ int value;
+ char *data;
+
+ if (bytes % WORD_INBYTES != 0) {
+ dev_err(dev, "Bytes requested should be word aligned\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (pufflag == 0 && offset % WORD_INBYTES) {
+ dev_err(dev, "Offset requested should be word aligned\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (pufflag == 1 && flag == EFUSE_WRITE) {
+ memcpy(&value, val, bytes);
+ if ((offset == EFUSE_PUF_START_OFFSET ||
+ offset == EFUSE_PUF_MID_OFFSET) &&
+ value & P_USER_0_64_UPPER_MASK) {
+ dev_err(dev, "Only lower 4 bytes are allowed to be programmed in P_USER_0 & P_USER_64\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (offset == EFUSE_PUF_END_OFFSET &&
+ (value & P_USER_127_LOWER_4_BIT_MASK)) {
+ dev_err(dev, "Only MSB 28 bits are allowed to be programmed for P_USER_127\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse),
+ &dma_addr, GFP_KERNEL);
+ if (!efuse)
+ return -ENOMEM;

-static int zynqmp_nvmem_read(void *context, unsigned int offset,
- void *val, size_t bytes)
+ data = dma_alloc_coherent(dev, sizeof(bytes),
+ &dma_buf, GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto efuse_data_fail;
+ }
+
+ if (flag == EFUSE_WRITE) {
+ memcpy(data, val, bytes);
+ efuse->flag = EFUSE_WRITE;
+ } else {
+ efuse->flag = EFUSE_READ;
+ }
+
+ efuse->src = dma_buf;
+ efuse->size = words;
+ efuse->offset = offset;
+ efuse->pufuserfuse = pufflag;
+
+ zynqmp_pm_efuse_access(dma_addr, (u32 *)&ret);
+ if (ret != 0) {
+ if (ret == EFUSE_NOT_ENABLED) {
+ dev_err(dev, "efuse access is not enabled\n");
+ ret = -EOPNOTSUPP;
+ } else {
+ dev_err(dev, "Error in efuse read %x\n", ret);
+ ret = -EPERM;
+ }
+ goto efuse_access_err;
+ }
+
+ if (flag == EFUSE_READ)
+ memcpy(val, data, bytes);
+efuse_access_err:
+ dma_free_coherent(dev, sizeof(bytes),
+ data, dma_buf);
+efuse_data_fail:
+ dma_free_coherent(dev, sizeof(struct xilinx_efuse),
+ efuse, dma_addr);
+
+ return ret;
+}
+
+static int zynqmp_nvmem_read(void *context, unsigned int offset, void *val, size_t bytes)
{
struct device *dev = context;
int ret;
+ int pufflag = 0;
int idcode;
int version;

- ret = zynqmp_pm_get_chipid(&idcode, &version);
- if (ret < 0)
- return ret;
+ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET)
+ pufflag = 1;
+
+ switch (offset) {
+ /* Soc version offset is zero */
+ case SOC_VERSION_OFFSET:
+ if (bytes != SOC_VER_SIZE)
+ return -EOPNOTSUPP;
+
+ ret = zynqmp_pm_get_chipid((u32 *)&idcode, (u32 *)&version);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dev, "Read chipid val %x %x\n", idcode, version);
+ *(int *)val = version & SILICON_REVISION_MASK;
+ break;
+ /* Efuse offset starts from 0xc */
+ case EFUSE_START_OFFSET ... EFUSE_END_OFFSET:
+ case EFUSE_PUF_START_OFFSET ... EFUSE_PUF_END_OFFSET:
+ ret = zynqmp_efuse_access(context, offset, val,
+ bytes, EFUSE_READ, pufflag);
+ break;
+ default:
+ *(u32 *)val = 0xDEADBEEF;
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int zynqmp_nvmem_write(void *context,
+ unsigned int offset, void *val, size_t bytes)
+{
+ int pufflag = 0;
+
+ if (offset < EFUSE_START_OFFSET || offset > EFUSE_PUF_END_OFFSET)
+ return -EOPNOTSUPP;

- dev_dbg(dev, "Read chipid val %x %x\n", idcode, version);
- *(int *)val = version & SILICON_REVISION_MASK;
+ if (offset >= EFUSE_PUF_START_OFFSET && offset <= EFUSE_PUF_END_OFFSET)
+ pufflag = 1;

- return 0;
+ return zynqmp_efuse_access(context, offset,
+ val, bytes, EFUSE_WRITE, pufflag);
}

static const struct of_device_id zynqmp_nvmem_match[] = {
@@ -45,11 +211,11 @@ static int zynqmp_nvmem_probe(struct platform_device *pdev)
econfig.name = "zynqmp-nvmem";
econfig.owner = THIS_MODULE;
econfig.word_size = 1;
- econfig.size = 1;
+ econfig.size = ZYNQMP_NVMEM_SIZE;
econfig.dev = dev;
econfig.add_legacy_fixed_of_cells = true;
- econfig.read_only = true;
econfig.reg_read = zynqmp_nvmem_read;
+ econfig.reg_write = zynqmp_nvmem_write;

return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &econfig));
}
--
2.25.1


2024-02-24 11:47:37

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 08/11] MAINTAINERS: Add maintainers for ZynqMP NVMEM driver

From: Praveen Teja Kundanala <[email protected]>

Add maintainers for ZynqMP NVMEM driver and driver document.

Signed-off-by: Praveen Teja Kundanala <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d1052fa6a69..b3103e03015e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24233,6 +24233,14 @@ M: Harsha <[email protected]>
S: Maintained
F: drivers/crypto/xilinx/zynqmp-sha.c

+XILINX ZYNQMP NVMEM DRIVER
+M: Praveen Teja Kundanala <[email protected]>
+M: Kalyani Akula <[email protected]>
+R: Michal Simek <[email protected]>
+S: Maintained
+F: Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml
+F: drivers/nvmem/zynqmp_nvmem.c
+
XILLYBUS DRIVER
M: Eli Billauer <[email protected]>
L: [email protected]
--
2.25.1


2024-02-24 11:48:19

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 10/11] nvmem: core: make nvmem_layout_bus_type const

From: "Ricardo B. Marliere" <[email protected]>

Since commit d492cc2573a0 ("driver core: device.h: make struct bus_type
a const *"), the driver core can properly handle constant struct
bus_type, move the nvmem_layout_bus_type variable to be a constant
structure as well, placing it into read-only memory which can not be
modified at runtime.

Cc: Greg Kroah-Hartman <[email protected]>
Suggested-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Ricardo B. Marliere <[email protected]>
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nvmem/layouts.c b/drivers/nvmem/layouts.c
index 6a6aa58369ff..8b5e2de138eb 100644
--- a/drivers/nvmem/layouts.c
+++ b/drivers/nvmem/layouts.c
@@ -45,7 +45,7 @@ static void nvmem_layout_bus_remove(struct device *dev)
return drv->remove(layout);
}

-static struct bus_type nvmem_layout_bus_type = {
+static const struct bus_type nvmem_layout_bus_type = {
.name = "nvmem-layout",
.match = nvmem_layout_bus_match,
.probe = nvmem_layout_bus_probe,
--
2.25.1


2024-02-24 11:48:23

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 09/11] nvmem: mtk-efuse: Drop NVMEM device name

From: Chen-Yu Tsai <[email protected]>

The MT8183 has not one but two efuse devices. The static name and ID
causes the second efuse device to fail to probe, due to duplicate sysfs
entries.

With the rework of the mtk-socinfo driver, lookup by name is no longer
necessary. The custom name can simply be dropped.

Signed-off-by: Chen-Yu Tsai <[email protected]>
Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
Tested-by: Nícolas F. R. A. Prado <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/mtk-efuse.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index f5bebcecf9bd..9caf04667341 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -86,7 +86,6 @@ static int mtk_efuse_probe(struct platform_device *pdev)
econfig.size = resource_size(res);
econfig.priv = priv;
econfig.dev = dev;
- econfig.name = "mtk-efuse";
if (pdata->uses_post_processing)
econfig.fixup_dt_cell_info = &mtk_efuse_fixup_dt_cell_info;
nvmem = devm_nvmem_register(dev, &econfig);
--
2.25.1


2024-02-24 11:48:31

by Srinivas Kandagatla

[permalink] [raw]
Subject: [PATCH 11/11] nvmem: core: Print error on wrong bits DT property

From: Markus Schneider-Pargmann <[email protected]>

The algorithms in nvmem core are built with the constraint that
bit_offset < 8. If bit_offset is greater the results are wrong. Print an
error if the devicetree 'bits' property is outside of the valid range
and abort parsing.

Signed-off-by: Markus Schneider-Pargmann <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 980123fb4dde..a9832b5a608e 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -806,6 +806,11 @@ static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_nod
if (addr && len == (2 * sizeof(u32))) {
info.bit_offset = be32_to_cpup(addr++);
info.nbits = be32_to_cpup(addr);
+ if (info.bit_offset >= BITS_PER_BYTE || info.nbits < 1) {
+ dev_err(dev, "nvmem: invalid bits on %pOF\n", child);
+ of_node_put(child);
+ return -EINVAL;
+ }
}

info.np = of_node_get(child);
--
2.25.1