Re: [PATCH v2 2/2] drivers: misc: Add driver to access ZynqMP efuses

2024-05-29 Thread Michal Simek




On 5/15/24 14:41, lukas.funke-...@weidmueller.com wrote:

From: Lukas Funke 

Add driver to access ZynqMP efuses. This is a u-boot port of [1].

[1] 
https://lore.kernel.org/all/20240224114516.86365-8-srinivas.kandaga...@linaro.org/

Signed-off-by: Lukas Funke 
---

Changes in v2:
- Drop vendor specific fuse cmd, use existing fuse cmd
- Minor code refactoring (reverse x-mas tree)

  drivers/misc/Kconfig|   8 +
  drivers/misc/Makefile   |   1 +
  drivers/misc/zynqmp_efuse.c | 324 
  3 files changed, 333 insertions(+)
  create mode 100644 drivers/misc/zynqmp_efuse.c


would be good to get also 3/3 which enables
CONFIG_CMD_FUSE=y
CONFIG_ZYNQMP_EFUSE=y

in zynqmp defconfigs (virt and kria) to have it enabled.



diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6009d55f400..c07f50c9a76 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -298,6 +298,14 @@ config FSL_SEC_MON
  Security Monitor can be transitioned on any security failures,
  like software violations or hardware security violations.
  
+config ZYNQMP_EFUSE

+   bool "Enable ZynqMP eFUSE Driver"
+   depends on ZYNQMP_FIRMWARE
+   help
+ Enable access to Zynq UltraScale (ZynqMP) eFUSEs thought PMU firmware
+ interface. ZnyqMP has 256 eFUSEs where some of them are security 
related
+ and cannot be read back (i.e. AES key).
+
  choice
prompt "Security monitor interaction endianess"
depends on FSL_SEC_MON
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e53d52c47b3..68ba5648eab 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -92,3 +92,4 @@ obj-$(CONFIG_ESM_K3) += k3_esm.o
  obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
  obj-$(CONFIG_SL28CPLD) += sl28cpld.o
  obj-$(CONFIG_SPL_SOCFPGA_DT_REG) += socfpga_dtreg.o
+obj-$(CONFIG_ZYNQMP_EFUSE) += zynqmp_efuse.o
diff --git a/drivers/misc/zynqmp_efuse.c b/drivers/misc/zynqmp_efuse.c
new file mode 100644
index 000..98a39c1ebdd
--- /dev/null
+++ b/drivers/misc/zynqmp_efuse.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek 
+ *
+ * (C) Copyright 2024 Weidmueller Interface GmbH
+ * Lukas Funke 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SILICON_REVISION_MASK 0xF
+#define P_USER_0_64_UPPER_MASK 0x5FFF
+#define P_USER_127_LOWER_4_BIT_MASK 0xF
+#define WORD_INBYTES   (4)
+#define SOC_VER_SIZE   (0x4)
+#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)
+#define EFUSE_READ (0)
+#define EFUSE_WRITE(1)


I did compare it with the latest upstream version and there are some differences 
which don't need to be there. Above macros for example



+
+/**
+ * struct efuse_map_entry - offset and length of zynqmp fuses
+ * @offset:offset of efuse to be read/write
+ * @length:length of efuse
+ */
+struct efuse_map_entry {
+   u32 offset;
+   u32 length;
+};
+
+struct efuse_map_entry zynqmp_efuse_table[] = {
+   {0x000, 0x04}, /* soc revision */
+   {0x00c, 0x0c}, /* SoC DNA */
+   {0x020, 0x04}, /* efuse-usr0 */
+   {0x024, 0x04}, /* efuse-usr1 */
+   {0x028, 0x04}, /* efuse-usr2 */
+   {0x02c, 0x04}, /* efuse-usr3 */
+   {0x030, 0x04}, /* efuse-usr4 */
+   {0x034, 0x04}, /* efuse-usr5 */
+   {0x038, 0x04}, /* efuse-usr6 */
+   {0x03c, 0x04}, /* efuse-usr7 */
+   {0x040, 0x04}, /* efuse-miscusr */
+   {0x050, 0x04}, /* efuse-chash */
+   {0x054, 0x04}, /* efuse-pufmisc */
+   {0x058, 0x04}, /* efuse-sec */
+   {0x05c, 0x04}, /* efuse-spkid */
+   {0x060, 0x30}, /* efuse-aeskey */
+   {0x0a0, 0x30}, /* ppk0-hash */
+   {0x0d0, 0x30}, /* ppk1-hash */
+   {0x100, 0x7f}, /* pufuser */
+};
+
+/**
+ * struct xilinx_efuse - the basic structure
+ * @src:   address of the buffer to store the data to be write/read
+ * @size:  no of words to be read/write
+ * @offset:offset to be read/write`


a little bit different description compare to upsream linux


+ * @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;
+   u32 flag;
+   u32 pufuserfuse;
+};
+
+static int zynqmp_efuse_get_length(u32 offset, u32 *base_offset, u32 *len)
+{
+   struct efuse_map_entry *fuse;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(zynqmp_efuse_table); ++i) {
+   

[PATCH v2 2/2] drivers: misc: Add driver to access ZynqMP efuses

2024-05-15 Thread lukas . funke-oss
From: Lukas Funke 

Add driver to access ZynqMP efuses. This is a u-boot port of [1].

[1] 
https://lore.kernel.org/all/20240224114516.86365-8-srinivas.kandaga...@linaro.org/

Signed-off-by: Lukas Funke 
---

Changes in v2:
- Drop vendor specific fuse cmd, use existing fuse cmd
- Minor code refactoring (reverse x-mas tree)

 drivers/misc/Kconfig|   8 +
 drivers/misc/Makefile   |   1 +
 drivers/misc/zynqmp_efuse.c | 324 
 3 files changed, 333 insertions(+)
 create mode 100644 drivers/misc/zynqmp_efuse.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6009d55f400..c07f50c9a76 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -298,6 +298,14 @@ config FSL_SEC_MON
  Security Monitor can be transitioned on any security failures,
  like software violations or hardware security violations.
 
+config ZYNQMP_EFUSE
+   bool "Enable ZynqMP eFUSE Driver"
+   depends on ZYNQMP_FIRMWARE
+   help
+ Enable access to Zynq UltraScale (ZynqMP) eFUSEs thought PMU firmware
+ interface. ZnyqMP has 256 eFUSEs where some of them are security 
related
+ and cannot be read back (i.e. AES key).
+
 choice
prompt "Security monitor interaction endianess"
depends on FSL_SEC_MON
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e53d52c47b3..68ba5648eab 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -92,3 +92,4 @@ obj-$(CONFIG_ESM_K3) += k3_esm.o
 obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
 obj-$(CONFIG_SL28CPLD) += sl28cpld.o
 obj-$(CONFIG_SPL_SOCFPGA_DT_REG) += socfpga_dtreg.o
+obj-$(CONFIG_ZYNQMP_EFUSE) += zynqmp_efuse.o
diff --git a/drivers/misc/zynqmp_efuse.c b/drivers/misc/zynqmp_efuse.c
new file mode 100644
index 000..98a39c1ebdd
--- /dev/null
+++ b/drivers/misc/zynqmp_efuse.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek 
+ *
+ * (C) Copyright 2024 Weidmueller Interface GmbH
+ * Lukas Funke 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SILICON_REVISION_MASK 0xF
+#define P_USER_0_64_UPPER_MASK 0x5FFF
+#define P_USER_127_LOWER_4_BIT_MASK 0xF
+#define WORD_INBYTES   (4)
+#define SOC_VER_SIZE   (0x4)
+#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)
+#define EFUSE_READ (0)
+#define EFUSE_WRITE(1)
+
+/**
+ * struct efuse_map_entry - offset and length of zynqmp fuses
+ * @offset:offset of efuse to be read/write
+ * @length:length of efuse
+ */
+struct efuse_map_entry {
+   u32 offset;
+   u32 length;
+};
+
+struct efuse_map_entry zynqmp_efuse_table[] = {
+   {0x000, 0x04}, /* soc revision */
+   {0x00c, 0x0c}, /* SoC DNA */
+   {0x020, 0x04}, /* efuse-usr0 */
+   {0x024, 0x04}, /* efuse-usr1 */
+   {0x028, 0x04}, /* efuse-usr2 */
+   {0x02c, 0x04}, /* efuse-usr3 */
+   {0x030, 0x04}, /* efuse-usr4 */
+   {0x034, 0x04}, /* efuse-usr5 */
+   {0x038, 0x04}, /* efuse-usr6 */
+   {0x03c, 0x04}, /* efuse-usr7 */
+   {0x040, 0x04}, /* efuse-miscusr */
+   {0x050, 0x04}, /* efuse-chash */
+   {0x054, 0x04}, /* efuse-pufmisc */
+   {0x058, 0x04}, /* efuse-sec */
+   {0x05c, 0x04}, /* efuse-spkid */
+   {0x060, 0x30}, /* efuse-aeskey */
+   {0x0a0, 0x30}, /* ppk0-hash */
+   {0x0d0, 0x30}, /* ppk1-hash */
+   {0x100, 0x7f}, /* pufuser */
+};
+
+/**
+ * struct xilinx_efuse - the basic structure
+ * @src:   address of the buffer to store the data to be write/read
+ * @size:  no of words to be read/write
+ * @offset:offset to be read/write`
+ * @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;
+   u32 flag;
+   u32 pufuserfuse;
+};
+
+static int zynqmp_efuse_get_length(u32 offset, u32 *base_offset, u32 *len)
+{
+   struct efuse_map_entry *fuse;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(zynqmp_efuse_table); ++i) {
+   fuse = _efuse_table[i];
+   if (offset >= fuse->offset &&
+   offset < fuse->offset + fuse->length) {
+   *base_offset = fuse->offset;
+   *len = fuse->length;
+   return 0;
+   }
+   }
+
+   return -ENOENT;
+}
+
+static int zynqmp_efuse_access(struct udevice *dev, unsigned int offset,
+