* [PATCH 1/3] nvmem: zynqmp_nvmem: Correct error message for PUF user fuse
2026-05-28 6:43 [PATCH 0/3]nvmem: zynqmp_nvmem: Cleanup and bug fixes Harsh Jain
@ 2026-05-28 6:43 ` Harsh Jain
2026-05-28 6:43 ` [PATCH 2/3] nvmem: zynqmp_nvmem: Use streaming DMA with single kmalloc block Harsh Jain
2026-05-28 6:43 ` [PATCH 3/3] nvmem: zynqmp_nvmem: Drop add_legacy_fixed_of_cells flag Harsh Jain
2 siblings, 0 replies; 4+ messages in thread
From: Harsh Jain @ 2026-05-28 6:43 UTC (permalink / raw)
To: srini, linux-arm-kernel, michal.simek, sarat.chand.savitala,
harish.ediga
Cc: Harsh Jain
From: Harish Ediga <harish.ediga@amd•com>
P_USER_0_64_UPPER_MASK is defined as GENMASK(31, 16), which masks the
upper 16 bits (2 bytes), so the old "lower 4 bytes" wording was
incorrect -- only the lower 2 bytes (bits 15:0) are programmable.
Fixes: 737c0c8d07b5 ("nvmem: zynqmp_nvmem: Add support to access efuse")
Signed-off-by: Harish Ediga <harish.ediga@amd•com>
Co-developed-by: Harsh Jain <h.jain@amd•com>
Signed-off-by: Harsh Jain <h.jain@amd•com>
---
drivers/nvmem/zynqmp_nvmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index d297ff150dc0..6be00a2be9e4 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -84,7 +84,7 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
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");
+ dev_err(dev, "Only lower 2 bytes are allowed to be programmed in P_USER_0 & P_USER_64\n");
return -EOPNOTSUPP;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/3] nvmem: zynqmp_nvmem: Use streaming DMA with single kmalloc block
2026-05-28 6:43 [PATCH 0/3]nvmem: zynqmp_nvmem: Cleanup and bug fixes Harsh Jain
2026-05-28 6:43 ` [PATCH 1/3] nvmem: zynqmp_nvmem: Correct error message for PUF user fuse Harsh Jain
@ 2026-05-28 6:43 ` Harsh Jain
2026-05-28 6:43 ` [PATCH 3/3] nvmem: zynqmp_nvmem: Drop add_legacy_fixed_of_cells flag Harsh Jain
2 siblings, 0 replies; 4+ messages in thread
From: Harsh Jain @ 2026-05-28 6:43 UTC (permalink / raw)
To: srini, linux-arm-kernel, michal.simek, sarat.chand.savitala,
harish.ediga
Cc: Harsh Jain
From: Harish Ediga <harish.ediga@amd•com>
Coherent buffers are required only when the device and host update
memory in parallel, which is not the case here. Replace the coherent
buffer with the streaming DMA API and combine the two allocations
into a single kmalloc block.
Signed-off-by: Harish Ediga <harish.ediga@amd•com>
Co-developed-by: Harsh Jain <h.jain@amd•com>
Signed-off-by: Harsh Jain <h.jain@amd•com>
---
drivers/nvmem/zynqmp_nvmem.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index 6be00a2be9e4..e8ab4ce23fb9 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -60,14 +60,13 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
void *val, size_t bytes, enum efuse_access flag,
unsigned int pufflag)
{
+ size_t words = bytes / WORD_INBYTES;
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;
unsigned int value;
char *data;
+ int ret;
if (bytes % WORD_INBYTES != 0) {
dev_err(dev, "Bytes requested should be word aligned\n");
@@ -95,18 +94,18 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
}
}
- efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse),
- &dma_addr, GFP_KERNEL);
+ efuse = kmalloc(sizeof(*efuse) + bytes, GFP_KERNEL);
if (!efuse)
return -ENOMEM;
- data = dma_alloc_coherent(dev, bytes,
- &dma_buf, GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto efuse_data_fail;
+ dma_addr = dma_map_single(dev, efuse, sizeof(*efuse) + bytes,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, dma_addr)) {
+ kfree(efuse);
+ return -ENOMEM;
}
+ data = (char *)efuse + sizeof(*efuse);
if (flag == EFUSE_WRITE) {
memcpy(data, val, bytes);
efuse->flag = EFUSE_WRITE;
@@ -114,12 +113,18 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
efuse->flag = EFUSE_READ;
}
- efuse->src = dma_buf;
+ efuse->src = dma_addr + sizeof(*efuse);
efuse->size = words;
efuse->offset = offset;
efuse->pufuserfuse = pufflag;
+ /* Sync DMA address updated after mapping*/
+ dma_sync_single_for_device(dev, dma_addr, sizeof(*efuse) + bytes,
+ DMA_BIDIRECTIONAL);
zynqmp_pm_efuse_access(dma_addr, (u32 *)&ret);
+ dma_unmap_single(dev, dma_addr, sizeof(*efuse) + bytes,
+ DMA_BIDIRECTIONAL);
+
if (ret != 0) {
if (ret == EFUSE_NOT_ENABLED) {
dev_err(dev, "efuse access is not enabled\n");
@@ -133,12 +138,9 @@ static int zynqmp_efuse_access(void *context, unsigned int offset,
if (flag == EFUSE_READ)
memcpy(val, data, bytes);
+
efuse_access_err:
- dma_free_coherent(dev, bytes,
- data, dma_buf);
-efuse_data_fail:
- dma_free_coherent(dev, sizeof(struct xilinx_efuse),
- efuse, dma_addr);
+ kfree(efuse);
return ret;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread