From 922d4504bcab8aebe159d811cc1e804f2d7bf8f7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 15 Jun 2023 18:09:04 +0800 Subject: imx: scu_api: update to version 1.16 and add more APIs Upgrade SCFW API to 1.16 Add more APIs: sc_misc_get_button_status sc_pm_reboot sc_seco_v2x_build_info Signed-off-by: Peng Fan --- drivers/misc/imx8/scu_api.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/imx8/scu_api.c b/drivers/misc/imx8/scu_api.c index dfede7f1d5f..3e3002ba6df 100644 --- a/drivers/misc/imx8/scu_api.c +++ b/drivers/misc/imx8/scu_api.c @@ -481,6 +481,22 @@ int sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource, sc_misc_temp_t temp, return 0; } +void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status) +{ + struct sc_rpc_msg_s msg; + struct udevice *dev = gd->arch.scu_dev; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 1U; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_MISC); + RPC_FUNC(&msg) = (u8)(MISC_FUNC_GET_BUTTON_STATUS); + + misc_call(dev, SC_FALSE, &msg, 1U, &msg, 1U); + + if (status) + *status = (sc_bool_t)(!!(RPC_U8(&msg, 0U))); +} + /* RM */ sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr) { @@ -851,6 +867,21 @@ int sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable, return ret; } +void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_PM); + RPC_FUNC(&msg) = (u8)(PM_FUNC_REBOOT); + RPC_U8(&msg, 0U) = (u8)(type); + RPC_SIZE(&msg) = 2U; + + misc_call(dev, SC_TRUE, &msg, size, &msg, size); +} + int sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, sc_pm_power_mode_t *mode) { @@ -877,6 +908,28 @@ int sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource, return ret; } +int sc_timer_set_wdog_window(sc_ipc_t ipc, sc_timer_wdog_time_t window) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 2U; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_TIMER); + RPC_FUNC(&msg) = (u8)(TIMER_FUNC_SET_WDOG_WINDOW); + + RPC_U32(&msg, 0U) = (u32)(window); + + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + printf("%s: window:%u: res:%d\n", + __func__, window, RPC_R8(&msg)); + + return ret; +} + int sc_seco_authenticate(sc_ipc_t ipc, sc_seco_auth_cmd_t cmd, sc_faddr_t addr) { @@ -974,6 +1027,31 @@ void sc_seco_build_info(sc_ipc_t ipc, u32 *version, u32 *commit) *commit = RPC_U32(&msg, 4U); } +int sc_seco_v2x_build_info(sc_ipc_t ipc, u32 *version, u32 *commit) +{ + struct udevice *dev = gd->arch.scu_dev; + struct sc_rpc_msg_s msg; + int size = sizeof(struct sc_rpc_msg_s); + int ret; + + RPC_VER(&msg) = SC_RPC_VERSION; + RPC_SIZE(&msg) = 1U; + RPC_SVC(&msg) = (u8)(SC_RPC_SVC_SECO); + RPC_FUNC(&msg) = (u8)(SECO_FUNC_V2X_BUILD_INFO); + + ret = misc_call(dev, SC_FALSE, &msg, size, &msg, size); + if (ret) + printf("%s: res:%d\n", __func__, RPC_R8(&msg)); + + if (version) + *version = RPC_U32(&msg, 0U); + + if (commit) + *commit = RPC_U32(&msg, 4U); + + return ret; +} + int sc_seco_get_event(sc_ipc_t ipc, u8 idx, u32 *event) { struct udevice *dev = gd->arch.scu_dev; -- cgit v1.3.1 From d3ee9dbd5984321d4a2932e19a59f455d8d90817 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 15 Jun 2023 18:09:05 +0800 Subject: imx: use generic name ele(EdgeLockSecure Enclave) Per NXP requirement, we rename all the NXP EdgeLock Secure Enclave code including comment, folder and API name to ELE to align. Signed-off-by: Peng Fan --- arch/arm/Kconfig | 4 +- arch/arm/include/asm/arch-imx9/ccm_regs.h | 2 +- arch/arm/include/asm/global_data.h | 4 +- arch/arm/include/asm/mach-imx/ele_api.h | 150 ++++++++ arch/arm/include/asm/mach-imx/s400_api.h | 148 -------- arch/arm/mach-imx/ele_ahab.c | 15 +- arch/arm/mach-imx/imx8ulp/rdc.c | 18 +- arch/arm/mach-imx/imx8ulp/soc.c | 16 +- arch/arm/mach-imx/imx8ulp/upower/upower_hal.c | 6 +- arch/arm/mach-imx/imx9/clock.c | 8 +- arch/arm/mach-imx/imx9/clock_root.c | 2 +- arch/arm/mach-imx/imx9/soc.c | 16 +- arch/arm/mach-imx/imx9/trdc.c | 14 +- board/freescale/imx8ulp_evk/spl.c | 10 +- board/freescale/imx93_evk/spl.c | 1 - drivers/misc/Kconfig | 4 +- drivers/misc/Makefile | 2 +- drivers/misc/imx_ele/Makefile | 4 + drivers/misc/imx_ele/ele_api.c | 492 ++++++++++++++++++++++++++ drivers/misc/imx_ele/ele_mu.c | 235 ++++++++++++ drivers/misc/imx_ele/fuse.c | 320 +++++++++++++++++ drivers/misc/sentinel/Makefile | 4 - drivers/misc/sentinel/fuse.c | 320 ----------------- drivers/misc/sentinel/s400_api.c | 492 -------------------------- drivers/misc/sentinel/s4mu.c | 235 ------------ 25 files changed, 1261 insertions(+), 1261 deletions(-) create mode 100644 arch/arm/include/asm/mach-imx/ele_api.h delete mode 100644 arch/arm/include/asm/mach-imx/s400_api.h create mode 100644 drivers/misc/imx_ele/Makefile create mode 100644 drivers/misc/imx_ele/ele_api.c create mode 100644 drivers/misc/imx_ele/ele_mu.c create mode 100644 drivers/misc/imx_ele/fuse.c delete mode 100644 drivers/misc/sentinel/Makefile delete mode 100644 drivers/misc/sentinel/fuse.c delete mode 100644 drivers/misc/sentinel/s400_api.c delete mode 100644 drivers/misc/sentinel/s4mu.c (limited to 'drivers/misc') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4604d41410c..17d69d27262 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -882,7 +882,7 @@ config ARCH_IMX8ULP select SUPPORT_SPL select GPIO_EXTRA_HEADER select MISC - select IMX_SENTINEL + select IMX_ELE imply CMD_DM config ARCH_IMX9 @@ -894,7 +894,7 @@ config ARCH_IMX9 select SUPPORT_SPL select GPIO_EXTRA_HEADER select MISC - select IMX_SENTINEL + select IMX_ELE imply CMD_DM config ARCH_IMXRT diff --git a/arch/arm/include/asm/arch-imx9/ccm_regs.h b/arch/arm/include/asm/arch-imx9/ccm_regs.h index d326a6ea516..f6ec8fda3e6 100644 --- a/arch/arm/include/asm/arch-imx9/ccm_regs.h +++ b/arch/arm/include/asm/arch-imx9/ccm_regs.h @@ -12,7 +12,7 @@ #define ARM_A55_MTR_BUS_CLK_ROOT 1 #define ARM_A55_CLK_ROOT 2 #define M33_CLK_ROOT 3 -#define SENTINEL_CLK_ROOT 4 +#define ELE_CLK_ROOT 4 #define BUS_WAKEUP_CLK_ROOT 5 #define BUS_AON_CLK_ROOT 6 #define WAKEUP_AXI_CLK_ROOT 7 diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 0c130757110..2a222c53882 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -92,8 +92,8 @@ struct arch_global_data { struct udevice *scu_dev; #endif -#ifdef CONFIG_IMX_SENTINEL - struct udevice *s400_dev; +#ifdef CONFIG_IMX_ELE + struct udevice *ele_dev; u32 soc_rev; u32 lifecycle; u32 uid[4]; diff --git a/arch/arm/include/asm/mach-imx/ele_api.h b/arch/arm/include/asm/mach-imx/ele_api.h new file mode 100644 index 00000000000..120da0854e4 --- /dev/null +++ b/arch/arm/include/asm/mach-imx/ele_api.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2021 NXP + */ + +#ifndef __ELE_API_H__ +#define __ELE_API_H__ + +#define ELE_VERSION 0x6 +#define ELE_CMD_TAG 0x17 +#define ELE_RESP_TAG 0xe1 + +/* ELE commands */ +#define ELE_PING_REQ (0x01) +#define ELE_FW_AUTH_REQ (0x02) +#define ELE_RESTART_RST_TIMER_REQ (0x04) +#define ELE_DUMP_DEBUG_BUFFER_REQ (0x21) +#define ELE_OEM_CNTN_AUTH_REQ (0x87) +#define ELE_VERIFY_IMAGE_REQ (0x88) +#define ELE_RELEASE_CONTAINER_REQ (0x89) +#define ELE_WRITE_SECURE_FUSE_REQ (0x91) +#define ELE_FWD_LIFECYCLE_UP_REQ (0x95) +#define ELE_READ_FUSE_REQ (0x97) +#define ELE_GET_FW_VERSION_REQ (0x9D) +#define ELE_RET_LIFECYCLE_UP_REQ (0xA0) +#define ELE_GET_EVENTS_REQ (0xA2) +#define ELE_START_RNG (0xA3) +#define ELE_GENERATE_DEK_BLOB (0xAF) +#define ELE_ENABLE_PATCH_REQ (0xC3) +#define ELE_RELEASE_RDC_REQ (0xC4) +#define ELE_GET_FW_STATUS_REQ (0xC5) +#define ELE_ENABLE_OTFAD_REQ (0xC6) +#define ELE_RESET_REQ (0xC7) +#define ELE_UPDATE_OTP_CLKDIV_REQ (0xD0) +#define ELE_POWER_DOWN_REQ (0xD1) +#define ELE_ENABLE_APC_REQ (0xD2) +#define ELE_ENABLE_RTC_REQ (0xD3) +#define ELE_DEEP_POWER_DOWN_REQ (0xD4) +#define ELE_STOP_RST_TIMER_REQ (0xD5) +#define ELE_WRITE_FUSE_REQ (0xD6) +#define ELE_RELEASE_CAAM_REQ (0xD7) +#define ELE_RESET_A35_CTX_REQ (0xD8) +#define ELE_MOVE_TO_UNSECURED_REQ (0xD9) +#define ELE_GET_INFO_REQ (0xDA) +#define ELE_ATTEST_REQ (0xDB) +#define ELE_RELEASE_PATCH_REQ (0xDC) +#define ELE_OTP_SEQ_SWITH_REQ (0xDD) + +/* ELE failure indications */ +#define ELE_ROM_PING_FAILURE_IND (0x0A) +#define ELE_FW_PING_FAILURE_IND (0x1A) +#define ELE_BAD_SIGNATURE_FAILURE_IND (0xF0) +#define ELE_BAD_HASH_FAILURE_IND (0xF1) +#define ELE_INVALID_LIFECYCLE_IND (0xF2) +#define ELE_PERMISSION_DENIED_FAILURE_IND (0xF3) +#define ELE_INVALID_MESSAGE_FAILURE_IND (0xF4) +#define ELE_BAD_VALUE_FAILURE_IND (0xF5) +#define ELE_BAD_FUSE_ID_FAILURE_IND (0xF6) +#define ELE_BAD_CONTAINER_FAILURE_IND (0xF7) +#define ELE_BAD_VERSION_FAILURE_IND (0xF8) +#define ELE_INVALID_KEY_FAILURE_IND (0xF9) +#define ELE_BAD_KEY_HASH_FAILURE_IND (0xFA) +#define ELE_NO_VALID_CONTAINER_FAILURE_IND (0xFB) +#define ELE_BAD_CERTIFICATE_FAILURE_IND (0xFC) +#define ELE_BAD_UID_FAILURE_IND (0xFD) +#define ELE_BAD_MONOTONIC_COUNTER_FAILURE_IND (0xFE) +#define ELE_MUST_SIGNED_FAILURE_IND (0xE0) +#define ELE_NO_AUTHENTICATION_FAILURE_IND (0xEE) +#define ELE_BAD_SRK_SET_FAILURE_IND (0xEF) +#define ELE_UNALIGNED_PAYLOAD_FAILURE_IND (0xA6) +#define ELE_WRONG_SIZE_FAILURE_IND (0xA7) +#define ELE_ENCRYPTION_FAILURE_IND (0xA8) +#define ELE_DECRYPTION_FAILURE_IND (0xA9) +#define ELE_OTP_PROGFAIL_FAILURE_IND (0xAA) +#define ELE_OTP_LOCKED_FAILURE_IND (0xAB) +#define ELE_OTP_INVALID_IDX_FAILURE_IND (0xAD) +#define ELE_TIME_OUT_FAILURE_IND (0xB0) +#define ELE_BAD_PAYLOAD_FAILURE_IND (0xB1) +#define ELE_WRONG_ADDRESS_FAILURE_IND (0xB4) +#define ELE_DMA_FAILURE_IND (0xB5) +#define ELE_DISABLED_FEATURE_FAILURE_IND (0xB6) +#define ELE_MUST_ATTEST_FAILURE_IND (0xB7) +#define ELE_RNG_NOT_STARTED_FAILURE_IND (0xB8) +#define ELE_CRC_ERROR_IND (0xB9) +#define ELE_AUTH_SKIPPED_OR_FAILED_FAILURE_IND (0xBB) +#define ELE_INCONSISTENT_PAR_FAILURE_IND (0xBC) +#define ELE_RNG_INST_FAILURE_FAILURE_IND (0xBD) +#define ELE_LOCKED_REG_FAILURE_IND (0xBE) +#define ELE_BAD_ID_FAILURE_IND (0xBF) +#define ELE_INVALID_OPERATION_FAILURE_IND (0xC0) +#define ELE_NON_SECURE_STATE_FAILURE_IND (0xC1) +#define ELE_MSG_TRUNCATED_IND (0xC2) +#define ELE_BAD_IMAGE_NUM_FAILURE_IND (0xC3) +#define ELE_BAD_IMAGE_ADDR_FAILURE_IND (0xC4) +#define ELE_BAD_IMAGE_PARAM_FAILURE_IND (0xC5) +#define ELE_BAD_IMAGE_TYPE_FAILURE_IND (0xC6) +#define ELE_CORRUPTED_SRK_FAILURE_IND (0xD0) +#define ELE_OUT_OF_MEMORY_IND (0xD1) +#define ELE_CSTM_FAILURE_IND (0xCF) +#define ELE_OLD_VERSION_FAILURE_IND (0xCE) +#define ELE_WRONG_BOOT_MODE_FAILURE_IND (0xCD) +#define ELE_APC_ALREADY_ENABLED_FAILURE_IND (0xCB) +#define ELE_RTC_ALREADY_ENABLED_FAILURE_IND (0xCC) +#define ELE_ABORT_IND (0xFF) + +/* ELE IPC identifier */ +#define ELE_IPC_MU_RTD (0x1) +#define ELE_IPC_MU_APD (0x2) + +/* ELE Status*/ +#define ELE_SUCCESS_IND (0xD6) +#define ELE_FAILURE_IND (0x29) + +#define ELE_MAX_MSG 255U + +struct ele_msg { + u8 version; + u8 size; + u8 command; + u8 tag; + u32 data[(ELE_MAX_MSG - 1U)]; +}; + +struct ele_get_info_data { + u32 hdr; + u32 soc; + u32 lc; + u32 uid[4]; + u32 sha256_rom_patch[8]; + u32 sha_fw[8]; + u32 oem_srkh[16]; + u32 state; +}; + +int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response); +int ele_auth_oem_ctnr(ulong ctnr_addr, u32 *response); +int ele_release_container(u32 *response); +int ele_verify_image(u32 img_id, u32 *response); +int ele_forward_lifecycle(u16 life_cycle, u32 *response); +int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response); +int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response); +int ele_release_caam(u32 core_did, u32 *response); +int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response); +int ele_get_events(u32 *events, u32 *events_cnt, u32 *response); +int ele_dump_buffer(u32 *buffer, u32 buffer_length); +int ele_get_info(struct ele_get_info_data *info, u32 *response); +int ele_get_fw_status(u32 *status, u32 *response); +int ele_release_m33_trout(void); + +#endif diff --git a/arch/arm/include/asm/mach-imx/s400_api.h b/arch/arm/include/asm/mach-imx/s400_api.h deleted file mode 100644 index 5582ff1a254..00000000000 --- a/arch/arm/include/asm/mach-imx/s400_api.h +++ /dev/null @@ -1,148 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2021 NXP - */ - -#ifndef __S400_API_H__ -#define __S400_API_H__ - -#define AHAB_VERSION 0x6 -#define AHAB_CMD_TAG 0x17 -#define AHAB_RESP_TAG 0xe1 - -/* ELE commands */ -#define ELE_PING_REQ (0x01) -#define ELE_FW_AUTH_REQ (0x02) -#define ELE_RESTART_RST_TIMER_REQ (0x04) -#define ELE_DUMP_DEBUG_BUFFER_REQ (0x21) -#define ELE_OEM_CNTN_AUTH_REQ (0x87) -#define ELE_VERIFY_IMAGE_REQ (0x88) -#define ELE_RELEASE_CONTAINER_REQ (0x89) -#define ELE_WRITE_SECURE_FUSE_REQ (0x91) -#define ELE_FWD_LIFECYCLE_UP_REQ (0x95) -#define ELE_READ_FUSE_REQ (0x97) -#define ELE_GET_FW_VERSION_REQ (0x9D) -#define ELE_RET_LIFECYCLE_UP_REQ (0xA0) -#define ELE_GET_EVENTS_REQ (0xA2) -#define ELE_ENABLE_PATCH_REQ (0xC3) -#define ELE_RELEASE_RDC_REQ (0xC4) -#define ELE_GET_FW_STATUS_REQ (0xC5) -#define ELE_ENABLE_OTFAD_REQ (0xC6) -#define ELE_RESET_REQ (0xC7) -#define ELE_UPDATE_OTP_CLKDIV_REQ (0xD0) -#define ELE_POWER_DOWN_REQ (0xD1) -#define ELE_ENABLE_APC_REQ (0xD2) -#define ELE_ENABLE_RTC_REQ (0xD3) -#define ELE_DEEP_POWER_DOWN_REQ (0xD4) -#define ELE_STOP_RST_TIMER_REQ (0xD5) -#define ELE_WRITE_FUSE_REQ (0xD6) -#define ELE_RELEASE_CAAM_REQ (0xD7) -#define ELE_RESET_A35_CTX_REQ (0xD8) -#define ELE_MOVE_TO_UNSECURED_REQ (0xD9) -#define ELE_GET_INFO_REQ (0xDA) -#define ELE_ATTEST_REQ (0xDB) -#define ELE_RELEASE_PATCH_REQ (0xDC) -#define ELE_OTP_SEQ_SWITH_REQ (0xDD) - -/* ELE failure indications */ -#define ELE_ROM_PING_FAILURE_IND (0x0A) -#define ELE_FW_PING_FAILURE_IND (0x1A) -#define ELE_BAD_SIGNATURE_FAILURE_IND (0xF0) -#define ELE_BAD_HASH_FAILURE_IND (0xF1) -#define ELE_INVALID_LIFECYCLE_IND (0xF2) -#define ELE_PERMISSION_DENIED_FAILURE_IND (0xF3) -#define ELE_INVALID_MESSAGE_FAILURE_IND (0xF4) -#define ELE_BAD_VALUE_FAILURE_IND (0xF5) -#define ELE_BAD_FUSE_ID_FAILURE_IND (0xF6) -#define ELE_BAD_CONTAINER_FAILURE_IND (0xF7) -#define ELE_BAD_VERSION_FAILURE_IND (0xF8) -#define ELE_INVALID_KEY_FAILURE_IND (0xF9) -#define ELE_BAD_KEY_HASH_FAILURE_IND (0xFA) -#define ELE_NO_VALID_CONTAINER_FAILURE_IND (0xFB) -#define ELE_BAD_CERTIFICATE_FAILURE_IND (0xFC) -#define ELE_BAD_UID_FAILURE_IND (0xFD) -#define ELE_BAD_MONOTONIC_COUNTER_FAILURE_IND (0xFE) -#define ELE_MUST_SIGNED_FAILURE_IND (0xE0) -#define ELE_NO_AUTHENTICATION_FAILURE_IND (0xEE) -#define ELE_BAD_SRK_SET_FAILURE_IND (0xEF) -#define ELE_UNALIGNED_PAYLOAD_FAILURE_IND (0xA6) -#define ELE_WRONG_SIZE_FAILURE_IND (0xA7) -#define ELE_ENCRYPTION_FAILURE_IND (0xA8) -#define ELE_DECRYPTION_FAILURE_IND (0xA9) -#define ELE_OTP_PROGFAIL_FAILURE_IND (0xAA) -#define ELE_OTP_LOCKED_FAILURE_IND (0xAB) -#define ELE_OTP_INVALID_IDX_FAILURE_IND (0xAD) -#define ELE_TIME_OUT_FAILURE_IND (0xB0) -#define ELE_BAD_PAYLOAD_FAILURE_IND (0xB1) -#define ELE_WRONG_ADDRESS_FAILURE_IND (0xB4) -#define ELE_DMA_FAILURE_IND (0xB5) -#define ELE_DISABLED_FEATURE_FAILURE_IND (0xB6) -#define ELE_MUST_ATTEST_FAILURE_IND (0xB7) -#define ELE_RNG_NOT_STARTED_FAILURE_IND (0xB8) -#define ELE_CRC_ERROR_IND (0xB9) -#define ELE_AUTH_SKIPPED_OR_FAILED_FAILURE_IND (0xBB) -#define ELE_INCONSISTENT_PAR_FAILURE_IND (0xBC) -#define ELE_RNG_INST_FAILURE_FAILURE_IND (0xBD) -#define ELE_LOCKED_REG_FAILURE_IND (0xBE) -#define ELE_BAD_ID_FAILURE_IND (0xBF) -#define ELE_INVALID_OPERATION_FAILURE_IND (0xC0) -#define ELE_NON_SECURE_STATE_FAILURE_IND (0xC1) -#define ELE_MSG_TRUNCATED_IND (0xC2) -#define ELE_BAD_IMAGE_NUM_FAILURE_IND (0xC3) -#define ELE_BAD_IMAGE_ADDR_FAILURE_IND (0xC4) -#define ELE_BAD_IMAGE_PARAM_FAILURE_IND (0xC5) -#define ELE_BAD_IMAGE_TYPE_FAILURE_IND (0xC6) -#define ELE_CORRUPTED_SRK_FAILURE_IND (0xD0) -#define ELE_OUT_OF_MEMORY_IND (0xD1) -#define ELE_CSTM_FAILURE_IND (0xCF) -#define ELE_OLD_VERSION_FAILURE_IND (0xCE) -#define ELE_WRONG_BOOT_MODE_FAILURE_IND (0xCD) -#define ELE_APC_ALREADY_ENABLED_FAILURE_IND (0xCB) -#define ELE_RTC_ALREADY_ENABLED_FAILURE_IND (0xCC) -#define ELE_ABORT_IND (0xFF) - -/* ELE IPC identifier */ -#define ELE_IPC_MU_RTD (0x1) -#define ELE_IPC_MU_APD (0x2) - -/* ELE Status*/ -#define ELE_SUCCESS_IND (0xD6) -#define ELE_FAILURE_IND (0x29) - -#define S400_MAX_MSG 255U - -struct sentinel_msg { - u8 version; - u8 size; - u8 command; - u8 tag; - u32 data[(S400_MAX_MSG - 1U)]; -}; - -struct sentinel_get_info_data { - u32 hdr; - u32 soc; - u32 lc; - u32 uid[4]; - u32 sha256_rom_patch[8]; - u32 sha_fw[8]; - u32 oem_srkh[16]; - u32 state; -}; - -int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response); -int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response); -int ahab_release_container(u32 *response); -int ahab_verify_image(u32 img_id, u32 *response); -int ahab_forward_lifecycle(u16 life_cycle, u32 *response); -int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response); -int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response); -int ahab_release_caam(u32 core_did, u32 *response); -int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response); -int ahab_dump_buffer(u32 *buffer, u32 buffer_length); -int ahab_get_info(struct sentinel_get_info_data *info, u32 *response); -int ahab_get_fw_status(u32 *status, u32 *response); -int ahab_release_m33_trout(void); -int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response); - -#endif diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 99fc5402719..9bb37919638 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -7,14 +7,13 @@ #include #include #include -#include +#include #include #include #include #include #include #include -#include #include DECLARE_GLOBAL_DATA_PTR; @@ -267,7 +266,7 @@ int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length) flush_dcache_range(IMG_CONTAINER_BASE, IMG_CONTAINER_BASE + ALIGN(length, CONFIG_SYS_CACHELINE_SIZE) - 1); - err = ahab_auth_oem_ctnr(IMG_CONTAINER_BASE, &resp); + err = ele_auth_oem_ctnr(IMG_CONTAINER_BASE, &resp); if (err) { printf("Authenticate container hdr failed, return %d, resp 0x%x\n", err, resp); @@ -282,7 +281,7 @@ int ahab_auth_release(void) int err; u32 resp; - err = ahab_release_container(&resp); + err = ele_release_container(&resp); if (err) { printf("Error: release container failed, resp 0x%x!\n", resp); display_ahab_auth_ind(resp); @@ -296,7 +295,7 @@ int ahab_verify_cntr_image(struct boot_img_t *img, int image_index) int err; u32 resp; - err = ahab_verify_image(image_index, &resp); + err = ele_verify_image(image_index, &resp); if (err) { printf("Authenticate img %d failed, return %d, resp 0x%x\n", image_index, err, resp); @@ -485,7 +484,7 @@ static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc, return -EPERM; } - err = ahab_forward_lifecycle(8, &resp); + err = ele_forward_lifecycle(8, &resp); if (err != 0) { printf("Error in forward lifecycle to OEM closed\n"); return -EIO; @@ -502,7 +501,7 @@ int ahab_dump(void) int ret, i = 0; do { - ret = ahab_dump_buffer(buffer, 32); + ret = ele_dump_buffer(buffer, 32); if (ret < 0) { printf("Error in dump AHAB log\n"); return -EIO; @@ -547,7 +546,7 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, char *const display_life_cycle(lc); - ret = ahab_get_events(events, &cnt, NULL); + ret = ele_get_events(events, &cnt, NULL); if (ret) { printf("Get ELE EVENTS error %d\n", ret); return CMD_RET_FAILURE; diff --git a/arch/arm/mach-imx/imx8ulp/rdc.c b/arch/arm/mach-imx/imx8ulp/rdc.c index 50b097b035a..cfc09e79cbd 100644 --- a/arch/arm/mach-imx/imx8ulp/rdc.c +++ b/arch/arm/mach-imx/imx8ulp/rdc.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -203,12 +203,12 @@ int xrdc_config_msc(u32 msc, u32 index, u32 dom, u32 perm) int release_rdc(enum rdc_type type) { ulong s_mu_base = 0x27020000UL; - struct sentinel_msg msg; + struct ele_msg msg; int ret; u32 rdc_id = (type == RDC_XRDC) ? 0x78 : 0x74; - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_RELEASE_RDC_REQ; msg.data[0] = (rdc_id << 8) | 0x2; /* A35 XRDC */ @@ -266,7 +266,7 @@ void xrdc_mrc_region_set_access(int mrc_index, u32 addr, u32 access) mrgd[4] |= ((access & 0xFFF) << 16); } - /* not handle other cases, since S400 only set ACCESS1 and 2 */ + /* not handle other cases, since ELE only set ACCESS1 and 2 */ writel(mrgd[4], xrdc_base + off + 0x10); return; } @@ -295,7 +295,7 @@ void xrdc_init_mda(void) void xrdc_init_mrc(void) { - /* Re-config MRC3 for SRAM0 in case protected by S400 */ + /* Re-config MRC3 for SRAM0 in case protected by ELE */ xrdc_config_mrc_w0_w1(3, 0, 0x22010000, 0x10000); xrdc_config_mrc_dx_perm(3, 0, 0, 1); xrdc_config_mrc_dx_perm(3, 0, 1, 1); @@ -320,7 +320,7 @@ void xrdc_init_mrc(void) xrdc_config_mrc_dx_perm(5, 0, 1, 1); xrdc_config_mrc_w3_w4(5, 0, 0x0, 0x80000FFF); - /* Set MRC6 for DDR access from Sentinel */ + /* Set MRC6 for DDR access from ELE */ xrdc_config_mrc_w0_w1(6, 0, CFG_SYS_SDRAM_BASE, PHYS_SDRAM_SIZE); xrdc_config_mrc_dx_perm(6, 0, 4, 1); xrdc_config_mrc_w3_w4(6, 0, 0x0, 0x80000FFF); @@ -404,7 +404,7 @@ int trdc_mbc_set_access(u32 mbc_x, u32 dom_x, u32 mem_x, u32 blk_x, bool sec_acc val &= ~(0xFU << offset); /* MBC0-3 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MBC0_MEMN_GLBAC0 */ if (sec_access) { @@ -445,7 +445,7 @@ int trdc_mrc_region_set_access(u32 mrc_x, u32 dom_x, u32 addr_start, u32 addr_en continue; /* MRC0,1 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MRCx_MEMN_GLBAC0 */ if (sec_access) { diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c index 81eae02b6a8..e23cf60d126 100644 --- a/arch/arm/mach-imx/imx8ulp/soc.c +++ b/arch/arm/mach-imx/imx8ulp/soc.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -70,7 +70,7 @@ int mmc_get_env_dev(void) } #endif -static void set_cpu_info(struct sentinel_get_info_data *info) +static void set_cpu_info(struct ele_get_info_data *info) { gd->arch.soc_rev = info->soc; gd->arch.lifecycle = info->lc; @@ -582,9 +582,9 @@ void get_board_serial(struct tag_serialnr *serialnr) u32 res; int ret; - ret = ahab_read_common_fuse(1, uid, 4, &res); + ret = ele_read_common_fuse(1, uid, 4, &res); if (ret) - printf("ahab read fuse failed %d, 0x%x\n", ret, res); + printf("ele read fuse failed %d, 0x%x\n", ret, res); else printf("UID 0x%x,0x%x,0x%x,0x%x\n", uid[0], uid[1], uid[2], uid[3]); @@ -783,7 +783,7 @@ int imx8ulp_dm_post_init(void) struct udevice *devp; int ret; u32 res; - struct sentinel_get_info_data *info = (struct sentinel_get_info_data *)SRAM0_BASE; + struct ele_get_info_data *info = (struct ele_get_info_data *)SRAM0_BASE; ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(imx8ulp_mu), &devp); if (ret) { @@ -791,11 +791,11 @@ int imx8ulp_dm_post_init(void) return ret; } - ret = ahab_get_info(info, &res); + ret = ele_get_info(info, &res); if (ret) { - printf("ahab_get_info failed %d\n", ret); + printf("ele_get_info failed %d\n", ret); /* fallback to A0.1 revision */ - memset((void *)info, 0, sizeof(struct sentinel_get_info_data)); + memset((void *)info, 0, sizeof(struct ele_get_info_data)); info->soc = 0xa000084d; } diff --git a/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c b/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c index fcb02ed3af6..b471a75caa1 100644 --- a/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c +++ b/arch/arm/mach-imx/imx8ulp/upower/upower_hal.c @@ -217,8 +217,8 @@ int upower_init(void) * CM33 Cache * PowerQuad RAM * ETF RAM - * Sentinel PKC, Data RAM1, Inst RAM0/1 - * Sentinel ROM + * ELE PKC, Data RAM1, Inst RAM0/1 + * ELE ROM * uPower IRAM/DRAM * uPower ROM * CM33 ROM @@ -230,7 +230,7 @@ int upower_init(void) * SSRAM Partition 7_a(128KB) * SSRAM Partition 7_b(64KB) * SSRAM Partition 7_c(64KB) - * Sentinel Data RAM0, Inst RAM2 + * ELE Data RAM0, Inst RAM2 */ /* MIPI-CSI FIFO BIT28 not set */ memon = 0x3FFFFFEFFFFFFCUL; diff --git a/arch/arm/mach-imx/imx9/clock.c b/arch/arm/mach-imx/imx9/clock.c index a7ecccaf879..766a8811c1f 100644 --- a/arch/arm/mach-imx/imx9/clock.c +++ b/arch/arm/mach-imx/imx9/clock.c @@ -709,8 +709,8 @@ struct imx_clk_setting imx_clk_settings[] = { /* Set A55 mtr bus to 133M */ {ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, - /* Sentinel to 133M */ - {SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, + /* ELE to 133M */ + {ELE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* Bus_wakeup to 133M */ {BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* Bus_AON to 133M */ @@ -740,8 +740,8 @@ struct imx_clk_setting imx_clk_settings[] = { {ARM_A55_PERIPH_CLK_ROOT, SYS_PLL_PFD0, 3}, /* Set A55 mtr bus to 133M */ {ARM_A55_MTR_BUS_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, - /* Sentinel to 200M */ - {SENTINEL_CLK_ROOT, SYS_PLL_PFD1_DIV2, 2}, + /* ELE to 200M */ + {ELE_CLK_ROOT, SYS_PLL_PFD1_DIV2, 2}, /* Bus_wakeup to 133M */ {BUS_WAKEUP_CLK_ROOT, SYS_PLL_PFD1_DIV2, 3}, /* Bus_AON to 133M */ diff --git a/arch/arm/mach-imx/imx9/clock_root.c b/arch/arm/mach-imx/imx9/clock_root.c index 06b93f60996..7d7ae865946 100644 --- a/arch/arm/mach-imx/imx9/clock_root.c +++ b/arch/arm/mach-imx/imx9/clock_root.c @@ -34,7 +34,7 @@ static struct clk_root_map clk_root_array[] = { { ARM_A55_MTR_BUS_CLK_ROOT, 2 }, { ARM_A55_CLK_ROOT, 0 }, { M33_CLK_ROOT, 2 }, - { SENTINEL_CLK_ROOT, 2 }, + { ELE_CLK_ROOT, 2 }, { BUS_WAKEUP_CLK_ROOT, 2 }, { BUS_AON_CLK_ROOT, 2 }, { WAKEUP_AXI_CLK_ROOT, 0 }, diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c index a0565f3aea0..f43b73a6c21 100644 --- a/arch/arm/mach-imx/imx9/soc.c +++ b/arch/arm/mach-imx/imx9/soc.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include @@ -151,7 +151,7 @@ u32 get_cpu_temp_grade(int *minc, int *maxc) return val; } -static void set_cpu_info(struct sentinel_get_info_data *info) +static void set_cpu_info(struct ele_get_info_data *info) { gd->arch.soc_rev = info->soc; gd->arch.lifecycle = info->lc; @@ -557,7 +557,7 @@ int imx9_probe_mu(void *ctx, struct event *event) struct udevice *devp; int node, ret; u32 res; - struct sentinel_get_info_data info; + struct ele_get_info_data info; node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx93-mu-s4"); @@ -568,7 +568,7 @@ int imx9_probe_mu(void *ctx, struct event *event) if (gd->flags & GD_FLG_RELOC) return 0; - ret = ahab_get_info(&info, &res); + ret = ele_get_info(&info, &res); if (ret) return ret; @@ -642,7 +642,7 @@ static int mix_power_init(enum mix_power_domain pd) mem_id = SRC_MEM_MEDIA; scr = BIT(5); - /* Enable S400 handshake */ + /* Enable ELE handshake */ struct blk_ctrl_s_aonmix_regs *s_regs = (struct blk_ctrl_s_aonmix_regs *)BLK_CTRL_S_ANOMIX_BASE_ADDR; @@ -759,8 +759,8 @@ int m33_prepare(void) while (!(val & SRC_MIX_SLICE_FUNC_STAT_RST_STAT)) val = readl(&mix_regs->func_stat); - /* Release Sentinel TROUT */ - ahab_release_m33_trout(); + /* Release ELE TROUT */ + ele_release_m33_trout(); /* Mask WDOG1 IRQ from A55, we use it for M33 reset */ setbits_le32(&s_regs->ca55_irq_mask[1], BIT(6)); @@ -768,7 +768,7 @@ int m33_prepare(void) /* Turn on WDOG1 clock */ ccm_lpcg_on(CCGR_WDG1, 1); - /* Set sentinel LP handshake for M33 reset */ + /* Set ELE LP handshake for M33 reset */ setbits_le32(&s_regs->lp_handshake[0], BIT(6)); /* Clear M33 TCM for ECC */ diff --git a/arch/arm/mach-imx/imx9/trdc.c b/arch/arm/mach-imx/imx9/trdc.c index e05c7048106..d0f855bb1bc 100644 --- a/arch/arm/mach-imx/imx9/trdc.c +++ b/arch/arm/mach-imx/imx9/trdc.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #define DID_NUM 16 @@ -196,7 +196,7 @@ int trdc_mbc_blk_config(ulong trdc_reg, u32 mbc_x, u32 dom_x, u32 mem_x, val &= ~(0xFU << offset); /* MBC0-3 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MBC0_MEMN_GLBAC0 */ if (sec_access) { @@ -266,7 +266,7 @@ int trdc_mrc_region_config(ulong trdc_reg, u32 mrc_x, u32 dom_x, u32 addr_start, continue; /* MRC0,1 - * Global 0, 0x7777 secure pri/user read/write/execute, S400 has already set it. + * Global 0, 0x7777 secure pri/user read/write/execute, ELE has already set it. * So select MRCx_MEMN_GLBAC0 */ if (sec_access) { @@ -315,7 +315,7 @@ bool trdc_mbc_enabled(ulong trdc_base) int release_rdc(u8 xrdc) { ulong s_mu_base = 0x47520000UL; - struct sentinel_msg msg; + struct ele_msg msg; int ret; u32 rdc_id; @@ -336,8 +336,8 @@ int release_rdc(u8 xrdc) return -EINVAL; } - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; msg.size = 2; msg.command = ELE_RELEASE_RDC_REQ; msg.data[0] = (rdc_id << 8) | 0x2; /* A55 */ @@ -394,7 +394,7 @@ void trdc_init(void) /* DDR */ trdc_mrc_set_control(0x49010000, 0, 0, 0x7777); - /* S400*/ + /* ELE */ trdc_mrc_region_config(0x49010000, 0, 0, 0x80000000, 0xFFFFFFFF, false, 0); /* MTR */ diff --git a/board/freescale/imx8ulp_evk/spl.c b/board/freescale/imx8ulp_evk/spl.c index a0dad5f9831..b7c6ff092b1 100644 --- a/board/freescale/imx8ulp_evk/spl.c +++ b/board/freescale/imx8ulp_evk/spl.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -63,9 +63,9 @@ void display_ele_fw_version(void) u32 fw_version, sha1, res; int ret; - ret = ahab_get_fw_version(&fw_version, &sha1, &res); + ret = ele_get_fw_version(&fw_version, &sha1, &res); if (ret) { - printf("ahab get firmware version failed %d, 0x%x\n", ret, res); + printf("ele get firmware version failed %d, 0x%x\n", ret, res); } else { printf("ELE firmware version %u.%u.%u-%x", (fw_version & (0x00ff0000)) >> 16, @@ -120,9 +120,9 @@ void spl_board_init(void) set_lpav_qos(); /* Enable A35 access to the CAAM */ - ret = ahab_release_caam(0x7, &res); + ret = ele_release_caam(0x7, &res); if (ret) - printf("ahab release caam failed %d, 0x%x\n", ret, res); + printf("ele release caam failed %d, 0x%x\n", ret, res); } void board_init_f(ulong dummy) diff --git a/board/freescale/imx93_evk/spl.c b/board/freescale/imx93_evk/spl.c index 352ad79cb67..63883b30dd7 100644 --- a/board/freescale/imx93_evk/spl.c +++ b/board/freescale/imx93_evk/spl.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 04460f1acb2..b9f5c7a37ae 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -364,8 +364,8 @@ config NPCM_OTP To compile this driver as a module, choose M here: the module will be called npcm_otp. -config IMX_SENTINEL - bool "Enable i.MX Sentinel MU driver and API" +config IMX_ELE + bool "Enable i.MX EdgeLock Enclave MU driver and API" depends on MISC && (ARCH_IMX9 || ARCH_IMX8ULP) help If you say Y here to enable Message Unit driver to work with diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 52aed096021..fd8805f34bd 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -47,7 +47,7 @@ obj-$(CONFIG_SANDBOX) += irq_sandbox.o irq_sandbox_test.o obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o obj-$(CONFIG_IMX8) += imx8/ -obj-$(CONFIG_IMX_SENTINEL) += sentinel/ +obj-$(CONFIG_IMX_ELE) += imx_ele/ obj-$(CONFIG_LED_STATUS) += status_led.o obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o diff --git a/drivers/misc/imx_ele/Makefile b/drivers/misc/imx_ele/Makefile new file mode 100644 index 00000000000..f8d8c55f983 --- /dev/null +++ b/drivers/misc/imx_ele/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += ele_api.o ele_mu.o +obj-$(CONFIG_CMD_FUSE) += fuse.o diff --git a/drivers/misc/imx_ele/ele_api.c b/drivers/misc/imx_ele/ele_api.c new file mode 100644 index 00000000000..56605714f44 --- /dev/null +++ b/drivers/misc/imx_ele/ele_api.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020 NXP + * + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 2; + msg.command = ELE_RELEASE_RDC_REQ; + switch (xrdc) { + case 0: + msg.data[0] = (0x74 << 8) | core_id; + break; + case 1: + msg.data[0] = (0x78 << 8) | core_id; + break; + case 2: + msg.data[0] = (0x82 << 8) | core_id; + break; + case 3: + msg.data[0] = (0x86 << 8) | core_id; + break; + default: + printf("Error: wrong xrdc index %u\n", xrdc); + return -EINVAL; + } + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, core id %u, response 0x%x\n", + __func__, ret, core_id, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_auth_oem_ctnr(ulong ctnr_addr, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 3; + msg.command = ELE_OEM_CNTN_AUTH_REQ; + msg.data[0] = upper_32_bits(ctnr_addr); + msg.data[1] = lower_32_bits(ctnr_addr); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, cntr_addr 0x%lx, response 0x%x\n", + __func__, ret, ctnr_addr, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_release_container(u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_RELEASE_CONTAINER_REQ; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_verify_image(u32 img_id, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 2; + msg.command = ELE_VERIFY_IMAGE_REQ; + msg.data[0] = 1 << img_id; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, img_id %u, response 0x%x\n", + __func__, ret, img_id, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_forward_lifecycle(u16 life_cycle, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 2; + msg.command = ELE_FWD_LIFECYCLE_UP_REQ; + msg.data[0] = life_cycle; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, life_cycle 0x%x, response 0x%x\n", + __func__, ret, life_cycle, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + if (!fuse_words) { + printf("Invalid parameters for fuse read\n"); + return -EINVAL; + } + + if ((fuse_id != 1 && fuse_num != 1) || + (fuse_id == 1 && fuse_num != 4)) { + printf("Invalid fuse number parameter\n"); + return -EINVAL; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 2; + msg.command = ELE_READ_FUSE_REQ; + msg.data[0] = fuse_id; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n", + __func__, ret, fuse_id, msg.data[0]); + + if (response) + *response = msg.data[0]; + + fuse_words[0] = msg.data[1]; + if (fuse_id == 1) { + /* OTP_UNIQ_ID */ + fuse_words[1] = msg.data[2]; + fuse_words[2] = msg.data[3]; + fuse_words[3] = msg.data[4]; + } + + return ret; +} + +int ele_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 3; + msg.command = ELE_WRITE_FUSE_REQ; + msg.data[0] = (32 << 16) | (fuse_id << 5); + if (lock) + msg.data[0] |= (1 << 31); + + msg.data[1] = fuse_val; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n", + __func__, ret, fuse_id, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_release_caam(u32 core_did, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 2; + msg.command = ELE_RELEASE_CAAM_REQ; + msg.data[0] = core_did; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + if (!fw_version) { + printf("Invalid parameters for f/w version read\n"); + return -EINVAL; + } + + if (!sha1) { + printf("Invalid parameters for commit sha1\n"); + return -EINVAL; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_GET_FW_VERSION_REQ; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + if (response) + *response = msg.data[0]; + + *fw_version = msg.data[1]; + *sha1 = msg.data[2]; + + return ret; +} + +int ele_dump_buffer(u32 *buffer, u32 buffer_length) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret, i = 0; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_DUMP_DEBUG_BUFFER_REQ; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) { + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + return ret; + } + + if (buffer) { + buffer[i++] = *(u32 *)&msg; /* Need dump the response header */ + for (; i < buffer_length && i < msg.size; i++) + buffer[i] = msg.data[i - 1]; + } + + return i; +} + +int ele_get_info(struct ele_get_info_data *info, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 4; + msg.command = ELE_GET_INFO_REQ; + msg.data[0] = upper_32_bits((ulong)info); + msg.data[1] = lower_32_bits((ulong)info); + msg.data[2] = sizeof(struct ele_get_info_data); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_get_fw_status(u32 *status, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_GET_FW_STATUS_REQ; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + if (response) + *response = msg.data[0]; + + *status = msg.data[1] & 0xF; + + return ret; +} + +int ele_release_m33_trout(void) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_ENABLE_RTC_REQ; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + return ret; +} + +int ele_get_events(u32 *events, u32 *events_cnt, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret, i = 0; + u32 actual_events; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + if (!events || !events_cnt || *events_cnt == 0) { + printf("Invalid parameters for %s\n", __func__); + return -EINVAL; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_GET_EVENTS_REQ; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + if (response) + *response = msg.data[0]; + + if (!ret) { + actual_events = msg.data[1] & 0xffff; + if (*events_cnt < actual_events) + actual_events = *events_cnt; + + for (; i < actual_events; i++) + events[i] = msg.data[i + 2]; + + *events_cnt = actual_events; + } + + return ret; +} diff --git a/drivers/misc/imx_ele/ele_mu.c b/drivers/misc/imx_ele/ele_mu.c new file mode 100644 index 00000000000..0d34b8c9010 --- /dev/null +++ b/drivers/misc/imx_ele/ele_mu.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020-2022 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct imx8ulp_mu { + struct mu_type *base; +}; + +#define MU_SR_TE0_MASK BIT(0) +#define MU_SR_RF0_MASK BIT(0) +#define MU_TR_COUNT 4 +#define MU_RR_COUNT 4 + +void mu_hal_init(ulong base) +{ + struct mu_type *mu_base = (struct mu_type *)base; + + writel(0, &mu_base->tcr); + writel(0, &mu_base->rcr); +} + +int mu_hal_sendmsg(ulong base, u32 reg_index, u32 msg) +{ + struct mu_type *mu_base = (struct mu_type *)base; + u32 mask = MU_SR_TE0_MASK << reg_index; + u32 val; + int ret; + + assert(reg_index < MU_TR_COUNT); + + debug("sendmsg sr 0x%x\n", readl(&mu_base->sr)); + + /* Wait TX register to be empty. */ + ret = readl_poll_timeout(&mu_base->tsr, val, val & mask, 10000); + if (ret < 0) { + debug("%s timeout\n", __func__); + return -ETIMEDOUT; + } + + debug("tr[%d] 0x%x\n", reg_index, msg); + + writel(msg, &mu_base->tr[reg_index]); + + return 0; +} + +int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg) +{ + struct mu_type *mu_base = (struct mu_type *)base; + u32 mask = MU_SR_RF0_MASK << reg_index; + u32 val; + int ret; + + assert(reg_index < MU_TR_COUNT); + + debug("receivemsg sr 0x%x\n", readl(&mu_base->sr)); + + /* Wait RX register to be full. */ + ret = readl_poll_timeout(&mu_base->rsr, val, val & mask, 10000); + if (ret < 0) { + debug("%s timeout\n", __func__); + return -ETIMEDOUT; + } + + *msg = readl(&mu_base->rr[reg_index]); + + debug("rr[%d] 0x%x\n", reg_index, *msg); + + return 0; +} + +static int imx8ulp_mu_read(struct mu_type *base, void *data) +{ + struct ele_msg *msg = (struct ele_msg *)data; + int ret; + u8 count = 0; + + if (!msg) + return -EINVAL; + + /* Read first word */ + ret = mu_hal_receivemsg((ulong)base, 0, (u32 *)msg); + if (ret) + return ret; + count++; + + /* Check size */ + if (msg->size > ELE_MAX_MSG) { + *((u32 *)msg) = 0; + return -EINVAL; + } + + /* Read remaining words */ + while (count < msg->size) { + ret = mu_hal_receivemsg((ulong)base, count % MU_RR_COUNT, + &msg->data[count - 1]); + if (ret) + return ret; + count++; + } + + return 0; +} + +static int imx8ulp_mu_write(struct mu_type *base, void *data) +{ + struct ele_msg *msg = (struct ele_msg *)data; + int ret; + u8 count = 0; + + if (!msg) + return -EINVAL; + + /* Check size */ + if (msg->size > ELE_MAX_MSG) + return -EINVAL; + + /* Write first word */ + ret = mu_hal_sendmsg((ulong)base, 0, *((u32 *)msg)); + if (ret) + return ret; + count++; + + /* Write remaining words */ + while (count < msg->size) { + ret = mu_hal_sendmsg((ulong)base, count % MU_TR_COUNT, + msg->data[count - 1]); + if (ret) + return ret; + count++; + } + + return 0; +} + +/* + * Note the function prototype use msgid as the 2nd parameter, here + * we take it as no_resp. + */ +static int imx8ulp_mu_call(struct udevice *dev, int no_resp, void *tx_msg, + int tx_size, void *rx_msg, int rx_size) +{ + struct imx8ulp_mu *priv = dev_get_priv(dev); + u32 result; + int ret; + + /* Expect tx_msg, rx_msg are the same value */ + if (rx_msg && tx_msg != rx_msg) + printf("tx_msg %p, rx_msg %p\n", tx_msg, rx_msg); + + ret = imx8ulp_mu_write(priv->base, tx_msg); + if (ret) + return ret; + if (!no_resp) { + ret = imx8ulp_mu_read(priv->base, rx_msg); + if (ret) + return ret; + } + + result = ((struct ele_msg *)rx_msg)->data[0]; + if ((result & 0xff) == 0xd6) + return 0; + + return -EIO; +} + +static int imx8ulp_mu_probe(struct udevice *dev) +{ + struct imx8ulp_mu *priv = dev_get_priv(dev); + fdt_addr_t addr; + + debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv); + + addr = devfdt_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = (struct mu_type *)addr; + + debug("mu base 0x%lx\n", (ulong)priv->base); + + /* U-Boot not enable interrupts, so need to enable RX interrupts */ + mu_hal_init((ulong)priv->base); + + gd->arch.ele_dev = dev; + + return 0; +} + +static int imx8ulp_mu_remove(struct udevice *dev) +{ + return 0; +} + +static int imx8ulp_mu_bind(struct udevice *dev) +{ + debug("%s(dev=%p)\n", __func__, dev); + + return 0; +} + +static struct misc_ops imx8ulp_mu_ops = { + .call = imx8ulp_mu_call, +}; + +static const struct udevice_id imx8ulp_mu_ids[] = { + { .compatible = "fsl,imx8ulp-mu" }, + { .compatible = "fsl,imx93-mu-s4" }, + { } +}; + +U_BOOT_DRIVER(imx8ulp_mu) = { + .name = "imx8ulp_mu", + .id = UCLASS_MISC, + .of_match = imx8ulp_mu_ids, + .probe = imx8ulp_mu_probe, + .bind = imx8ulp_mu_bind, + .remove = imx8ulp_mu_remove, + .ops = &imx8ulp_mu_ops, + .priv_auto = sizeof(struct imx8ulp_mu), +}; diff --git a/drivers/misc/imx_ele/fuse.c b/drivers/misc/imx_ele/fuse.c new file mode 100644 index 00000000000..4e4dcb42cdd --- /dev/null +++ b/drivers/misc/imx_ele/fuse.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define FUSE_BANKS 64 +#define WORDS_PER_BANKS 8 + +struct fsb_map_entry { + s32 fuse_bank; + u32 fuse_words; + bool redundancy; +}; + +struct ele_map_entry { + s32 fuse_bank; + u32 fuse_words; + u32 fuse_offset; + u32 ele_index; +}; + +#if defined(CONFIG_IMX8ULP) +#define FSB_OTP_SHADOW 0x800 + +struct fsb_map_entry fsb_mapping_table[] = { + { 3, 8 }, + { 4, 8 }, + { -1, 48 }, /* Reserve 48 words */ + { 5, 8 }, + { 6, 8 }, + { 8, 4, true }, + { 24, 4, true }, + { 26, 4, true }, + { 27, 4, true }, + { 28, 8 }, + { 29, 8 }, + { 30, 8 }, + { 31, 8 }, + { 37, 8 }, + { 38, 8 }, + { 39, 8 }, + { 40, 8 }, + { 41, 8 }, + { 42, 8 }, + { 43, 8 }, + { 44, 8 }, + { 45, 8 }, + { 46, 8 }, +}; + +/* None ECC banks such like Redundancy or Bit protect */ +u32 nonecc_fuse_banks[] = { + 0, 1, 8, 12, 16, 22, 24, 25, 26, 27, 36, 41, 51, 56 +}; + +struct ele_map_entry ele_api_mapping_table[] = { + { 1, 8 }, /* LOCK */ + { 2, 8 }, /* ECID */ + { 7, 4, 0, 1 }, /* OTP_UNIQ_ID */ + { 15, 8 }, /* OEM SRK HASH */ + { 23, 1, 4, 2 }, /* OTFAD */ + { 25, 8 }, /* Test config2 */ + { 26, 8 }, /* PMU */ + { 27, 8 }, /* Test flow/USB */ + { 32, 8 }, /* GP1 */ + { 33, 8 }, /* GP2 */ + { 34, 8 }, /* GP3 */ + { 35, 8 }, /* GP4 */ + { 36, 8 }, /* GP5 */ + { 49, 8 }, /* GP8 */ + { 50, 8 }, /* GP9 */ + { 51, 8 }, /* GP10 */ +}; +#elif defined(CONFIG_ARCH_IMX9) +#define FSB_OTP_SHADOW 0x8000 + +struct fsb_map_entry fsb_mapping_table[] = { + { 0, 8 }, + { 1, 8 }, + { 2, 8 }, + { 3, 8 }, + { 4, 8 }, + { 5, 8 }, + { 6, 4 }, + { -1, 260 }, + { 39, 8 }, + { 40, 8 }, + { 41, 8 }, + { 42, 8 }, + { 43, 8 }, + { 44, 8 }, + { 45, 8 }, + { 46, 8 }, + { 47, 8 }, + { 48, 8 }, + { 49, 8 }, + { 50, 8 }, + { 51, 8 }, + { 52, 8 }, + { 53, 8 }, + { 54, 8 }, + { 55, 8 }, + { 56, 8 }, + { 57, 8 }, + { 58, 8 }, + { 59, 8 }, + { 60, 8 }, + { 61, 8 }, + { 62, 8 }, + { 63, 8 }, +}; + +struct ele_map_entry ele_api_mapping_table[] = { + { 7, 1, 7, 63 }, + { 16, 8, }, + { 17, 8, }, + { 22, 1, 6 }, + { 23, 1, 4 }, +}; +#endif + +static s32 map_fsb_fuse_index(u32 bank, u32 word, bool *redundancy) +{ + s32 size = ARRAY_SIZE(fsb_mapping_table); + s32 i, word_pos = 0; + + /* map the fuse from ocotp fuse map to FSB*/ + for (i = 0; i < size; i++) { + if (fsb_mapping_table[i].fuse_bank != -1 && + fsb_mapping_table[i].fuse_bank == bank && + fsb_mapping_table[i].fuse_words > word) { + break; + } + + word_pos += fsb_mapping_table[i].fuse_words; + } + + if (i == size) + return -1; /* Failed to find */ + + if (fsb_mapping_table[i].redundancy) { + *redundancy = true; + return (word >> 1) + word_pos; + } + + *redundancy = false; + return word + word_pos; +} + +static s32 map_ele_fuse_index(u32 bank, u32 word) +{ + s32 size = ARRAY_SIZE(ele_api_mapping_table); + s32 i; + + /* map the fuse from ocotp fuse map to FSB*/ + for (i = 0; i < size; i++) { + if (ele_api_mapping_table[i].fuse_bank != -1 && + ele_api_mapping_table[i].fuse_bank == bank) { + if (word >= ele_api_mapping_table[i].fuse_offset && + word < (ele_api_mapping_table[i].fuse_offset + + ele_api_mapping_table[i].fuse_words)) + break; + } + } + + if (i == size) + return -1; /* Failed to find */ + + if (ele_api_mapping_table[i].ele_index != 0) + return ele_api_mapping_table[i].ele_index; + + return ele_api_mapping_table[i].fuse_bank * 8 + word; +} + +#if defined(CONFIG_IMX8ULP) +int fuse_sense(u32 bank, u32 word, u32 *val) +{ + s32 word_index; + bool redundancy; + + if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val) + return -EINVAL; + + word_index = map_fsb_fuse_index(bank, word, &redundancy); + if (word_index >= 0) { + *val = readl((ulong)FSB_BASE_ADDR + FSB_OTP_SHADOW + (word_index << 2)); + if (redundancy) + *val = (*val >> ((word % 2) * 16)) & 0xFFFF; + + return 0; + } + + word_index = map_ele_fuse_index(bank, word); + if (word_index >= 0) { + u32 data[4]; + u32 res, size = 4; + int ret; + + /* Only UID return 4 words */ + if (word_index != 1) + size = 1; + + ret = ele_read_common_fuse(word_index, data, size, &res); + if (ret) { + printf("ahab read fuse failed %d, 0x%x\n", ret, res); + return ret; + } + + if (word_index == 1) { + *val = data[word]; /* UID */ + } else if (word_index == 2) { + /* + * OTFAD 3 bits as follow: + * bit 0: OTFAD_ENABLE + * bit 1: OTFAD_DISABLE_OVERRIDE + * bit 2: KEY_BLOB_EN + */ + *val = data[0] << 3; + } else { + *val = data[0]; + } + + return 0; + } + + return -ENOENT; +} +#elif defined(CONFIG_ARCH_IMX9) +int fuse_sense(u32 bank, u32 word, u32 *val) +{ + s32 word_index; + bool redundancy; + + if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val) + return -EINVAL; + + word_index = map_fsb_fuse_index(bank, word, &redundancy); + if (word_index >= 0) { + *val = readl((ulong)FSB_BASE_ADDR + FSB_OTP_SHADOW + (word_index << 2)); + if (redundancy) + *val = (*val >> ((word % 2) * 16)) & 0xFFFF; + + return 0; + } + + word_index = map_ele_fuse_index(bank, word); + if (word_index >= 0) { + u32 data; + u32 res, size = 1; + int ret; + + ret = ele_read_common_fuse(word_index, &data, size, &res); + if (ret) { + printf("ahab read fuse failed %d, 0x%x\n", ret, res); + return ret; + } + + *val = data; + + return 0; + } + + return -ENOENT; +} +#endif + +int fuse_read(u32 bank, u32 word, u32 *val) +{ + return fuse_sense(bank, word, val); +} + +int fuse_prog(u32 bank, u32 word, u32 val) +{ + u32 res; + int ret; + bool lock = false; + + if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val) + return -EINVAL; + + /* Lock 8ULP ECC fuse word, so second programming will return failure. + * iMX9 OTP can protect ECC fuse, so not need it + */ +#if defined(CONFIG_IMX8ULP) + u32 i; + for (i = 0; i < ARRAY_SIZE(nonecc_fuse_banks); i++) { + if (nonecc_fuse_banks[i] == bank) + break; + } + + if (i == ARRAY_SIZE(nonecc_fuse_banks)) + lock = true; +#endif + + ret = ele_write_fuse((bank * 8 + word), val, lock, &res); + if (ret) { + printf("ahab write fuse failed %d, 0x%x\n", ret, res); + return ret; + } + + return 0; +} + +int fuse_override(u32 bank, u32 word, u32 val) +{ + printf("Override fuse to i.MX8ULP in u-boot is forbidden\n"); + return -EPERM; +} diff --git a/drivers/misc/sentinel/Makefile b/drivers/misc/sentinel/Makefile deleted file mode 100644 index 446154cb201..00000000000 --- a/drivers/misc/sentinel/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ - -obj-y += s400_api.o s4mu.o -obj-$(CONFIG_CMD_FUSE) += fuse.o diff --git a/drivers/misc/sentinel/fuse.c b/drivers/misc/sentinel/fuse.c deleted file mode 100644 index 99342d33c06..00000000000 --- a/drivers/misc/sentinel/fuse.c +++ /dev/null @@ -1,320 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2020 NXP - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -#define FUSE_BANKS 64 -#define WORDS_PER_BANKS 8 - -struct fsb_map_entry { - s32 fuse_bank; - u32 fuse_words; - bool redundancy; -}; - -struct s400_map_entry { - s32 fuse_bank; - u32 fuse_words; - u32 fuse_offset; - u32 s400_index; -}; - -#if defined(CONFIG_IMX8ULP) -#define FSB_OTP_SHADOW 0x800 - -struct fsb_map_entry fsb_mapping_table[] = { - { 3, 8 }, - { 4, 8 }, - { -1, 48 }, /* Reserve 48 words */ - { 5, 8 }, - { 6, 8 }, - { 8, 4, true }, - { 24, 4, true }, - { 26, 4, true }, - { 27, 4, true }, - { 28, 8 }, - { 29, 8 }, - { 30, 8 }, - { 31, 8 }, - { 37, 8 }, - { 38, 8 }, - { 39, 8 }, - { 40, 8 }, - { 41, 8 }, - { 42, 8 }, - { 43, 8 }, - { 44, 8 }, - { 45, 8 }, - { 46, 8 }, -}; - -/* None ECC banks such like Redundancy or Bit protect */ -u32 nonecc_fuse_banks[] = { - 0, 1, 8, 12, 16, 22, 24, 25, 26, 27, 36, 41, 51, 56 -}; - -struct s400_map_entry s400_api_mapping_table[] = { - { 1, 8 }, /* LOCK */ - { 2, 8 }, /* ECID */ - { 7, 4, 0, 1 }, /* OTP_UNIQ_ID */ - { 15, 8 }, /* OEM SRK HASH */ - { 23, 1, 4, 2 }, /* OTFAD */ - { 25, 8 }, /* Test config2 */ - { 26, 8 }, /* PMU */ - { 27, 8 }, /* Test flow/USB */ - { 32, 8 }, /* GP1 */ - { 33, 8 }, /* GP2 */ - { 34, 8 }, /* GP3 */ - { 35, 8 }, /* GP4 */ - { 36, 8 }, /* GP5 */ - { 49, 8 }, /* GP8 */ - { 50, 8 }, /* GP9 */ - { 51, 8 }, /* GP10 */ -}; -#elif defined(CONFIG_ARCH_IMX9) -#define FSB_OTP_SHADOW 0x8000 - -struct fsb_map_entry fsb_mapping_table[] = { - { 0, 8 }, - { 1, 8 }, - { 2, 8 }, - { 3, 8 }, - { 4, 8 }, - { 5, 8 }, - { 6, 4 }, - { -1, 260 }, - { 39, 8 }, - { 40, 8 }, - { 41, 8 }, - { 42, 8 }, - { 43, 8 }, - { 44, 8 }, - { 45, 8 }, - { 46, 8 }, - { 47, 8 }, - { 48, 8 }, - { 49, 8 }, - { 50, 8 }, - { 51, 8 }, - { 52, 8 }, - { 53, 8 }, - { 54, 8 }, - { 55, 8 }, - { 56, 8 }, - { 57, 8 }, - { 58, 8 }, - { 59, 8 }, - { 60, 8 }, - { 61, 8 }, - { 62, 8 }, - { 63, 8 }, -}; - -struct s400_map_entry s400_api_mapping_table[] = { - { 7, 1, 7, 63 }, - { 16, 8, }, - { 17, 8, }, - { 22, 1, 6 }, - { 23, 1, 4 }, -}; -#endif - -static s32 map_fsb_fuse_index(u32 bank, u32 word, bool *redundancy) -{ - s32 size = ARRAY_SIZE(fsb_mapping_table); - s32 i, word_pos = 0; - - /* map the fuse from ocotp fuse map to FSB*/ - for (i = 0; i < size; i++) { - if (fsb_mapping_table[i].fuse_bank != -1 && - fsb_mapping_table[i].fuse_bank == bank && - fsb_mapping_table[i].fuse_words > word) { - break; - } - - word_pos += fsb_mapping_table[i].fuse_words; - } - - if (i == size) - return -1; /* Failed to find */ - - if (fsb_mapping_table[i].redundancy) { - *redundancy = true; - return (word >> 1) + word_pos; - } - - *redundancy = false; - return word + word_pos; -} - -static s32 map_s400_fuse_index(u32 bank, u32 word) -{ - s32 size = ARRAY_SIZE(s400_api_mapping_table); - s32 i; - - /* map the fuse from ocotp fuse map to FSB*/ - for (i = 0; i < size; i++) { - if (s400_api_mapping_table[i].fuse_bank != -1 && - s400_api_mapping_table[i].fuse_bank == bank) { - if (word >= s400_api_mapping_table[i].fuse_offset && - word < (s400_api_mapping_table[i].fuse_offset + - s400_api_mapping_table[i].fuse_words)) - break; - } - } - - if (i == size) - return -1; /* Failed to find */ - - if (s400_api_mapping_table[i].s400_index != 0) - return s400_api_mapping_table[i].s400_index; - - return s400_api_mapping_table[i].fuse_bank * 8 + word; -} - -#if defined(CONFIG_IMX8ULP) -int fuse_sense(u32 bank, u32 word, u32 *val) -{ - s32 word_index; - bool redundancy; - - if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val) - return -EINVAL; - - word_index = map_fsb_fuse_index(bank, word, &redundancy); - if (word_index >= 0) { - *val = readl((ulong)FSB_BASE_ADDR + FSB_OTP_SHADOW + (word_index << 2)); - if (redundancy) - *val = (*val >> ((word % 2) * 16)) & 0xFFFF; - - return 0; - } - - word_index = map_s400_fuse_index(bank, word); - if (word_index >= 0) { - u32 data[4]; - u32 res, size = 4; - int ret; - - /* Only UID return 4 words */ - if (word_index != 1) - size = 1; - - ret = ahab_read_common_fuse(word_index, data, size, &res); - if (ret) { - printf("ahab read fuse failed %d, 0x%x\n", ret, res); - return ret; - } - - if (word_index == 1) { - *val = data[word]; /* UID */ - } else if (word_index == 2) { - /* - * OTFAD 3 bits as follow: - * bit 0: OTFAD_ENABLE - * bit 1: OTFAD_DISABLE_OVERRIDE - * bit 2: KEY_BLOB_EN - */ - *val = data[0] << 3; - } else { - *val = data[0]; - } - - return 0; - } - - return -ENOENT; -} -#elif defined(CONFIG_ARCH_IMX9) -int fuse_sense(u32 bank, u32 word, u32 *val) -{ - s32 word_index; - bool redundancy; - - if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val) - return -EINVAL; - - word_index = map_fsb_fuse_index(bank, word, &redundancy); - if (word_index >= 0) { - *val = readl((ulong)FSB_BASE_ADDR + FSB_OTP_SHADOW + (word_index << 2)); - if (redundancy) - *val = (*val >> ((word % 2) * 16)) & 0xFFFF; - - return 0; - } - - word_index = map_s400_fuse_index(bank, word); - if (word_index >= 0) { - u32 data; - u32 res, size = 1; - int ret; - - ret = ahab_read_common_fuse(word_index, &data, size, &res); - if (ret) { - printf("ahab read fuse failed %d, 0x%x\n", ret, res); - return ret; - } - - *val = data; - - return 0; - } - - return -ENOENT; -} -#endif - -int fuse_read(u32 bank, u32 word, u32 *val) -{ - return fuse_sense(bank, word, val); -} - -int fuse_prog(u32 bank, u32 word, u32 val) -{ - u32 res; - int ret; - bool lock = false; - - if (bank >= FUSE_BANKS || word >= WORDS_PER_BANKS || !val) - return -EINVAL; - - /* Lock 8ULP ECC fuse word, so second programming will return failure. - * iMX9 OTP can protect ECC fuse, so not need it - */ -#if defined(CONFIG_IMX8ULP) - u32 i; - for (i = 0; i < ARRAY_SIZE(nonecc_fuse_banks); i++) { - if (nonecc_fuse_banks[i] == bank) - break; - } - - if (i == ARRAY_SIZE(nonecc_fuse_banks)) - lock = true; -#endif - - ret = ahab_write_fuse((bank * 8 + word), val, lock, &res); - if (ret) { - printf("ahab write fuse failed %d, 0x%x\n", ret, res); - return ret; - } - - return 0; -} - -int fuse_override(u32 bank, u32 word, u32 val) -{ - printf("Override fuse to i.MX8ULP in u-boot is forbidden\n"); - return -EPERM; -} diff --git a/drivers/misc/sentinel/s400_api.c b/drivers/misc/sentinel/s400_api.c deleted file mode 100644 index 6c0d0b3f18a..00000000000 --- a/drivers/misc/sentinel/s400_api.c +++ /dev/null @@ -1,492 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2020 NXP - * - */ - -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -int ahab_release_rdc(u8 core_id, u8 xrdc, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 2; - msg.command = ELE_RELEASE_RDC_REQ; - switch (xrdc) { - case 0: - msg.data[0] = (0x74 << 8) | core_id; - break; - case 1: - msg.data[0] = (0x78 << 8) | core_id; - break; - case 2: - msg.data[0] = (0x82 << 8) | core_id; - break; - case 3: - msg.data[0] = (0x86 << 8) | core_id; - break; - default: - printf("Error: wrong xrdc index %u\n", xrdc); - return -EINVAL; - } - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, core id %u, response 0x%x\n", - __func__, ret, core_id, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_auth_oem_ctnr(ulong ctnr_addr, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 3; - msg.command = ELE_OEM_CNTN_AUTH_REQ; - msg.data[0] = upper_32_bits(ctnr_addr); - msg.data[1] = lower_32_bits(ctnr_addr); - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, cntr_addr 0x%lx, response 0x%x\n", - __func__, ret, ctnr_addr, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_release_container(u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 1; - msg.command = ELE_RELEASE_CONTAINER_REQ; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_verify_image(u32 img_id, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 2; - msg.command = ELE_VERIFY_IMAGE_REQ; - msg.data[0] = 1 << img_id; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, img_id %u, response 0x%x\n", - __func__, ret, img_id, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_forward_lifecycle(u16 life_cycle, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 2; - msg.command = ELE_FWD_LIFECYCLE_UP_REQ; - msg.data[0] = life_cycle; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, life_cycle 0x%x, response 0x%x\n", - __func__, ret, life_cycle, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - if (!fuse_words) { - printf("Invalid parameters for fuse read\n"); - return -EINVAL; - } - - if ((fuse_id != 1 && fuse_num != 1) || - (fuse_id == 1 && fuse_num != 4)) { - printf("Invalid fuse number parameter\n"); - return -EINVAL; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 2; - msg.command = ELE_READ_FUSE_REQ; - msg.data[0] = fuse_id; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n", - __func__, ret, fuse_id, msg.data[0]); - - if (response) - *response = msg.data[0]; - - fuse_words[0] = msg.data[1]; - if (fuse_id == 1) { - /* OTP_UNIQ_ID */ - fuse_words[1] = msg.data[2]; - fuse_words[2] = msg.data[3]; - fuse_words[3] = msg.data[4]; - } - - return ret; -} - -int ahab_write_fuse(u16 fuse_id, u32 fuse_val, bool lock, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 3; - msg.command = ELE_WRITE_FUSE_REQ; - msg.data[0] = (32 << 16) | (fuse_id << 5); - if (lock) - msg.data[0] |= (1 << 31); - - msg.data[1] = fuse_val; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n", - __func__, ret, fuse_id, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_release_caam(u32 core_did, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 2; - msg.command = ELE_RELEASE_CAAM_REQ; - msg.data[0] = core_did; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - if (!fw_version) { - printf("Invalid parameters for f/w version read\n"); - return -EINVAL; - } - - if (!sha1) { - printf("Invalid parameters for commit sha1\n"); - return -EINVAL; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 1; - msg.command = ELE_GET_FW_VERSION_REQ; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - if (response) - *response = msg.data[0]; - - *fw_version = msg.data[1]; - *sha1 = msg.data[2]; - - return ret; -} - -int ahab_dump_buffer(u32 *buffer, u32 buffer_length) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret, i = 0; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 1; - msg.command = ELE_DUMP_DEBUG_BUFFER_REQ; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) { - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - return ret; - } - - if (buffer) { - buffer[i++] = *(u32 *)&msg; /* Need dump the response header */ - for (; i < buffer_length && i < msg.size; i++) - buffer[i] = msg.data[i - 1]; - } - - return i; -} - -int ahab_get_info(struct sentinel_get_info_data *info, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 4; - msg.command = ELE_GET_INFO_REQ; - msg.data[0] = upper_32_bits((ulong)info); - msg.data[1] = lower_32_bits((ulong)info); - msg.data[2] = sizeof(struct sentinel_get_info_data); - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - if (response) - *response = msg.data[0]; - - return ret; -} - -int ahab_get_fw_status(u32 *status, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 1; - msg.command = ELE_GET_FW_STATUS_REQ; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - if (response) - *response = msg.data[0]; - - *status = msg.data[1] & 0xF; - - return ret; -} - -int ahab_release_m33_trout(void) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 1; - msg.command = ELE_ENABLE_RTC_REQ; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - return ret; -} - -int ahab_get_events(u32 *events, u32 *events_cnt, u32 *response) -{ - struct udevice *dev = gd->arch.s400_dev; - int size = sizeof(struct sentinel_msg); - struct sentinel_msg msg; - int ret, i = 0; - u32 actual_events; - - if (!dev) { - printf("s400 dev is not initialized\n"); - return -ENODEV; - } - - if (!events || !events_cnt || *events_cnt == 0) { - printf("Invalid parameters for %s\n", __func__); - return -EINVAL; - } - - msg.version = AHAB_VERSION; - msg.tag = AHAB_CMD_TAG; - msg.size = 1; - msg.command = ELE_GET_EVENTS_REQ; - - ret = misc_call(dev, false, &msg, size, &msg, size); - if (ret) - printf("Error: %s: ret %d, response 0x%x\n", - __func__, ret, msg.data[0]); - - if (response) - *response = msg.data[0]; - - if (!ret) { - actual_events = msg.data[1] & 0xffff; - if (*events_cnt < actual_events) - actual_events = *events_cnt; - - for (; i < actual_events; i++) - events[i] = msg.data[i + 2]; - - *events_cnt = actual_events; - } - - return ret; -} diff --git a/drivers/misc/sentinel/s4mu.c b/drivers/misc/sentinel/s4mu.c deleted file mode 100644 index 794fc40c620..00000000000 --- a/drivers/misc/sentinel/s4mu.c +++ /dev/null @@ -1,235 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2020-2022 NXP - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -struct imx8ulp_mu { - struct mu_type *base; -}; - -#define MU_SR_TE0_MASK BIT(0) -#define MU_SR_RF0_MASK BIT(0) -#define MU_TR_COUNT 4 -#define MU_RR_COUNT 4 - -void mu_hal_init(ulong base) -{ - struct mu_type *mu_base = (struct mu_type *)base; - - writel(0, &mu_base->tcr); - writel(0, &mu_base->rcr); -} - -int mu_hal_sendmsg(ulong base, u32 reg_index, u32 msg) -{ - struct mu_type *mu_base = (struct mu_type *)base; - u32 mask = MU_SR_TE0_MASK << reg_index; - u32 val; - int ret; - - assert(reg_index < MU_TR_COUNT); - - debug("sendmsg sr 0x%x\n", readl(&mu_base->sr)); - - /* Wait TX register to be empty. */ - ret = readl_poll_timeout(&mu_base->tsr, val, val & mask, 10000); - if (ret < 0) { - debug("%s timeout\n", __func__); - return -ETIMEDOUT; - } - - debug("tr[%d] 0x%x\n", reg_index, msg); - - writel(msg, &mu_base->tr[reg_index]); - - return 0; -} - -int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg) -{ - struct mu_type *mu_base = (struct mu_type *)base; - u32 mask = MU_SR_RF0_MASK << reg_index; - u32 val; - int ret; - - assert(reg_index < MU_TR_COUNT); - - debug("receivemsg sr 0x%x\n", readl(&mu_base->sr)); - - /* Wait RX register to be full. */ - ret = readl_poll_timeout(&mu_base->rsr, val, val & mask, 10000); - if (ret < 0) { - debug("%s timeout\n", __func__); - return -ETIMEDOUT; - } - - *msg = readl(&mu_base->rr[reg_index]); - - debug("rr[%d] 0x%x\n", reg_index, *msg); - - return 0; -} - -static int imx8ulp_mu_read(struct mu_type *base, void *data) -{ - struct sentinel_msg *msg = (struct sentinel_msg *)data; - int ret; - u8 count = 0; - - if (!msg) - return -EINVAL; - - /* Read first word */ - ret = mu_hal_receivemsg((ulong)base, 0, (u32 *)msg); - if (ret) - return ret; - count++; - - /* Check size */ - if (msg->size > S400_MAX_MSG) { - *((u32 *)msg) = 0; - return -EINVAL; - } - - /* Read remaining words */ - while (count < msg->size) { - ret = mu_hal_receivemsg((ulong)base, count % MU_RR_COUNT, - &msg->data[count - 1]); - if (ret) - return ret; - count++; - } - - return 0; -} - -static int imx8ulp_mu_write(struct mu_type *base, void *data) -{ - struct sentinel_msg *msg = (struct sentinel_msg *)data; - int ret; - u8 count = 0; - - if (!msg) - return -EINVAL; - - /* Check size */ - if (msg->size > S400_MAX_MSG) - return -EINVAL; - - /* Write first word */ - ret = mu_hal_sendmsg((ulong)base, 0, *((u32 *)msg)); - if (ret) - return ret; - count++; - - /* Write remaining words */ - while (count < msg->size) { - ret = mu_hal_sendmsg((ulong)base, count % MU_TR_COUNT, - msg->data[count - 1]); - if (ret) - return ret; - count++; - } - - return 0; -} - -/* - * Note the function prototype use msgid as the 2nd parameter, here - * we take it as no_resp. - */ -static int imx8ulp_mu_call(struct udevice *dev, int no_resp, void *tx_msg, - int tx_size, void *rx_msg, int rx_size) -{ - struct imx8ulp_mu *priv = dev_get_priv(dev); - u32 result; - int ret; - - /* Expect tx_msg, rx_msg are the same value */ - if (rx_msg && tx_msg != rx_msg) - printf("tx_msg %p, rx_msg %p\n", tx_msg, rx_msg); - - ret = imx8ulp_mu_write(priv->base, tx_msg); - if (ret) - return ret; - if (!no_resp) { - ret = imx8ulp_mu_read(priv->base, rx_msg); - if (ret) - return ret; - } - - result = ((struct sentinel_msg *)rx_msg)->data[0]; - if ((result & 0xff) == 0xd6) - return 0; - - return -EIO; -} - -static int imx8ulp_mu_probe(struct udevice *dev) -{ - struct imx8ulp_mu *priv = dev_get_priv(dev); - fdt_addr_t addr; - - debug("%s(dev=%p) (priv=%p)\n", __func__, dev, priv); - - addr = devfdt_get_addr(dev); - if (addr == FDT_ADDR_T_NONE) - return -EINVAL; - - priv->base = (struct mu_type *)addr; - - debug("mu base 0x%lx\n", (ulong)priv->base); - - /* U-Boot not enable interrupts, so need to enable RX interrupts */ - mu_hal_init((ulong)priv->base); - - gd->arch.s400_dev = dev; - - return 0; -} - -static int imx8ulp_mu_remove(struct udevice *dev) -{ - return 0; -} - -static int imx8ulp_mu_bind(struct udevice *dev) -{ - debug("%s(dev=%p)\n", __func__, dev); - - return 0; -} - -static struct misc_ops imx8ulp_mu_ops = { - .call = imx8ulp_mu_call, -}; - -static const struct udevice_id imx8ulp_mu_ids[] = { - { .compatible = "fsl,imx8ulp-mu" }, - { .compatible = "fsl,imx93-mu-s4" }, - { } -}; - -U_BOOT_DRIVER(imx8ulp_mu) = { - .name = "imx8ulp_mu", - .id = UCLASS_MISC, - .of_match = imx8ulp_mu_ids, - .probe = imx8ulp_mu_probe, - .bind = imx8ulp_mu_bind, - .remove = imx8ulp_mu_remove, - .ops = &imx8ulp_mu_ops, - .priv_auto = sizeof(struct imx8ulp_mu), -}; -- cgit v1.3.1 From 31e5ec23238b884109dbfde9390b7f7b3bba1520 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 15 Jun 2023 18:09:08 +0800 Subject: imx: ele_api: support program secure fuse and return lifecycle Add two ELE API: ele_return_lifecycle_update and ele_write_secure_fuse Add two cmd: ahab_return_lifecycle and ahab_sec_fuse_prog Signed-off-by: Peng Fan --- arch/arm/include/asm/mach-imx/ele_api.h | 2 + arch/arm/mach-imx/ele_ahab.c | 74 +++++++++++++++++++++++++++++++++ drivers/misc/imx_ele/ele_api.c | 64 +++++++++++++++++++++++++++- 3 files changed, 139 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/arch/arm/include/asm/mach-imx/ele_api.h b/arch/arm/include/asm/mach-imx/ele_api.h index 120da0854e4..477cfe73ab0 100644 --- a/arch/arm/include/asm/mach-imx/ele_api.h +++ b/arch/arm/include/asm/mach-imx/ele_api.h @@ -146,5 +146,7 @@ int ele_dump_buffer(u32 *buffer, u32 buffer_length); int ele_get_info(struct ele_get_info_data *info, u32 *response); int ele_get_fw_status(u32 *status, u32 *response); int ele_release_m33_trout(void); +int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response); +int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response); #endif diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 5f23486304c..785b0d6ec3c 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -563,6 +563,68 @@ static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc, char *const return 0; } +static int do_sec_fuse_prog(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr; + u32 header, response; + + if (argc < 2) + return CMD_RET_USAGE; + + addr = hextoul(argv[1], NULL); + header = *(u32 *)addr; + + if ((header & 0xff0000ff) != 0x89000000) { + printf("Wrong Signed message block format, header 0x%x\n", header); + return CMD_RET_FAILURE; + } + + header = (header & 0xffff00) >> 8; + + printf("Signed Message block at 0x%lx, size 0x%x\n", addr, header); + flush_dcache_range(addr, addr + header - 1); + + if (ele_write_secure_fuse(addr, &response)) { + printf("Program secure fuse failed, response 0x%x\n", response); + return CMD_RET_FAILURE; + } + + printf("Program secure fuse completed, response 0x%x\n", response); + + return CMD_RET_SUCCESS; +} + +static int do_ahab_return_lifecycle(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + ulong addr; + u32 header, response; + + if (argc < 2) + return CMD_RET_USAGE; + + addr = hextoul(argv[1], NULL); + header = *(u32 *)addr; + + if ((header & 0xff0000ff) != 0x89000000) { + printf("Wrong Signed message block format, header 0x%x\n", header); + return CMD_RET_FAILURE; + } + + header = (header & 0xffff00) >> 8; + + printf("Signed Message block at 0x%lx, size 0x%x\n", addr, header); + flush_dcache_range(addr, addr + header - 1); + + if (ele_return_lifecycle_update(addr, &response)) { + printf("Return lifecycle failed, response 0x%x\n", response); + return CMD_RET_FAILURE; + } + + printf("Return lifecycle completed, response 0x%x\n", response); + + return CMD_RET_SUCCESS; +} + U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate, "autenticate OS container via AHAB", "addr\n" @@ -583,3 +645,15 @@ U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status, "display AHAB lifecycle only", "" ); + +U_BOOT_CMD(ahab_sec_fuse_prog, CONFIG_SYS_MAXARGS, 1, do_sec_fuse_prog, + "Program secure fuse via signed message block", + "addr\n" + "addr - Signed message block for secure fuse\n" +); + +U_BOOT_CMD(ahab_return_lifecycle, CONFIG_SYS_MAXARGS, 1, do_ahab_return_lifecycle, + "Return lifecycle to OEM field return via signed message block", + "addr\n" + "addr - Return lifecycle message block signed by OEM SRK\n" +); diff --git a/drivers/misc/imx_ele/ele_api.c b/drivers/misc/imx_ele/ele_api.c index 56605714f44..0ca0a94f08c 100644 --- a/drivers/misc/imx_ele/ele_api.c +++ b/drivers/misc/imx_ele/ele_api.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2020 NXP + * Copyright 2020, 2023 NXP * */ @@ -490,3 +490,65 @@ int ele_get_events(u32 *events, u32 *events_cnt, u32 *response) return ret; } + +int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 3; + msg.command = ELE_WRITE_SECURE_FUSE_REQ; + + msg.data[0] = upper_32_bits(signed_msg_blk); + msg.data[1] = lower_32_bits(signed_msg_blk); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n", + __func__, ret, msg.data[0], msg.data[1]); + + if (response) + *response = msg.data[0]; + + return ret; +} + +int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 3; + msg.command = ELE_RET_LIFECYCLE_UP_REQ; + + msg.data[0] = upper_32_bits(signed_msg_blk); + msg.data[1] = lower_32_bits(signed_msg_blk); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x, failed fuse row index %u\n", + __func__, ret, msg.data[0], msg.data[1]); + + if (response) + *response = msg.data[0]; + + return ret; +} -- cgit v1.3.1 From d0e2a012a3832573a510b7323840d2d6f74dd0a7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 15 Jun 2023 18:09:09 +0800 Subject: imx: ele_api: add DEK Blob generation - Add crc computation. - Add ele_generate_dek_blob API for encrypted boot support. Signed-off-by: Clement Faure Signed-off-by: Peng Fan --- arch/arm/include/asm/mach-imx/ele_api.h | 2 +- drivers/misc/imx_ele/ele_api.c | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/arch/arm/include/asm/mach-imx/ele_api.h b/arch/arm/include/asm/mach-imx/ele_api.h index 477cfe73ab0..053a23f030b 100644 --- a/arch/arm/include/asm/mach-imx/ele_api.h +++ b/arch/arm/include/asm/mach-imx/ele_api.h @@ -142,11 +142,11 @@ int ele_read_common_fuse(u16 fuse_id, u32 *fuse_words, u32 fuse_num, u32 *respon int ele_release_caam(u32 core_did, u32 *response); int ele_get_fw_version(u32 *fw_version, u32 *sha1, u32 *response); int ele_get_events(u32 *events, u32 *events_cnt, u32 *response); +int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size); int ele_dump_buffer(u32 *buffer, u32 buffer_length); int ele_get_info(struct ele_get_info_data *info, u32 *response); int ele_get_fw_status(u32 *status, u32 *response); int ele_release_m33_trout(void); int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response); int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response); - #endif diff --git a/drivers/misc/imx_ele/ele_api.c b/drivers/misc/imx_ele/ele_api.c index 0ca0a94f08c..8a14cf6aa92 100644 --- a/drivers/misc/imx_ele/ele_api.c +++ b/drivers/misc/imx_ele/ele_api.c @@ -14,6 +14,18 @@ DECLARE_GLOBAL_DATA_PTR; +static u32 compute_crc(const struct ele_msg *msg) +{ + u32 crc = 0; + size_t i = 0; + u32 *data = (u32 *)msg; + + for (i = 0; i < (msg->size - 1); i++) + crc ^= data[i]; + + return crc; +} + int ele_release_rdc(u8 core_id, u8 xrdc, u32 *response) { struct udevice *dev = gd->arch.ele_dev; @@ -552,3 +564,35 @@ int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response) return ret; } + +int ele_generate_dek_blob(u32 key_id, u32 src_paddr, u32 dst_paddr, u32 max_output_size) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 8; + msg.command = ELE_GENERATE_DEK_BLOB; + msg.data[0] = key_id; + msg.data[1] = 0x0; + msg.data[2] = src_paddr; + msg.data[3] = 0x0; + msg.data[4] = dst_paddr; + msg.data[5] = max_output_size; + msg.data[6] = compute_crc(&msg); + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret 0x%x, response 0x%x\n", + __func__, ret, msg.data[0]); + + return ret; +} -- cgit v1.3.1 From 71a21425d278a07ba263109fff0cba09ff30a157 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Thu, 15 Jun 2023 18:09:12 +0800 Subject: imx: misc: ele_mu: Update MU TR registers count According to SRM, the Sentinel MU has 8 TR and 4 RR registers. All of them are used for ELE message. So update TR count to 8 and fix a typo in receive msg Reviewed-by: Peng Fan Signed-off-by: Ye Li Signed-off-by: Peng Fan --- drivers/misc/imx_ele/ele_mu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/imx_ele/ele_mu.c b/drivers/misc/imx_ele/ele_mu.c index 0d34b8c9010..956f8a1eb2f 100644 --- a/drivers/misc/imx_ele/ele_mu.c +++ b/drivers/misc/imx_ele/ele_mu.c @@ -22,7 +22,7 @@ struct imx8ulp_mu { #define MU_SR_TE0_MASK BIT(0) #define MU_SR_RF0_MASK BIT(0) -#define MU_TR_COUNT 4 +#define MU_TR_COUNT 8 #define MU_RR_COUNT 4 void mu_hal_init(ulong base) @@ -65,7 +65,7 @@ int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg) u32 val; int ret; - assert(reg_index < MU_TR_COUNT); + assert(reg_index < MU_RR_COUNT); debug("receivemsg sr 0x%x\n", readl(&mu_base->sr)); -- cgit v1.3.1 From 78b4cf75307f4704881b7b7501721f27f2691f9f Mon Sep 17 00:00:00 2001 From: Ye Li Date: Thu, 15 Jun 2023 18:09:13 +0800 Subject: imx: misc: ele_mu: Update ELE MU driver Extend the RX timeout value to 10s, because when authentication is failed the ELE needs long time (>2s for 28M image) to return the result. Print rx wait info per 1s. Also correct TX and RX status registers in debug. Signed-off-by: Ye Li Signed-off-by: Peng Fan --- drivers/misc/imx_ele/ele_mu.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/imx_ele/ele_mu.c b/drivers/misc/imx_ele/ele_mu.c index 956f8a1eb2f..053cdcf0fe0 100644 --- a/drivers/misc/imx_ele/ele_mu.c +++ b/drivers/misc/imx_ele/ele_mu.c @@ -42,7 +42,7 @@ int mu_hal_sendmsg(ulong base, u32 reg_index, u32 msg) assert(reg_index < MU_TR_COUNT); - debug("sendmsg sr 0x%x\n", readl(&mu_base->sr)); + debug("sendmsg tsr 0x%x\n", readl(&mu_base->tsr)); /* Wait TX register to be empty. */ ret = readl_poll_timeout(&mu_base->tsr, val, val & mask, 10000); @@ -64,14 +64,24 @@ int mu_hal_receivemsg(ulong base, u32 reg_index, u32 *msg) u32 mask = MU_SR_RF0_MASK << reg_index; u32 val; int ret; + u32 count = 10; assert(reg_index < MU_RR_COUNT); - debug("receivemsg sr 0x%x\n", readl(&mu_base->sr)); + debug("receivemsg rsr 0x%x\n", readl(&mu_base->rsr)); - /* Wait RX register to be full. */ - ret = readl_poll_timeout(&mu_base->rsr, val, val & mask, 10000); - if (ret < 0) { + do { + /* Wait RX register to be full. */ + ret = readl_poll_timeout(&mu_base->rsr, val, val & mask, 1000000); + if (ret < 0) { + count--; + printf("mu receive msg wait %us\n", 10 - count); + } else { + break; + } + } while (count > 0); + + if (count == 0) { debug("%s timeout\n", __func__); return -ETIMEDOUT; } -- cgit v1.3.1 From 1c3f5df2597b80d4dac635152fc5dd1a9c4150b9 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 15 Jun 2023 18:09:14 +0800 Subject: imx: imx8ulp: start the ELE RNG at boot On the imx8ulp A1 SoC, the ELE RNG needs to be manually started. Signed-off-by: Clement Faure Signed-off-by: Peng Fan --- arch/arm/include/asm/mach-imx/ele_api.h | 1 + board/freescale/imx8ulp_evk/spl.c | 10 ++++++++++ drivers/misc/imx_ele/ele_api.c | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+) (limited to 'drivers/misc') diff --git a/arch/arm/include/asm/mach-imx/ele_api.h b/arch/arm/include/asm/mach-imx/ele_api.h index 053a23f030b..cfd4ecebb62 100644 --- a/arch/arm/include/asm/mach-imx/ele_api.h +++ b/arch/arm/include/asm/mach-imx/ele_api.h @@ -149,4 +149,5 @@ int ele_get_fw_status(u32 *status, u32 *response); int ele_release_m33_trout(void); int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response); int ele_return_lifecycle_update(ulong signed_msg_blk, u32 *response); +int ele_start_rng(void); #endif diff --git a/board/freescale/imx8ulp_evk/spl.c b/board/freescale/imx8ulp_evk/spl.c index b7c6ff092b1..66d0f68cc62 100644 --- a/board/freescale/imx8ulp_evk/spl.c +++ b/board/freescale/imx8ulp_evk/spl.c @@ -123,6 +123,16 @@ void spl_board_init(void) ret = ele_release_caam(0x7, &res); if (ret) printf("ele release caam failed %d, 0x%x\n", ret, res); + + /* + * RNG start only available on the A1 soc revision. + * Check some JTAG register for the SoC revision. + */ + if (!is_soc_rev(CHIP_REV_1_0)) { + ret = ele_start_rng(); + if (ret) + printf("Fail to start RNG: %d\n", ret); + } } void board_init_f(ulong dummy) diff --git a/drivers/misc/imx_ele/ele_api.c b/drivers/misc/imx_ele/ele_api.c index 8a14cf6aa92..0c017734a49 100644 --- a/drivers/misc/imx_ele/ele_api.c +++ b/drivers/misc/imx_ele/ele_api.c @@ -503,6 +503,31 @@ int ele_get_events(u32 *events, u32 *events_cnt, u32 *response) return ret; } +int ele_start_rng(void) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 1; + msg.command = ELE_START_RNG; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, response 0x%x\n", + __func__, ret, msg.data[0]); + + return ret; +} + int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response) { struct udevice *dev = gd->arch.ele_dev; -- cgit v1.3.1