From a9fd69f3107ef3d800c192915d863a848b2c4b28 Mon Sep 17 00:00:00 2001 From: Poovendhan Selvaraj Date: Mon, 24 Apr 2023 17:03:38 +0530 Subject: [PATCH] qca : Read the TME-l OEM fuse parameters from qfprom core address Add support to read the TME-l OEM fuse parameters from qfprom address Change-Id: Ia4f0766a68b67fccc59a09883dd7ef11bc970eef Signed-off-by: Poovendhan Selvaraj --- arch/arm/cpu/armv7/qca/common/scm.c | 28 +++++++++++ arch/arm/include/asm/arch-qca-common/scm.h | 6 +++ board/qca/arm/common/cmd_blowsecfuse.c | 56 ++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/arch/arm/cpu/armv7/qca/common/scm.c b/arch/arm/cpu/armv7/qca/common/scm.c index fd4c9d79d8..851ed3cc0d 100644 --- a/arch/arm/cpu/armv7/qca/common/scm.c +++ b/arch/arm/cpu/armv7/qca/common/scm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /** @@ -490,6 +491,29 @@ int qca_scm_fuseipq(u32 svc_id, u32 cmd_id, void *buf, size_t len) return ret; } +int qca_scm_list_ipq5332_fuse(u32 svc_id, u32 cmd_id, + struct fuse_payload *fuse, size_t len) +{ + int ret = 0; + if (is_scm_armv8()) + { + struct qca_scm_desc desc = {0}; + dma_addr_t dma_fuse; + dma_fuse = dma_map_single(fuse, len, + DMA_FROM_DEVICE); + desc.arginfo = QCA_SCM_ARGS(2, SCM_IO_WRITE, SCM_VAL); + desc.args[0] = dma_fuse; + desc.args[1] = len; + + ret = scm_call_64(svc_id, cmd_id, &desc); + } + else + { + ret = scm_call(svc_id, cmd_id, fuse, len, NULL, 0); + } + return ret; +} + int qca_scm_part_info(void *cmd_buf, size_t cmd_len) { @@ -751,6 +775,10 @@ int qca_scm_fuseipq(u32 svc_id, u32 cmd_id, void *buf, size_t len) { return 0; } +int qca_scm_list_ipq5332_fuse(u32 svc_id, u32 cmd_id, void *buf, size_t len) +{ + return 0; +} int qca_scm_part_info(void *cmd_buf, size_t cmd_len) { return 0; diff --git a/arch/arm/include/asm/arch-qca-common/scm.h b/arch/arm/include/asm/arch-qca-common/scm.h index 938fff71d2..c83d81fa5a 100644 --- a/arch/arm/include/asm/arch-qca-common/scm.h +++ b/arch/arm/include/asm/arch-qca-common/scm.h @@ -119,6 +119,11 @@ struct scm_response { u32 is_complete; }; +struct fuse_payload { + u32 fuse_addr; + u32 lsb_val; + u32 msb_val; +}; int scm_init(void); extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, @@ -133,6 +138,7 @@ int qca_scm_crypto(int, void *, u32); int qca_scm_sdi(void); int qca_scm_dload(u32); int qca_scm_fuseipq(u32, u32, void *, size_t); +int qca_scm_list_ipq5332_fuse(u32, u32, struct fuse_payload *, size_t); bool is_scm_armv8(void); int qca_scm_secure_authenticate(void *cmd_buf, size_t cmd_len); int qca_scm_part_info(void *cmd_buf, size_t cmd_len); diff --git a/board/qca/arm/common/cmd_blowsecfuse.c b/board/qca/arm/common/cmd_blowsecfuse.c index a6f987b69d..1bcd8295ee 100644 --- a/board/qca/arm/common/cmd_blowsecfuse.c +++ b/board/qca/arm/common/cmd_blowsecfuse.c @@ -26,6 +26,8 @@ #define FUSEPROV_INVALID_HASH 0x09 #define FUSEPROV_SECDAT_LOCK_BLOWN 0xB #define TZ_BLOW_FUSE_SECDAT 0x20 +#define TZ_READ_FUSE_VALUE 0x22 +#define MAX_FUSE_ADDR_SIZE 0x8 int do_fuseipq(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { @@ -64,6 +66,60 @@ int do_fuseipq(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return 0; } +#ifdef CONFIG_IPQ5332 +int do_list_ipq5332_fuse(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + int index, next = 0; + unsigned long addr = 0xA00E8; + struct fuse_payload *fuse = NULL; + + fuse = malloc(sizeof(struct fuse_payload ) * MAX_FUSE_ADDR_SIZE); + if (fuse == NULL) { + return 1; + } + + memset(fuse, 0, MAX_FUSE_ADDR_SIZE * sizeof(struct fuse_payload)); + + fuse[0].fuse_addr = 0xA00D0; + for (index = 1; index < MAX_FUSE_ADDR_SIZE; index++) { + fuse[index].fuse_addr = addr + next; + next += 0x8; + } + + ret = qca_scm_list_ipq5332_fuse(SCM_SVC_FUSE, TZ_READ_FUSE_VALUE, fuse, + sizeof(struct fuse_payload ) * MAX_FUSE_ADDR_SIZE); + + printf("Fuse Name\tAddress\t\tValue\n"); + printf("------------------------------------------------\n"); + + printf("TME_AUTH_EN\t0x%08X\t0x%08X\n", fuse[0].fuse_addr, + fuse[0].lsb_val & 0x41); + printf("TME_OEM_ID\t0x%08X\t0x%08X\n", fuse[0].fuse_addr, + fuse[0].lsb_val & 0xFFFF0000); + printf("TME_PRODUCT_ID\t0x%08X\t0x%08X\n", fuse[0].fuse_addr + 0x4, + fuse[0].msb_val & 0xFFFF); + + for (index = 1; index < MAX_FUSE_ADDR_SIZE; index++) { + printf("TME_MRC_HASH\t0x%08X\t0x%08X\n", + fuse[index].fuse_addr, fuse[index].lsb_val); + printf("TME_MRC_HASH\t0x%08X\t0x%08X\n", + fuse[index].fuse_addr + 0x4, fuse[index].msb_val); + } + + if (ret) { + printf("Failed to read OEM parameters at Address 0x%X\n", ret); + } + free(fuse); + return 0; +} + +U_BOOT_CMD(list_ipq5332_fuse, 1, 0, do_list_ipq5332_fuse, + "fuse set of QFPROM registers from memory\n", + ""); +#endif + U_BOOT_CMD(fuseipq, 2, 0, do_fuseipq, "fuse QFPROM registers from memory\n", "fuseipq [address] - Load fuse(s) and blows in the qfprom\n");