From bdeff7cd5639451a836bfeb07d8f052014698e58 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Mon, 21 Apr 2025 21:48:56 +0530 Subject: [PATCH] LF-13910: remove base driver for secure-enclave remove base driver for secure-enclave Signed-off-by: Pankaj Gupta Acked-by: Jason Liu --- drivers/firmware/imx/Kconfig | 32 - drivers/firmware/imx/Makefile | 4 - drivers/firmware/imx/ele_base_msg.c | 602 ------ drivers/firmware/imx/ele_common.c | 291 --- drivers/firmware/imx/ele_common.h | 40 - drivers/firmware/imx/ele_fw_api.c | 142 -- drivers/firmware/imx/ele_fw_api.h | 26 - drivers/firmware/imx/ele_trng.c | 47 - drivers/firmware/imx/se_fw.c | 2284 -------------------- drivers/firmware/imx/se_fw.h | 172 -- drivers/firmware/imx/seco.c | 142 -- drivers/firmware/imx/seco_mu.c | 1318 ----------- drivers/firmware/imx/v2x_base_msg.c | 70 - include/linux/firmware/imx/ele_base_msg.h | 102 - include/linux/firmware/imx/ele_mu_ioctl.h | 112 - include/linux/firmware/imx/se_fw_inc.h | 10 - include/linux/firmware/imx/seco_mu_ioctl.h | 63 - include/linux/firmware/imx/svc/seco.h | 29 +- include/linux/firmware/imx/v2x_base_msg.h | 20 - 19 files changed, 1 insertion(+), 5505 deletions(-) delete mode 100644 drivers/firmware/imx/ele_base_msg.c delete mode 100644 drivers/firmware/imx/ele_common.c delete mode 100644 drivers/firmware/imx/ele_common.h delete mode 100644 drivers/firmware/imx/ele_fw_api.c delete mode 100644 drivers/firmware/imx/ele_fw_api.h delete mode 100644 drivers/firmware/imx/ele_trng.c delete mode 100644 drivers/firmware/imx/se_fw.c delete mode 100644 drivers/firmware/imx/se_fw.h delete mode 100644 drivers/firmware/imx/seco_mu.c delete mode 100644 drivers/firmware/imx/v2x_base_msg.c delete mode 100644 include/linux/firmware/imx/ele_base_msg.h delete mode 100644 include/linux/firmware/imx/ele_mu_ioctl.h delete mode 100644 include/linux/firmware/imx/se_fw_inc.h delete mode 100644 include/linux/firmware/imx/seco_mu_ioctl.h delete mode 100644 include/linux/firmware/imx/v2x_base_msg.h diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig index afaa709d49a8..5249aabff22a 100644 --- a/drivers/firmware/imx/Kconfig +++ b/drivers/firmware/imx/Kconfig @@ -29,38 +29,6 @@ config IMX_SCU_PD help The System Controller Firmware (SCFW) based power domain driver. -config IMX_SECO_MU - tristate "i.MX Security Controller (SECO) support" - depends on IMX_MBOX - default y if IMX_SCU - - help - It is possible to use APIs exposed by the SECO like HSM and SHE using the - SAB protocol via the shared Messaging Unit. This driver exposes these - interfaces via a set of file descriptors allowing to configure shared - memory, send and receive messages. - -config IMX_SEC_ENCLAVE - tristate "i.MX Embedded Secure Enclave - EdgeLock Enclave Firmware driver." - depends on IMX_MBOX && ARCH_MXC && ARM64 - default m if ARCH_MXC - - help - It is possible to use APIs exposed by the iMX Secure Enclave HW IP called: - - EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93), - like base, HSM, V2X & SHE using the SAB protocol via the shared Messaging - Unit. This driver exposes these interfaces via a set of file descriptors - allowing to configure shared memory, send and receive messages. - -config IMX_ELE_TRNG - tristate "i.MX ELE True Random Number Generator" - default y - select CRYPTO_RNG - select HW_RANDOM - help - This driver provides kernel-side support for the Random Number generation, - through NXP hardware IP for secure-enclave called EdgeLock Enclave. - config IMX_ISPMU tristate "IMX ISP MU Protocol driver" depends on IMX_MBOX diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile index faad36bf57a7..fcb29da8220f 100644 --- a/drivers/firmware/imx/Makefile +++ b/drivers/firmware/imx/Makefile @@ -2,9 +2,5 @@ obj-$(CONFIG_IMX_DSP) += imx-dsp.o obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o seco.o obj-${CONFIG_IMX_SCMI_MISC_CONTROL} += sm-misc.o -obj-${CONFIG_IMX_SECO_MU} += seco_mu.o -sec_enclave-objs = se_fw.o ele_common.o ele_base_msg.o ele_fw_api.o v2x_base_msg.o -obj-${CONFIG_IMX_SEC_ENCLAVE} += sec_enclave.o -sec_enclave-${CONFIG_IMX_ELE_TRNG} += ele_trng.o obj-$(CONFIG_IMX_SCMI_BBM_CONTROL) += sm-bbm.o obj-$(CONFIG_IMX_ISPMU) += isp-mu.o diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c deleted file mode 100644 index c553cd16f99e..000000000000 --- a/drivers/firmware/imx/ele_base_msg.c +++ /dev/null @@ -1,602 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2021-2024 NXP - */ - -#include -#include - -#include -#include - -#include "ele_common.h" - -int ele_get_info(struct device *dev, phys_addr_t addr, u32 data_size) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_GET_INFO_REQ, - ELE_GET_INFO_REQ_MSG_SZ, - true); - if (ret) - goto exit; - - priv->tx_msg->data[0] = upper_32_bits(addr); - priv->tx_msg->data[1] = lower_32_bits(addr); - priv->tx_msg->data[2] = data_size; - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_GET_INFO_REQ, - ELE_GET_INFO_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_GET_INFO_REQ, status); - ret = -1; - } - -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - - return ret; -} - -int ele_get_v2x_fw_state(struct device *dev, uint32_t *state) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - struct mu_hdr *hdr; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - hdr = (struct mu_hdr *)&priv->tx_msg->header; - - ret = plat_fill_cmd_msg_hdr(priv, - hdr, - ELE_GET_STATE, ELE_GET_STATE_REQ_SZ, - true); - if (ret) { - pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); - goto exit; - } - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_GET_STATE, - ELE_GET_STATE_RSP_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_GET_STATE, status); - ret = -1; - } else { - *state = 0xFF & priv->rx_msg->data[1]; - } -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} - -int ele_write_fuse(struct device *dev, uint16_t fuse_id, u32 value, bool lock) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - unsigned int status, ind; - int ret; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_WRITE_FUSE, ELE_WRITE_FUSE_REQ_MSG_SZ, - true); - if (ret) { - pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); - goto exit; - } - - priv->tx_msg->data[0] = (32 << 16) | (fuse_id << 5); - if (lock) - priv->tx_msg->data[0] |= BIT(31); - priv->tx_msg->data[1] = value; - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_WRITE_FUSE, - ELE_WRITE_FUSE_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - ind = RES_IND(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Status=0x%x, Indicator=0x%x", - ELE_WRITE_FUSE, status, ind); - ret = -1; - } - -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} -EXPORT_SYMBOL_GPL(ele_write_fuse); - -int ele_ping(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_PING_REQ, ELE_PING_REQ_SZ, - true); - if (ret) { - pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); - goto exit; - } - - ret = imx_ele_msg_send_rcv(priv); - if (ret) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_PING_REQ, - ELE_PING_RSP_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_PING_REQ, status); - ret = -1; - } -exit: - imx_se_free_tx_rx_buf(priv); - - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} - -/* - * ele_get_trng_state() - prepare and send the command to read - * crypto lib and TRNG state - * TRNG state - * 0x1 TRNG is in program mode - * 0x2 TRNG is still generating entropy - * 0x3 TRNG entropy is valid and ready to be read - * 0x4 TRNG encounter an error while generating entropy - * - * CSAL state - * 0x0 Crypto Lib random context initialization is not done yet - * 0x1 Crypto Lib random context initialization is on-going - * 0x2 Crypto Lib random context initialization succeed - * 0x3 Crypto Lib random context initialization failed - * - * returns: csal and trng state. - * - */ -int ele_get_trng_state(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_GET_TRNG_STATE_REQ, - ELE_GET_TRNG_STATE_REQ_MSG_SZ, - true); - if (ret) { - pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); - goto exit; - } - - ret = imx_ele_msg_send_rcv(priv); - if (ret) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_GET_TRNG_STATE_REQ, - ELE_GET_TRNG_STATE_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_GET_TRNG_STATE_REQ, status); - ret = -1; - } else - ret = (priv->rx_msg->data[1] & CSAL_TRNG_STATE_MASK); - -exit: - imx_se_free_tx_rx_buf(priv); - - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} - -/* - * ele_start_rng() - prepare and send the command to start - * initialization of the ELE RNG context - * - * returns: 0 on success. - */ -int ele_start_rng(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_START_RNG_REQ, - ELE_START_RNG_REQ_MSG_SZ, - true); - if (ret) - goto exit; - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_START_RNG_REQ, - ELE_START_RNG_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_START_RNG_REQ, status); - ret = -1; - } - -exit: - imx_se_free_tx_rx_buf(priv); - - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} - -int ele_service_swap(struct device *dev, - phys_addr_t addr, - u32 addr_size, u16 flag) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_SERVICE_SWAP_REQ, - ELE_SERVICE_SWAP_REQ_MSG_SZ, - true); - if (ret) - goto exit; - - priv->tx_msg->data[0] = flag; - priv->tx_msg->data[1] = addr_size; - priv->tx_msg->data[2] = ELE_NONE_VAL; - priv->tx_msg->data[3] = lower_32_bits(addr); - priv->tx_msg->data[4] = plat_add_msg_crc((uint32_t *)&priv->tx_msg[0], - ELE_SERVICE_SWAP_REQ_MSG_SZ); - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_SERVICE_SWAP_REQ, - ELE_SERVICE_SWAP_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_SERVICE_SWAP_REQ, status); - ret = -1; - } else { - if (flag == ELE_IMEM_EXPORT) - ret = priv->rx_msg->data[1]; - else - ret = 0; - } -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - - return ret; -} - -int ele_fw_authenticate(struct device *dev, phys_addr_t addr) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - unsigned int status; - int ret; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_FW_AUTH_REQ, - ELE_FW_AUTH_REQ_SZ, - true); - if (ret) - goto exit; - - priv->tx_msg->data[0] = addr; - priv->tx_msg->data[1] = 0x0; - priv->tx_msg->data[2] = addr; - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_FW_AUTH_REQ, - ELE_FW_AUTH_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_FW_AUTH_REQ, status); - ret = -1; - } -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - - return ret; -} - -static int read_otp_uniq_id(struct ele_mu_priv *priv, u32 *value) -{ - int ret; - unsigned int status; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_READ_FUSE_REQ, - ELE_READ_FUSE_OTP_UNQ_ID_RSP_MSG_SZ, - true); - if (ret) - return ret; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(priv->dev, "Command Id[%d], Response Failure = 0x%x", - ELE_READ_FUSE_REQ, status); - ret = -1; - } else { - value[0] = priv->rx_msg->data[1]; - value[1] = priv->rx_msg->data[2]; - value[2] = priv->rx_msg->data[3]; - value[3] = priv->rx_msg->data[4]; - - ret = 0; - } - - return ret; -} - -static int read_fuse_word(struct ele_mu_priv *priv, u32 *value) -{ - int ret; - unsigned int status; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_READ_FUSE_REQ, - ELE_READ_FUSE_RSP_MSG_SZ, - true); - if (ret) - return ret; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(priv->dev, "Command Id[%d], Response Failure = 0x%x", - ELE_READ_FUSE_REQ, status); - ret = -1; - } else { - value[0] = priv->rx_msg->data[1]; - - ret = 0; - } - - return ret; -} - -/** - * read_common_fuse() - Brief description of function. - * @struct device *dev: Device to send the request to read fuses. - * @uint16_t fuse_id: Fuse identifier to read. - * @u32 *value: unsigned integer array to store the fused-values. - * - * Secure-enclave like EdgeLock Enclave, manages the fuse. This API - * requests FW to read the common fuses. FW sends the read value as - * response. - * - * Context: This function takes two mutex locks: one on the command - * and second on the message unit. - * such that multiple commands cannot be sent. - * for the device Describes whether the function can sleep, what locks it takes, - * releases, or expects to be held. It can extend over multiple - * lines. - * Return: Describe the return value of function_name. - * - * The return value description can also have multiple paragraphs, and should - * be placed at the end of the comment block. - */ -int read_common_fuse(struct device *dev, - uint16_t fuse_id, u32 *value) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_READ_FUSE_REQ, - ELE_READ_FUSE_REQ_MSG_SZ, - true); - if (ret) { - pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); - goto exit; - } - - priv->tx_msg->data[0] = fuse_id; - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - switch (fuse_id) { - case OTP_UNIQ_ID: - ret = read_otp_uniq_id(priv, value); - break; - default: - ret = read_fuse_word(priv, value); - break; - } - -exit: - imx_se_free_tx_rx_buf(priv); - - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} -EXPORT_SYMBOL_GPL(read_common_fuse); - - -int ele_voltage_change_req(struct device *dev, bool start) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - uint8_t cmd = start ? ELE_VOLT_CHANGE_START_REQ : ELE_VOLT_CHANGE_FINISH_REQ; - - if (start) - mutex_lock(&priv->mu_cmd_lock); - - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - cmd, - ELE_VOLT_CHANGE_REQ_MSG_SZ, - true); - if (ret) { - pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); - goto exit; - } - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - cmd, - ELE_VOLT_CHANGE_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_VOLT_CHANGE_START_REQ, status); - ret = -1; - } - -exit: - imx_se_free_tx_rx_buf(priv); - - if (!start || ret) - mutex_unlock(&priv->mu_cmd_lock); - return ret; -} -EXPORT_SYMBOL_GPL(ele_voltage_change_req); diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c deleted file mode 100644 index e5f65f46e301..000000000000 --- a/drivers/firmware/imx/ele_common.c +++ /dev/null @@ -1,291 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2023 NXP - */ - -#include -#include -#include - -#include "ele_common.h" -#include "se_fw.h" - -int imx_se_alloc_tx_rx_buf(struct ele_mu_priv *priv) -{ - int ret = 0; - - priv->tx_msg = devm_kzalloc(priv->dev, - sizeof(*priv->tx_msg), - GFP_KERNEL); - if (!priv->tx_msg) { - ret = -ENOMEM; - dev_err(priv->dev, "Fail allocate mem for tx_msg.\n"); - return ret; - } - - priv->rx_msg = devm_kzalloc(priv->dev, - sizeof(*priv->rx_msg), - GFP_KERNEL); - - if (!priv->rx_msg) { - ret = -ENOMEM; - dev_err(priv->dev, "Fail allocate mem for rx_msg.\n"); - return ret; - } - - return ret; -} - -void imx_se_free_tx_rx_buf(struct ele_mu_priv *priv) -{ - if (priv->tx_msg) - devm_kfree(priv->dev, priv->tx_msg); - - if (priv->rx_msg) - devm_kfree(priv->dev, priv->rx_msg); -} - -uint32_t plat_add_msg_crc(uint32_t *msg, uint32_t msg_len) -{ - uint32_t i; - uint32_t crc = 0; - uint32_t nb_words = msg_len / (uint32_t)sizeof(uint32_t); - - for (i = 0; i < nb_words - 1; i++) - crc ^= *(msg + i); - - return crc; -} - -int imx_ele_msg_send_rcv(struct ele_mu_priv *priv) -{ - unsigned int wait; - int err; - - mutex_lock(&priv->mu_lock); - - err = mbox_send_message(priv->tx_chan, priv->tx_msg); - if (err < 0) { - pr_err("Error: mbox_send_message failure.\n"); - mutex_unlock(&priv->mu_lock); - return err; - } - err = 0; - - mutex_unlock(&priv->mu_lock); - - wait = msecs_to_jiffies(1000); - if (!wait_for_completion_timeout(&priv->done, wait)) { - pr_err("Error: wait_for_completion timed out.\n"); - err = -ETIMEDOUT; - } - - - return err; -} - -/* Fill a command message header with a given command ID and length in bytes. */ -int plat_fill_cmd_msg_hdr(struct ele_mu_priv *priv, - struct mu_hdr *hdr, - uint8_t cmd, - uint32_t len, - bool is_base_api) -{ - hdr->tag = priv->cmd_tag; - hdr->ver = (is_base_api) ? priv->base_api_ver : priv->fw_api_ver; - hdr->command = cmd; - hdr->size = len >> 2; - - return 0; -} - -int validate_rsp_hdr(struct ele_mu_priv *priv, unsigned int header, - uint8_t msg_id, uint8_t sz, bool is_base_api) -{ - unsigned int tag, command, size, ver; - int ret = -EINVAL; - - tag = MSG_TAG(header); - command = MSG_COMMAND(header); - size = MSG_SIZE(header); - ver = MSG_VER(header); - - do { - if (tag != priv->rsp_tag) { - dev_err(priv->dev, - "MSG[0x%x] Hdr: Resp tag mismatch. (0x%x != 0x%x)", - msg_id, tag, priv->rsp_tag); - break; - } - - if (command != msg_id) { - dev_err(priv->dev, - "MSG Header: Cmd id mismatch. (0x%x != 0x%x)", - command, msg_id); - break; - } - - if (size != (sz >> 2)) { - dev_err(priv->dev, - "MSG[0x%x] Hdr: Cmd size mismatch. (0x%x != 0x%x)", - msg_id, size, (sz >> 2)); - break; - } - - if (is_base_api && (ver != priv->base_api_ver)) { - dev_err(priv->dev, - "MSG[0x%x] Hdr: Base API Vers mismatch. (0x%x != 0x%x)", - msg_id, ver, priv->base_api_ver); - break; - } else if (!is_base_api && ver != priv->fw_api_ver) { - dev_err(priv->dev, - "MSG[0x%x] Hdr: FW API Vers mismatch. (0x%x != 0x%x)", - msg_id, ver, priv->fw_api_ver); - break; - } - - ret = 0; - - } while (false); - - return ret; -} - -int ele_do_start_rng(struct device *dev) -{ - int ret; - int count = ELE_GET_TRNG_STATE_RETRY_COUNT; - - ret = ele_get_trng_state(dev); - if (ret < 0) { - dev_err(dev, "Failed to get trng state\n"); - return ret; - } else if (ret != ELE_TRNG_STATE_OK) { - /* call start rng */ - ret = ele_start_rng(dev); - if (ret) { - dev_err(dev, "Failed to start rng\n"); - return ret; - } - - /* poll get trng state API, ELE_GET_TRNG_STATE_RETRY_COUNT times - * or while trng state != 0x203 - */ - do { - msleep(10); - ret = ele_get_trng_state(dev); - if (ret < 0) { - dev_err(dev, "Failed to get trng state\n"); - return ret; - } - count--; - } while ((ret != ELE_TRNG_STATE_OK) && count); - if (ret != ELE_TRNG_STATE_OK) - return -EIO; - } - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -int save_imem(struct device *dev) -{ - int ret; - struct ele_mu_priv *priv = dev_get_drvdata(dev); - - /* EXPORT command will save encrypted IMEM to given address, - * so later in resume, IMEM can be restored from the given - * address. - * - * Size must be at least 64 kB. - */ - ret = ele_service_swap(dev, - priv->imem.phyaddr, - ELE_IMEM_SIZE, - ELE_IMEM_EXPORT); - if (ret < 0) - dev_err(dev, "Failed to export IMEM\n"); - else - dev_info(dev, - "Exported %d bytes of encrypted IMEM\n", - ret); - - return ret; -} - -int restore_imem(struct device *dev, - uint8_t *pool_name) -{ - int ret; - u32 imem_state; - u32 *get_info_buf = NULL; - phys_addr_t get_info_phyaddr = 0; - struct ele_mu_priv *priv = dev_get_drvdata(dev); - - get_info_phyaddr - = pool_name ? get_phy_buf_mem_pool(dev, - pool_name, - &get_info_buf, - DEVICE_GET_INFO_SZ) - : 0x0; - - if (!get_info_buf) { - dev_err(dev, "Unable to alloc sram from sram pool\n"); - return -ENOMEM; - } - - ret = ele_do_start_rng(dev); - if (ret) - goto exit; - - /* get info from ELE */ - ret = ele_get_info(dev, get_info_phyaddr, ELE_GET_INFO_READ_SZ); - if (ret) { - dev_err(dev, "Failed to get info from ELE.\n"); - goto exit; - } - - /* Get IMEM state, if 0xFE then import IMEM */ - imem_state = (get_info_buf[ELE_IMEM_STATE_WORD] - & ELE_IMEM_STATE_MASK) >> 16; - if (imem_state == ELE_IMEM_STATE_BAD) { - /* IMPORT command will restore IMEM from the given - * address, here size is the actual size returned by ELE - * during the export operation - */ - ret = ele_service_swap(dev, - priv->imem.phyaddr, - priv->imem.size, - ELE_IMEM_IMPORT); - if (ret) { - dev_err(dev, "Failed to import IMEM\n"); - goto exit; - } - } else - goto exit; - - /* After importing IMEM, check if IMEM state is equal to 0xCA - * to ensure IMEM is fully loaded and - * ELE functionality can be used. - */ - ret = ele_get_info(dev, get_info_phyaddr, ELE_GET_INFO_READ_SZ); - if (ret) { - dev_err(dev, "Failed to get info from ELE.\n"); - goto exit; - } - - imem_state = (get_info_buf[ELE_IMEM_STATE_WORD] - & ELE_IMEM_STATE_MASK) >> 16; - if (imem_state == ELE_IMEM_STATE_OK) - dev_info(dev, "Successfully restored IMEM\n"); - else - dev_err(dev, "Failed to restore IMEM\n"); - -exit: - if (pool_name && get_info_buf) - free_phybuf_mem_pool(dev, pool_name, - get_info_buf, DEVICE_GET_INFO_SZ); - - return ret; -} -#endif diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h deleted file mode 100644 index e1979b555b58..000000000000 --- a/drivers/firmware/imx/ele_common.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2023 NXP - */ - - -#ifndef __ELE_COMMON_H__ -#define __ELE_COMMON_H__ - -#include "se_fw.h" - -uint32_t plat_add_msg_crc(uint32_t *msg, uint32_t msg_len); -int imx_ele_msg_send_rcv(struct ele_mu_priv *priv); -void imx_se_free_tx_rx_buf(struct ele_mu_priv *priv); -int imx_se_alloc_tx_rx_buf(struct ele_mu_priv *priv); -int validate_rsp_hdr(struct ele_mu_priv *priv, unsigned int header, - uint8_t msg_id, uint8_t sz, bool is_base_api); -int plat_fill_cmd_msg_hdr(struct ele_mu_priv *priv, - struct mu_hdr *hdr, - uint8_t cmd, - uint32_t len, - bool is_base_api); -#ifdef CONFIG_IMX_ELE_TRNG -int ele_trng_init(struct device *dev); -#else -static inline int ele_trng_init(struct device *dev) -{ - return 0; -} -#endif - -int ele_do_start_rng(struct device *dev); - -#ifdef CONFIG_PM_SLEEP -int save_imem(struct device *dev); -int restore_imem(struct device *dev, - uint8_t *pool_name); -#endif - -#endif /*__ELE_COMMON_H__ */ diff --git a/drivers/firmware/imx/ele_fw_api.c b/drivers/firmware/imx/ele_fw_api.c deleted file mode 100644 index 44ff2083aa77..000000000000 --- a/drivers/firmware/imx/ele_fw_api.c +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright 2023-2024 NXP - */ - -#include - -#include "ele_common.h" -#include "ele_fw_api.h" - -struct ele_rng_msg { - u32 header; /* u8 Tag; u8 Command; u8 Size; u8 Ver; */ - u16 rsv; - u16 flags; - u32 data[2]; -}; - -int ele_init_fw(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - unsigned int status; - int ret; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - ELE_INIT_FW_REQ, ELE_INIT_FW_REQ_SZ, - false); - if (ret) - goto exit; - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_INIT_FW_REQ, - ELE_INIT_FW_RSP_SZ, - false); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_INIT_FW_REQ, status); - ret = -1; - } - -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - - return ret; -} - -/* - * ele_get_random() - prepare and send the command to proceed - * with a random number generation operation - * - * returns: size of the rondom number generated - */ -int ele_get_random(struct device *dev, - void *data, size_t len) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - struct ele_rng_msg *tx_msg; - unsigned int status; - dma_addr_t dst_dma; - u8 *buf; - int ret; - - /* As per RBG3(RS) construction mentioned in NIST SP800-90C, - * CTR_DRBG generates 128(full entropy) bits after reseeding - * the CTR_DRBG with 256 bits of entropy. so splitting the - * user rng request in multiple of 128 bits & enforce reseed - * for every iteration. - */ - len = ELE_RNG_MAX_SIZE; - buf = dmam_alloc_coherent(priv->dev, len, &dst_dma, GFP_KERNEL); - if (!buf) { - dev_err(priv->dev, "Failed to map destination buffer memory\n"); - return -ENOMEM; - } - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) { - ret = -ENOMEM; - goto exit; - } - - tx_msg = (struct ele_rng_msg *)priv->tx_msg; - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&tx_msg->header, - ELE_GET_RANDOM_REQ, ELE_GET_RANDOM_REQ_SZ, - false); - if (ret) - goto exit; - - /* bit 1(blocking reseed): wait for trng entropy, - * then reseed rng context. - */ - if (get_se_soc_id(dev) != SOC_ID_OF_IMX95) - tx_msg->flags = BIT(1); - - tx_msg->data[0] = dst_dma; - tx_msg->data[1] = len; - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - ELE_GET_RANDOM_REQ, - ELE_GET_RANDOM_RSP_SZ, - false); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - ELE_GET_RANDOM_REQ, status); - ret = -1; - } else { - memcpy(data, buf, len); - ret = len; - } - -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - dmam_free_coherent(priv->dev, len, buf, dst_dma); - - return ret; -} diff --git a/drivers/firmware/imx/ele_fw_api.h b/drivers/firmware/imx/ele_fw_api.h deleted file mode 100644 index e83604e004c8..000000000000 --- a/drivers/firmware/imx/ele_fw_api.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2023 NXP - */ - -#ifndef ELE_FW_API_H -#define ELE_FW_API_H - -#include - -#define MESSAGING_VERSION_7 0x7 - -#define ELE_INIT_FW_REQ 0x17 -#define ELE_INIT_FW_REQ_SZ 0x04 -#define ELE_INIT_FW_RSP_SZ 0x08 - -#define ELE_GET_RANDOM_REQ 0xCD -#define ELE_GET_RANDOM_REQ_SZ 0x10 -#define ELE_GET_RANDOM_RSP_SZ 0x08 -#define ELE_RNG_MAX_SIZE 16 - -int ele_init_fw(struct device *dev); -int ele_get_random(struct device *dev, void *data, size_t len); -int ele_get_hwrng(struct hwrng *rng, void *data, size_t len, bool wait); - -#endif /* ELE_FW_API_H */ diff --git a/drivers/firmware/imx/ele_trng.c b/drivers/firmware/imx/ele_trng.c deleted file mode 100644 index 4a7a119ff435..000000000000 --- a/drivers/firmware/imx/ele_trng.c +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * ELE Random Number Generator Driver NXP's Platforms - * - * Copyright 2023 NXP - */ - -#include "ele_common.h" -#include "ele_fw_api.h" - -struct ele_trng { - struct hwrng rng; - struct device *dev; -}; - -int ele_trng_init(struct device *dev) -{ - struct ele_trng *trng; - int ret; - - trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL); - if (!trng) - return -ENOMEM; - - trng->dev = dev; - trng->rng.name = "ele-trng"; - trng->rng.read = ele_get_hwrng; - trng->rng.priv = (unsigned long)trng; - trng->rng.quality = 1024; - - dev_dbg(dev, "registering ele-trng\n"); - - ret = devm_hwrng_register(dev, &trng->rng); - if (ret) - return ret; - - dev_info(dev, "Successfully registered ele-trng\n"); - return 0; -} - -int ele_get_hwrng(struct hwrng *rng, - void *data, size_t len, bool wait) -{ - struct ele_trng *trng = (struct ele_trng *)rng->priv; - - return ele_get_random(trng->dev, data, len); -} diff --git a/drivers/firmware/imx/se_fw.c b/drivers/firmware/imx/se_fw.c deleted file mode 100644 index ca98c94171ba..000000000000 --- a/drivers/firmware/imx/se_fw.c +++ /dev/null @@ -1,2284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2021-2024 NXP - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ele_common.h" -#include "ele_fw_api.h" -#include "se_fw.h" - -static uint32_t v2x_fw_state; - -#define SOC_ID_OF_IMX8ULP 0x084D -#define SOC_ID_OF_IMX93 0x9300 -#define SOC_ID_OF_IMX8DXL 0xE -#define SOC_ID_OF_IMX8QXP 0x2 -#define SOC_REV_A1 0xA100 -#define SOC_REV_B0 0xB000 -#define SOC_REV_C0 0xC000 -#define SOC_VER_MASK 0xFFFF0000 -#define SOC_ID_MASK 0x0000FFFF -#define RESERVED_DMA_POOL BIT(1) -#define SCU_MEM_CFG BIT(2) -#define SCU_SIGNED_MSG_CFG BIT(3) -#define IMX_ELE_FW_DIR "/lib/firmware/imx/ele/" -#define SECURE_RAM_BASE_ADDRESS_SCU (0x20800000u) -#define V2X_NON_FIPS 0x00000c00 -#define SECO_NON_FIPS 0x00000018 - -struct imx_info { - const uint8_t pdev_name[10]; - bool socdev; - uint8_t mu_id; - uint8_t mu_did; - uint8_t max_dev_ctx; - uint8_t cmd_tag; - uint8_t rsp_tag; - uint8_t success_tag; - uint8_t base_api_ver; - uint8_t fw_api_ver; - uint16_t abort_err_code; - uint8_t *se_name; - uint8_t *mbox_tx_name; - uint8_t *mbox_rx_name; - uint8_t *pool_name; - uint32_t mu_buff_size; - bool reserved_dma_ranges; - bool init_fw; - int (*pre_if_config)(struct device *dev); - int (*post_if_config)(struct device *dev); - /* platform specific flag to enable/disable the ELE True RNG */ - bool v2x_state_check; - int (*start_rng)(struct device *dev); - bool enable_ele_trng; - uint8_t *fw_name_in_rfs; - uint8_t *primary_fw_rfs; -}; - -struct imx_info_list { - uint8_t num_mu; - uint16_t soc_id; - uint16_t soc_rev; - uint8_t board_type; - struct imx_info info[]; -}; - -#define IMX8DXL_DL1 0x1 -#define IMX8DXL_DL2 0x2 -#define IMX8DXL_DL3 0x4 - -struct seco_soc_info { - u16 soc_id; - u16 soc_rev; - u8 board_type; -}; - -static LIST_HEAD(priv_data_list); - -static const struct imx_info_list imx8ulp_info = { - .num_mu = 1, - .soc_id = SOC_ID_OF_IMX8ULP, - .board_type = 0, - .info = { - { - .pdev_name = {"se-fw2"}, - .socdev = true, - .mu_id = 2, - .mu_did = 7, - .max_dev_ctx = 4, - .cmd_tag = 0x17, - .rsp_tag = 0xe1, - .success_tag = 0xd6, - .base_api_ver = MESSAGING_VERSION_6, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "hsm1", - .mbox_tx_name = "tx", - .mbox_rx_name = "rx", - .pool_name = "sram", - .reserved_dma_ranges = true, - .pre_if_config = false, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = ele_start_rng, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = IMX_ELE_FW_DIR\ - "mx8ulpa2ext-ahab-container.img", - .primary_fw_rfs = IMX_ELE_FW_DIR"mx8ulpa2-ahab-container.img", - }, - }, -}; - -static const struct imx_info_list imx93_info = { - .num_mu = 1, - .soc_id = SOC_ID_OF_IMX93, - .board_type = 0, - .info = { - { - .pdev_name = {"se-fw2"}, - .socdev = false, - .mu_id = 2, - .mu_did = 3, - .max_dev_ctx = 4, - .cmd_tag = 0x17, - .rsp_tag = 0xe1, - .success_tag = 0xd6, - .base_api_ver = MESSAGING_VERSION_6, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "hsm1", - .mbox_tx_name = "tx", - .mbox_rx_name = "rx", - .pool_name = NULL, - .reserved_dma_ranges = true, - .pre_if_config = false, - .post_if_config = ele_init_fw, - .v2x_state_check = false, - .start_rng = ele_start_rng, - .enable_ele_trng = true, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - }, -}; - -static const struct imx_info_list imx8dxl_info = { - .num_mu = 7, - .soc_id = SOC_ID_OF_IMX8DXL, - .board_type = 0, - .info = { - { - .pdev_name = {"seco-she"}, - .socdev = false, - .mu_id = 1, - .mu_did = 0, - .max_dev_ctx = 4, - .cmd_tag = 0x17, - .rsp_tag = 0xe1, - .success_tag = 0x00, - .base_api_ver = MESSAGING_VERSION_6, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "she1", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"se-fw2"}, - .socdev = false, - .mu_id = 2, - .mu_did = 0, - .max_dev_ctx = 2, - .cmd_tag = 0x17, - .rsp_tag = 0xe1, - .success_tag = 0x00, - .base_api_ver = MESSAGING_VERSION_6, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "hsm1", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-sv0"}, - .socdev = false, - .mu_id = 4, - .mu_did = 0, - .max_dev_ctx = 2, - .cmd_tag = 0x18, - .rsp_tag = 0xe2, - .success_tag = 0x00, - .base_api_ver = 0x02, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "v2x_sv0", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-sv1"}, - .socdev = false, - .mu_id = 5, - .mu_did = 0, - .max_dev_ctx = 2, - .cmd_tag = 0x19, - .rsp_tag = 0xe3, - .success_tag = 0x00, - .base_api_ver = 0x02, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "v2x_sv1", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-she"}, - .socdev = false, - .mu_id = 6, - .mu_did = 0, - .max_dev_ctx = 2, - .cmd_tag = 0x1a, - .rsp_tag = 0xe4, - .success_tag = 0x00, - .base_api_ver = 0x02, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "v2x_she", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 16, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-sg0"}, - .socdev = false, - .mu_id = 7, - .mu_did = 0, - .max_dev_ctx = 2, - .cmd_tag = 0x1d, - .rsp_tag = 0xe7, - .success_tag = 0x00, - .base_api_ver = 0x02, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "v2x_sg0", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-sg1"}, - .socdev = false, - .mu_id = 8, - .mu_did = 0, - .max_dev_ctx = 2, - .cmd_tag = 0x1e, - .rsp_tag = 0xe8, - .success_tag = 0x00, - .base_api_ver = 0x02, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "v2x_sg1", - .mbox_tx_name = "txdb", - .mbox_rx_name = "rxdb", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = imx_scu_init_fw, - .post_if_config = false, - .v2x_state_check = false, - .start_rng = false, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - }, -}; - -static const struct imx_info_list imx95_info = { - .num_mu = 4, - .soc_id = SOC_ID_OF_IMX95, - .board_type = 0, - .info = { - { - .pdev_name = {"se-fw2"}, - .socdev = false, - .mu_id = 2, - .mu_did = 3, - .max_dev_ctx = 4, - .cmd_tag = 0x17, - .rsp_tag = 0xe1, - .success_tag = 0xd6, - .base_api_ver = MESSAGING_VERSION_6, - .fw_api_ver = MESSAGING_VERSION_7, - .abort_err_code = 0xff29, - .se_name = "hsm1", - .mbox_tx_name = "tx", - .mbox_rx_name = "rx", - .pool_name = NULL, - .reserved_dma_ranges = false, - .pre_if_config = false, - .post_if_config = ele_init_fw, - .v2x_state_check = true, - .start_rng = ele_start_rng, - .enable_ele_trng = true, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-fw0"}, - .socdev = false, - .mu_id = 0, - .mu_did = 0, - .max_dev_ctx = 1, - .cmd_tag = 0x1a, - .rsp_tag = 0xe4, - .success_tag = 0xd6, - .base_api_ver = 0x2, - .fw_api_ver = 0x2, - .abort_err_code = 0xff29, - .se_name = "v2x_dbg", - .pool_name = NULL, - .mbox_tx_name = "tx", - .mbox_rx_name = "rx", - .reserved_dma_ranges = false, - .pre_if_config = false, - .post_if_config = false, - .v2x_state_check = true, - .start_rng = v2x_start_rng, - .enable_ele_trng = false, - .mu_buff_size = 0, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-fw4"}, - .socdev = false, - .mu_id = 4, - .mu_did = 0, - .max_dev_ctx = 4, - .cmd_tag = 0x18, - .rsp_tag = 0xe2, - .success_tag = 0xd6, - .base_api_ver = 0x2, - .fw_api_ver = 0x2, - .abort_err_code = 0xff29, - .se_name = "v2x_sv0", - .pool_name = NULL, - .mbox_tx_name = "tx", - .mbox_rx_name = "rx", - .reserved_dma_ranges = false, - .pre_if_config = false, - .post_if_config = false, - .v2x_state_check = true, - .start_rng = NULL, - .enable_ele_trng = false, - .mu_buff_size = 16, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - { - .pdev_name = {"v2x-fw6"}, - .socdev = false, - .mu_id = 6, - .mu_did = 0, - .max_dev_ctx = 4, - .cmd_tag = 0x1a, - .rsp_tag = 0xe4, - .success_tag = 0xd6, - .base_api_ver = 0x2, - .fw_api_ver = 0x2, - .abort_err_code = 0xff29, - .se_name = "v2x_she", - .pool_name = NULL, - .mbox_tx_name = "tx", - .mbox_rx_name = "rx", - .reserved_dma_ranges = false, - .pre_if_config = false, - .post_if_config = false, - .v2x_state_check = true, - .start_rng = NULL, - .enable_ele_trng = false, - .mu_buff_size = 256, - .fw_name_in_rfs = NULL, - .primary_fw_rfs = NULL, - }, - } -}; - -static const struct of_device_id se_fw_match[] = { - { .compatible = "fsl,imx8ulp-se-fw", .data = (void *)&imx8ulp_info}, - { .compatible = "fsl,imx93-se-fw", .data = (void *)&imx93_info}, - { .compatible = "fsl,imx95-se-fw", .data = (void *)&imx95_info}, - { .compatible = "fsl,imx8dxl-se-fw", .data = (void *)&imx8dxl_info}, - {}, -}; - -static const struct soc_device_attribute soc_info_matches[] = { - { .soc_id = "i.MX8DXL", - .revision = "1.1", - .data = &(struct seco_soc_info) {.soc_id = SOC_ID_OF_IMX8DXL, .soc_rev = SOC_REV_A1,} - }, - { .soc_id = "i.MX8DXL", - .revision = "1.2", - .data = &(struct seco_soc_info) {.soc_id = SOC_ID_OF_IMX8DXL, .soc_rev = SOC_REV_B0,} - }, - { .soc_id = "i.MX8QXP", - .revision = "1.1", - .data = &(struct seco_soc_info) {.soc_id = SOC_ID_OF_IMX8QXP, .soc_rev = SOC_REV_B0,} - }, - { .soc_id = "i.MX8QXP", - .revision = "1.2", - .data = &(struct seco_soc_info) {.soc_id = SOC_ID_OF_IMX8QXP, .soc_rev = SOC_REV_C0,} - }, -}; - -/* - * get_se_soc_id() - to fetch the soc_id of the platform - * - * @dev : reference to the device for se interface. - * - * This function returns the SoC ID. - * - * Context: Other module, requiring to access the secure services based on SoC Id. - * - * Return: SoC Id of the device. - */ -uint32_t get_se_soc_id(struct device *dev) -{ - struct imx_info_list *info_list - = (struct imx_info_list *) device_get_match_data(dev); - - return info_list->soc_id; -} - -static struct imx_info *get_imx_info(struct imx_info_list *info_list, - const uint8_t *pdev_name, - uint8_t len) -{ - int i = 0; - - for (i = 0; i < info_list->num_mu; i++) - if (!memcmp(info_list->info[i].pdev_name, pdev_name, len)) - return &info_list->info[i]; - - return NULL; -} - -/* - * Callback called by mailbox FW when data are received - */ -static void ele_mu_rx_callback(struct mbox_client *c, void *msg) -{ - struct device *dev = c->dev; - struct ele_mu_priv *priv = dev_get_drvdata(dev); - struct ele_mu_device_ctx *dev_ctx; - bool is_response = false; - int msg_size; - struct mu_hdr header; - const struct imx_info *info = priv->info; - - /* The function can be called with NULL msg */ - if (!msg) { - dev_err(dev, "Message is invalid\n"); - return; - } - - if ((((uint32_t *)msg)[1] & 0xFFFF) == priv->abort_err_code) - dev_err(priv->dev, - "Rx-Msg(0x%x): Fatal abort received by %s.\n", - ((uint32_t *)msg)[0], info->se_name); - - header.tag = ((u8 *)msg)[TAG_OFFSET]; - header.command = ((u8 *)msg)[CMD_OFFSET]; - header.size = ((u8 *)msg)[SZ_OFFSET]; - header.ver = ((u8 *)msg)[VER_OFFSET]; - - /* Incoming command: wake up the receiver if any. */ - if (header.tag == priv->cmd_tag) { - dev_dbg(dev, "Selecting cmd receiver\n"); - dev_ctx = priv->cmd_receiver_dev; - } else if (header.tag == priv->rsp_tag) { - if (priv->waiting_rsp_dev) { - /* Capture response timer for user space interaction */ - ktime_get_ts64(&priv->time_frame.t_end); - dev_dbg(dev, "Selecting rsp waiter\n"); - dev_ctx = priv->waiting_rsp_dev; - is_response = true; - } else { - /* - * Reading the EdgeLock Enclave response - * to the command, sent by other - * linux kernel services. - */ - spin_lock(&priv->lock); - if (priv->rx_msg) - memcpy(priv->rx_msg, msg, header.size << 2); - else - dev_err(dev, "No RX buffer to save response.\n"); - - complete(&priv->done); - spin_unlock(&priv->lock); - return; - } - } else { - dev_err(dev, "Failed to select a device for message: %.8x\n", - *((u32 *) &header)); - return; - } - - if (!dev_ctx) { - dev_err(dev, "No device context selected for message: %.8x\n", - *((u32 *)&header)); - return; - } - /* Init reception */ - msg_size = header.size; - if (msg_size > MAX_RECV_SIZE) { - dev_err(dev, "%s: Message is too big (%d > %d)", - dev_ctx->miscdev.name, - msg_size, - MAX_RECV_SIZE); - return; - } - - memcpy(dev_ctx->temp_resp, msg, msg_size << 2); - dev_ctx->temp_resp_size = msg_size; - - /* Allow user to read */ - dev_ctx->pending_hdr = dev_ctx->temp_resp[0]; - wake_up_interruptible(&dev_ctx->wq); - - if (is_response) - priv->waiting_rsp_dev = NULL; - -} - -phys_addr_t get_phy_buf_mem_pool(struct device *dev, - char *mem_pool_name, - u32 **buf, - uint32_t size) -{ - struct device_node *of_node = dev->of_node; - struct gen_pool *mem_pool = of_gen_pool_get(of_node, - mem_pool_name, 0); - if (!mem_pool) { - dev_err(dev, "Unable to get sram pool\n"); - return 0; - } - - *buf = (u32 *)gen_pool_alloc(mem_pool, size); - if (!buf) { - dev_err(dev, "Unable to alloc sram from sram pool\n"); - return 0; - } - - return gen_pool_virt_to_phys(mem_pool, (ulong)*buf); -} - -void free_phybuf_mem_pool(struct device *dev, - char *mem_pool_name, - u32 *buf, - uint32_t size) -{ - struct device_node *of_node = dev->of_node; - struct gen_pool *mem_pool = of_gen_pool_get(of_node, - mem_pool_name, 0); - - if (!mem_pool) - dev_err(dev, "%s failed: Unable to get sram pool.\n", __func__); - - gen_pool_free(mem_pool, (unsigned long)buf, size); -} - -static int read_fuse(struct ele_mu_priv *priv, u32 id, u32 *value, u8 mul) -{ - struct nvmem_device *nvmem; - u32 size_to_read = mul * sizeof(u32); - struct device_node *np; - int ret = 0; - - np = priv->dev->of_node; - if (!of_get_property(np, "nvmem", NULL)) - return 0; - - nvmem = devm_nvmem_device_get(priv->dev, NULL); - if (IS_ERR(nvmem)) { - ret = PTR_ERR(nvmem); - - if (ret != -EPROBE_DEFER) - dev_err(priv->dev, "Failed to retrieve nvmem node\n"); - - return ret; - } - - ret = nvmem_device_read(nvmem, id, size_to_read, value); - if (ret < 0) { - dev_err(priv->dev, "Failed to read fuse %d: %d\n", id, ret); - return ret; - } - - if (ret != size_to_read) { - dev_err(priv->dev, "Read only %d instead of %d\n", ret, - size_to_read); - return -ENOMEM; - } - - dev_dbg(priv->dev, "FUSE value 0x%x 0x%x 0x%x 0x%x\n", - value[0], value[1], - value[2], value[3]); - - devm_nvmem_device_put(priv->dev, nvmem); - - return 0; -} - -/* function to fetch SoC revision on the SECO platform */ -static int seco_fetch_soc_info(uint16_t *soc_id, uint16_t *soc_rev) -{ - const struct soc_device_attribute *imx_soc_match; - int err = 0; - - imx_soc_match = soc_device_match(soc_info_matches); - if (!soc_id || !soc_rev || !imx_soc_match || !imx_soc_match->data) { - err = -EINVAL; - goto exit; - } - - *soc_id = ((const struct seco_soc_info *)imx_soc_match->data)->soc_id; - *soc_rev = ((const struct seco_soc_info *)imx_soc_match->data)->soc_rev; -exit: - return err; -} - -static int imx_fetch_soc_info(struct ele_mu_priv *priv, - struct imx_info *info) -{ - struct soc_device_attribute *attr; - struct soc_device *sdev = NULL; - const struct of_device_id *of_id = of_match_device(se_fw_match, priv->dev); - struct imx_info_list *info_list; - phys_addr_t get_info_addr = 0; - u32 *get_info_data = NULL; - u8 major_ver, minor_ver; - int err = 0; - u32 fuse_val[4] = {0xFF}; - - info_list = (struct imx_info_list *)of_id->data; - - if (info_list->soc_id == SOC_ID_OF_IMX8DXL) { - if (!info_list->board_type) { - /* Read the fuse values to check fips compliant */ - err = read_fuse(priv, 8, (u32 *)&fuse_val, 4); - if (err) { - dev_err(priv->dev, "Fail to read FIPS fuse\n"); - return err; - } - - if (fuse_val[2] & SECO_NON_FIPS) - info_list->board_type = IMX8DXL_DL1; - else if (fuse_val[0] & V2X_NON_FIPS) - info_list->board_type = IMX8DXL_DL3; - else if (!fuse_val[0] && !fuse_val[2]) - info_list->board_type = IMX8DXL_DL2; - } - return err; - } - - if (info_list->soc_rev) - return err; - - if (info->pool_name) { - get_info_addr = get_phy_buf_mem_pool(priv->dev, - info->pool_name, - &get_info_data, - DEVICE_GET_INFO_SZ); - } else { - get_info_data = dmam_alloc_coherent(priv->dev, - DEVICE_GET_INFO_SZ, - &get_info_addr, - GFP_KERNEL); - } - if (!get_info_addr) { - dev_err(priv->dev, "Unable to alloc buffer for device info.\n"); - return -ENOMEM; - } - - attr = kzalloc(sizeof(*attr), GFP_KERNEL); - if (!attr) - return -ENOMEM; - - err = ele_get_info(priv->dev, get_info_addr, ELE_GET_INFO_READ_SZ); - if (err) { - attr->revision = kasprintf(GFP_KERNEL, "A0"); - } else { - major_ver = (get_info_data[GET_INFO_SOC_INFO_WORD_OFFSET] - & SOC_VER_MASK) >> 24; - minor_ver = ((get_info_data[GET_INFO_SOC_INFO_WORD_OFFSET] - & SOC_VER_MASK) >> 16) & 0xFF; - /* SoC revision need to be stored in the info list structure */ - info_list->soc_rev = (get_info_data[GET_INFO_SOC_INFO_WORD_OFFSET] - & SOC_VER_MASK) >> 16; - - if (minor_ver) - attr->revision = kasprintf(GFP_KERNEL, - "%x.%x", - major_ver, - minor_ver); - else - attr->revision = kasprintf(GFP_KERNEL, - "%x", - major_ver); - - switch (get_info_data[GET_INFO_SOC_INFO_WORD_OFFSET] - & SOC_ID_MASK) { - case SOC_ID_OF_IMX8ULP: - attr->soc_id = kasprintf(GFP_KERNEL, - "i.MX8ULP"); - priv->imem.state = (get_info_data[ELE_IMEM_STATE_WORD] - & ELE_IMEM_STATE_MASK) >> 16; - break; - case SOC_ID_OF_IMX93: - attr->soc_id = kasprintf(GFP_KERNEL, - "i.MX93"); - break; - case SOC_ID_OF_IMX95: - attr->soc_id = kasprintf(GFP_KERNEL, - "i.MX95"); - break; - } - } - - err = of_property_read_string(of_root, "model", - &attr->machine); - if (err) { - kfree(attr); - return -EINVAL; - } - attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX"); - - attr->serial_number - = kasprintf(GFP_KERNEL, "%016llX", - (u64)get_info_data[GET_INFO_SL_NUM_MSB_WORD_OFF] << 32 - | get_info_data[GET_INFO_SL_NUM_LSB_WORD_OFF]); - - if (info->pool_name) { - free_phybuf_mem_pool(priv->dev, info->pool_name, - get_info_data, DEVICE_GET_INFO_SZ); - } else { - dmam_free_coherent(priv->dev, - DEVICE_GET_INFO_SZ, - get_info_data, - get_info_addr); - } - - if (!info->socdev) - return 0; - - sdev = soc_device_register(attr); - if (IS_ERR(sdev)) { - kfree(attr->soc_id); - kfree(attr->serial_number); - kfree(attr->revision); - kfree(attr->family); - kfree(attr->machine); - kfree(attr); - return PTR_ERR(sdev); - } - - return 0; -} - -/* - * File operations for user-space - */ - -/* Write a message to the MU. */ -static ssize_t ele_mu_fops_write(struct file *fp, const char __user *buf, - size_t size, loff_t *ppos) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - struct ele_mu_priv *ele_mu_priv = dev_ctx->priv; - u32 nb_words = 0; - struct mu_hdr header; - int err; - - dev_dbg(ele_mu_priv->dev, - "%s: write from buf (%p)%zu, ppos=%lld\n", - dev_ctx->miscdev.name, - buf, size, ((ppos) ? *ppos : 0)); - - if (down_interruptible(&dev_ctx->fops_lock)) - return -EBUSY; - - if (dev_ctx->status != MU_OPENED) { - err = -EINVAL; - goto exit; - } - - if (size < ELE_MU_HDR_SZ) { - dev_err(ele_mu_priv->dev, - "%s: User buffer too small(%zu < %d)\n", - dev_ctx->miscdev.name, - size, ELE_MU_HDR_SZ); - err = -ENOSPC; - goto exit; - } - - if (size > MAX_MESSAGE_SIZE_BYTES) { - dev_err(ele_mu_priv->dev, - "%s: User buffer too big(%zu > %d)\n", - dev_ctx->miscdev.name, - size, - MAX_MESSAGE_SIZE_BYTES); - err = -ENOSPC; - goto exit; - } - - /* Copy data to buffer */ - if (copy_from_user(dev_ctx->temp_cmd, buf, size)) { - err = -EFAULT; - dev_err(ele_mu_priv->dev, - "%s: Fail copy message from user\n", - dev_ctx->miscdev.name); - goto exit; - } - - print_hex_dump_debug("from user ", DUMP_PREFIX_OFFSET, 4, 4, - dev_ctx->temp_cmd, size, false); - - header = *((struct mu_hdr *) (&dev_ctx->temp_cmd[0])); - - /* Check the message is valid according to tags */ - if (header.tag == ele_mu_priv->cmd_tag) { - /* - * Command-lock will be unlocked in ele_mu_fops_read - * when the response to this command, is read. - * - * This command lock is taken to serialize - * the command execution over an MU. - * - * A command execution considered completed, when the - * response to the command is received. - */ - mutex_lock(&ele_mu_priv->mu_cmd_lock); - ele_mu_priv->waiting_rsp_dev = dev_ctx; - } else if (header.tag == ele_mu_priv->rsp_tag) { - /* Check the device context can send the command */ - if (dev_ctx != ele_mu_priv->cmd_receiver_dev) { - dev_err(ele_mu_priv->dev, - "%s: Channel not configured to send resp to FW.", - dev_ctx->miscdev.name); - err = -EPERM; - goto exit; - } - } else { - dev_err(ele_mu_priv->dev, - "%s: The message does not have a valid TAG\n", - dev_ctx->miscdev.name); - err = -EINVAL; - goto exit; - } - - /* - * Check that the size passed as argument matches the size - * carried in the message. - */ - nb_words = header.size; - if (nb_words << 2 != size) { - err = -EINVAL; - dev_err(ele_mu_priv->dev, - "%s: User buffer too small\n", - dev_ctx->miscdev.name); - goto exit; - } - - mutex_lock(&ele_mu_priv->mu_lock); - - /* Send message */ - dev_dbg(ele_mu_priv->dev, - "%s: sending message\n", - dev_ctx->miscdev.name); - - /* Capture request timer here to not include time for mutex lock */ - if (header.tag == ele_mu_priv->cmd_tag) - ktime_get_ts64(&ele_mu_priv->time_frame.t_start); - - err = mbox_send_message(ele_mu_priv->tx_chan, dev_ctx->temp_cmd); - if (err < 0) { - dev_err(ele_mu_priv->dev, - "%s: Failed to send message\n", - dev_ctx->miscdev.name); - goto unlock; - } - - err = nb_words << 2; - -unlock: - mutex_unlock(&ele_mu_priv->mu_lock); - -exit: - if (err < 0) - mutex_unlock(&ele_mu_priv->mu_cmd_lock); - up(&dev_ctx->fops_lock); - return err; -} - -/* - * Read a message from the MU. - * Blocking until a message is available. - */ -static ssize_t ele_mu_fops_read(struct file *fp, char __user *buf, - size_t size, loff_t *ppos) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - struct ele_mu_priv *ele_mu_priv = dev_ctx->priv; - u32 data_size = 0, size_to_copy = 0; - struct ele_buf_desc *b_desc; - int err; - struct mu_hdr header = {0}; - - dev_dbg(ele_mu_priv->dev, - "%s: read to buf %p(%zu), ppos=%lld\n", - dev_ctx->miscdev.name, - buf, size, ((ppos) ? *ppos : 0)); - - if (down_interruptible(&dev_ctx->fops_lock)) - return -EBUSY; - - if (dev_ctx->status != MU_OPENED) { - err = -EINVAL; - goto exit; - } - - do { - err = wait_event_interruptible(dev_ctx->wq, dev_ctx->pending_hdr != 0); - if (err == -ERESTARTSYS) { - dev_dbg(dev_ctx->dev, - "%s: err[0x%x]:interrupted by CTRL + C.\n", - dev_ctx->miscdev.name, err); - if (dev_ctx->priv->waiting_rsp_dev) { - dev_ctx->priv->waiting_rsp_dev->signal_recvd = true; - continue; - } else { - dev_dbg(dev_ctx->dev, - "Command receiver Dev ctx %s, is getting killed.\n", - dev_ctx->priv->cmd_receiver_dev->miscdev.name); - err = -EINTR; - goto exit; - } - } else if (err) { - dev_err(dev_ctx->dev, - "%s: err[0x%x]: other than signal interruption.\n", - dev_ctx->miscdev.name, err); - goto exit; - } - } while (!dev_ctx->pending_hdr); - - dev_dbg(ele_mu_priv->dev, - "%s: %s %s\n", - dev_ctx->miscdev.name, - __func__, - "message received, start transmit to user"); - - /* - * Check that the size passed as argument is larger than - * the one carried in the message. - */ - data_size = dev_ctx->temp_resp_size << 2; - size_to_copy = data_size; - if (size_to_copy > size) { - dev_dbg(ele_mu_priv->dev, - "%s: User buffer too small (%zu < %d)\n", - dev_ctx->miscdev.name, - size, size_to_copy); - size_to_copy = size; - } - - /* - * We may need to copy the output data to user before - * delivering the completion message. - */ - while (!list_empty(&dev_ctx->pending_out)) { - b_desc = list_first_entry_or_null(&dev_ctx->pending_out, - struct ele_buf_desc, - link); - if (!b_desc) - continue; - - if (b_desc->usr_buf_ptr && b_desc->shared_buf_ptr) { - - dev_dbg(ele_mu_priv->dev, - "%s: Copy output data to user\n", - dev_ctx->miscdev.name); - if (copy_to_user(b_desc->usr_buf_ptr, - b_desc->shared_buf_ptr, - b_desc->size)) { - dev_err(ele_mu_priv->dev, - "%s: Failure copying output data to user.", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } - } - - /* - * Variable "mu_buff_offset" is set while dealing with MU's device memory. - * For device type memory, it is recommended to use memset_io. - */ - if (b_desc->shared_buf_ptr) { - if (dev_ctx->mu_buff_offset) - memset_io(b_desc->shared_buf_ptr, 0, b_desc->size); - else - memset(b_desc->shared_buf_ptr, 0, b_desc->size); - } - - __list_del_entry(&b_desc->link); - devm_kfree(dev_ctx->dev, b_desc); - } - - header = *((struct mu_hdr *) (&dev_ctx->temp_resp[0])); - - /* Copy data from the buffer */ - print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4, - dev_ctx->temp_resp, size_to_copy, false); - if (copy_to_user(buf, dev_ctx->temp_resp, size_to_copy)) { - dev_err(ele_mu_priv->dev, - "%s: Failed to copy to user\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } - - err = size_to_copy; - if (dev_ctx->priv->waiting_rsp_dev && - dev_ctx == dev_ctx->priv->waiting_rsp_dev && - dev_ctx->signal_recvd == true) { - dev_ctx->signal_recvd = false; - err = -EINTR; - } - - /* free memory allocated on the shared buffers. */ - dev_ctx->secure_mem.pos = 0; - dev_ctx->non_secure_mem.pos = 0; - - dev_ctx->pending_hdr = 0; - -exit: - /* - * Clean the used Shared Memory space, - * whether its Input Data copied from user buffers, or - * Data received from FW. - */ - while (!list_empty(&dev_ctx->pending_in) || - !list_empty(&dev_ctx->pending_out)) { - if (!list_empty(&dev_ctx->pending_in)) - b_desc = list_first_entry_or_null(&dev_ctx->pending_in, - struct ele_buf_desc, - link); - else - b_desc = list_first_entry_or_null(&dev_ctx->pending_out, - struct ele_buf_desc, - link); - - if (!b_desc) - continue; - - /* - * Variable "mu_buff_offset" is set while dealing with MU's device memory. - * For device type memory, it is recommended to use memset_io. - */ - if (b_desc->shared_buf_ptr) { - if (dev_ctx->mu_buff_offset) - memset_io(b_desc->shared_buf_ptr, 0, b_desc->size); - else - memset(b_desc->shared_buf_ptr, 0, b_desc->size); - } - - __list_del_entry(&b_desc->link); - devm_kfree(dev_ctx->dev, b_desc); - } - if (header.tag == ele_mu_priv->rsp_tag) - mutex_unlock(&ele_mu_priv->mu_cmd_lock); - - dev_ctx->mu_buff_offset = 0; - - up(&dev_ctx->fops_lock); - return err; -} - -/* Configure the shared memory according to user config */ -static int ele_mu_ioctl_shared_mem_cfg_handler(struct file *fp, - struct ele_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct ele_mu_ioctl_shared_mem_cfg cfg; - int err = -EINVAL; - - /* Check if not already configured. */ - if (dev_ctx->secure_mem.dma_addr != 0u) { - dev_err(dev_ctx->priv->dev, "Shared memory not configured\n"); - return err; - } - - err = (int)copy_from_user(&cfg, (u8 *)arg, sizeof(cfg)); - if (err) { - dev_err(dev_ctx->priv->dev, "Fail copy memory config\n"); - err = -EFAULT; - return err; - } - - dev_dbg(dev_ctx->priv->dev, "cfg offset: %u(%d)\n", cfg.base_offset, cfg.size); - - err = imx_scu_sec_mem_cfg(fp, cfg.base_offset, cfg.size); - if (err) { - dev_err(dev_ctx->priv->dev, "Failt to map memory\n"); - err = -ENOMEM; - return err; - } - - return err; -} - -static int ele_mu_ioctl_get_mu_info(struct ele_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - struct ele_mu_ioctl_get_mu_info info; - struct imx_info *imx_info = (struct imx_info *)priv->info; - int err = 0; - - info.ele_mu_id = imx_info->mu_id; - info.interrupt_idx = 0; - info.tz = 0; - info.did = imx_info->mu_did; - info.cmd_tag = imx_info->cmd_tag; - info.rsp_tag = imx_info->rsp_tag; - info.success_tag = imx_info->success_tag; - info.base_api_ver = imx_info->base_api_ver; - info.fw_api_ver = imx_info->fw_api_ver; - - dev_dbg(priv->dev, - "%s: info [mu_idx: %d, irq_idx: %d, tz: 0x%x, did: 0x%x]\n", - dev_ctx->miscdev.name, - info.ele_mu_id, info.interrupt_idx, info.tz, info.did); - - if (copy_to_user((u8 *)arg, &info, sizeof(info))) { - dev_err(dev_ctx->priv->dev, - "%s: Failed to copy mu info to user\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -static int ele_mu_ioctl_signed_msg_handler(struct file *fp, - struct ele_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct ele_mu_ioctl_signed_message msg; - int err; - - err = copy_from_user(&msg, (u8 *)arg, sizeof(msg)); - if (err) { - dev_err(dev_ctx->priv->dev, "Failed to copy from user: %d\n", err); - return -EFAULT; - } - - err = imx_scu_signed_msg(fp, msg.message, msg.msg_size, &msg.error_code); - if (err) { - dev_err(dev_ctx->priv->dev, - "Failed to send signed message: %d\n", - err); - return err; - } - - err = copy_to_user((u8 *)arg, &msg, sizeof(msg)); - if (err) { - dev_err(dev_ctx->priv->dev, "Failed to copy to user: %d\n", err); - return -EFAULT; - } - - return err; -} - -/* - * Copy a buffer of data to/from the user and return the address to use in - * messages - */ -static int ele_mu_ioctl_setup_iobuf_handler(struct ele_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct ele_buf_desc *b_desc; - struct ele_mu_ioctl_setup_iobuf io = {0}; - struct ele_shared_mem *shared_mem; - int err = 0; - u32 pos; - u8 *addr; - - struct ele_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - struct imx_info *imx_info = (struct imx_info *)priv->info; - - if (copy_from_user(&io, (u8 *)arg, sizeof(io))) { - dev_err(dev_ctx->priv->dev, - "%s: Failed copy iobuf config from user\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } - - /* Function call to retrieve MU Buffer address */ - if (io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X) { - addr = get_mu_buf(priv->tx_chan); - addr = addr + dev_ctx->mu_buff_offset; - dev_ctx->mu_buff_offset = dev_ctx->mu_buff_offset + io.length; - if (dev_ctx->mu_buff_offset > imx_info->mu_buff_size) { - err = -ENOMEM; - goto exit; - } - } - - dev_dbg(dev_ctx->priv->dev, - "%s: io [buf: %p(%d) flag: %x]\n", - dev_ctx->miscdev.name, - io.user_buf, io.length, io.flags); - - if (io.length == 0 || !io.user_buf) { - /* - * Accept NULL pointers since some buffers are optional - * in FW commands. In this case we should return 0 as - * pointer to be embedded into the message. - * Skip all data copy part of code below. - */ - io.ele_addr = 0; - goto copy; - } - - /* Select the shared memory to be used for this buffer. */ - if (!(io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X)) { - if ((io.flags & ELE_MU_IO_FLAGS_USE_SEC_MEM) && - (priv->flags & SCU_MEM_CFG)) { - /* App requires to use secure memory for this buffer.*/ - shared_mem = &dev_ctx->secure_mem; - } else { - /* No specific requirement for this buffer. */ - shared_mem = &dev_ctx->non_secure_mem; - } - } - - /* Check there is enough space in the shared memory. */ - if (!(io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X) && - (shared_mem->size < shared_mem->pos - || io.length >= shared_mem->size - shared_mem->pos)) { - dev_err(dev_ctx->priv->dev, - "%s: Not enough space in shared memory\n", - dev_ctx->miscdev.name); - err = -ENOMEM; - goto exit; - } - - if (!(io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X)) { - /* Allocate space in shared memory. 8 bytes aligned. */ - pos = shared_mem->pos; - shared_mem->pos += round_up(io.length, 8u); - io.ele_addr = (u64)shared_mem->dma_addr + pos; - } else { - io.ele_addr = (u64)addr; - } - - if (priv->flags & SCU_MEM_CFG) { - if ((io.flags & ELE_MU_IO_FLAGS_USE_SEC_MEM) && - !(io.flags & ELE_MU_IO_FLAGS_USE_SHORT_ADDR)) { - /*Add base address to get full address.#TODO: Add API*/ - io.ele_addr += SECURE_RAM_BASE_ADDRESS_SCU; - } - } - - if (!(io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X)) { - memset(shared_mem->ptr + pos, 0, io.length); - } - - if ((io.flags & ELE_MU_IO_FLAGS_IS_INPUT) || - (io.flags & ELE_MU_IO_FLAGS_IS_IN_OUT)) { - /* - * buffer is input: - * copy data from user space to this allocated buffer. - */ - if (io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X) { - err = (int)copy_from_user(addr, io.user_buf, io.length); - } else { - err = (int)copy_from_user(shared_mem->ptr + pos, io.user_buf, io.length); - } - - if (err) { - dev_err(dev_ctx->priv->dev, - "%s: Failed copy data to shared memory\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } - } - - b_desc = devm_kmalloc(dev_ctx->dev, sizeof(*b_desc), GFP_KERNEL); - if (!b_desc) { - err = -ENOMEM; - dev_err(dev_ctx->priv->dev, - "%s: Failed allocating mem for pending buffer\n", - dev_ctx->miscdev.name); - goto exit; - } - - if (io.flags & ELE_MU_IO_DATA_BUF_SHE_V2X) - b_desc->shared_buf_ptr = addr; - else - b_desc->shared_buf_ptr = shared_mem->ptr + pos; - b_desc->usr_buf_ptr = io.user_buf; - b_desc->size = io.length; - - if (io.flags & ELE_MU_IO_FLAGS_IS_INPUT) { - /* - * buffer is input: - * add an entry in the "pending input buffers" list so - * that copied data can be cleaned from shared memory - * later. - */ - list_add_tail(&b_desc->link, &dev_ctx->pending_in); - } else { - /* - * buffer is output: - * add an entry in the "pending out buffers" list so data - * can be copied to user space when receiving ELE - * response. - */ - list_add_tail(&b_desc->link, &dev_ctx->pending_out); - } - -copy: - /* Provide the EdgeLock Enclave address to user space only if success.*/ - if (copy_to_user((u8 *)arg, &io, sizeof(io))) { - dev_err(dev_ctx->priv->dev, - "%s: Failed to copy iobuff setup to user\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } -exit: - return err; -} - -/* IOCTL to provide SoC information */ -static int ele_mu_ioctl_get_soc_info_handler(struct ele_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - const struct of_device_id *of_id = of_match_device(se_fw_match, - dev_ctx->priv->dev); - struct imx_info_list *info_list; - struct ele_mu_ioctl_get_soc_info soc_info; - int err = -EINVAL; - - if (!of_id || !of_id->data) - goto exit; - - info_list = (struct imx_info_list *)of_id->data; - - if (info_list->soc_id == SOC_ID_OF_IMX8DXL) { - err = seco_fetch_soc_info(&soc_info.soc_id, &soc_info.soc_rev); - if (err) - dev_err(dev_ctx->priv->dev, - "%s: Failed[%d] to fetch SoC Info\n", - dev_ctx->miscdev.name, err); - - soc_info.board_type = info_list->board_type; - } else { - soc_info.soc_id = info_list->soc_id; - soc_info.soc_rev = info_list->soc_rev; - soc_info.board_type = info_list->board_type; - } - - err = (int)copy_to_user((u8 *)arg, (u8 *)(&soc_info), sizeof(soc_info)); - if (err) { - dev_err(dev_ctx->priv->dev, - "%s: Failed to copy soc info to user\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -/* IOCTL to provide request and response timestamps from FW for a crypto - * operation - */ -static int ele_mu_ioctl_get_time(struct ele_mu_device_ctx *dev_ctx, unsigned long arg) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - int err = -EINVAL; - struct ele_time_frame time_frame; - - if (!priv) { - err = -EINVAL; - goto exit; - } - - time_frame.t_start = priv->time_frame.t_start; - time_frame.t_end = priv->time_frame.t_end; - err = (int)copy_to_user((u8 *)arg, (u8 *)(&time_frame), sizeof(time_frame)); - if (err) { - dev_err(dev_ctx->priv->dev, - "%s: Failed to copy timer to user\n", - dev_ctx->miscdev.name); - err = -EFAULT; - goto exit; - } -exit: - return err; -} - -/* Open a char device. */ -static int ele_mu_fops_open(struct inode *nd, struct file *fp) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - struct ele_mu_priv *priv = dev_ctx->priv; - int err = 0; - - /* Avoid race if opened at the same time */ - if (down_trylock(&dev_ctx->fops_lock)) - return -EBUSY; - - /* Authorize only 1 instance. */ - if (dev_ctx->status != MU_FREE) { - err = -EBUSY; - goto exit; - } - - /* - * Allocate some memory for data exchanges with S40x. - * This will be used for data not requiring secure memory. - */ - dev_ctx->non_secure_mem.ptr = dmam_alloc_coherent(dev_ctx->dev, - MAX_DATA_SIZE_PER_USER, - &dev_ctx->non_secure_mem.dma_addr, - GFP_KERNEL); - if (!dev_ctx->non_secure_mem.ptr) { - err = -ENOMEM; - dev_err(dev_ctx->priv->dev, - "%s: Failed to map shared memory with FW.\n", - dev_ctx->miscdev.name); - goto exit; - } - - if (priv->flags & SCU_MEM_CFG) { - err = imx_scu_mem_access(fp); - if (err) { - err = -EPERM; - dev_err(dev_ctx->priv->dev, - "%s: Failed to share access to shared memory\n", - dev_ctx->miscdev.name); - goto free_coherent; - } - } - - dev_ctx->non_secure_mem.size = MAX_DATA_SIZE_PER_USER; - dev_ctx->non_secure_mem.pos = 0; - dev_ctx->status = MU_OPENED; - - dev_ctx->pending_hdr = 0; - - goto exit; - -free_coherent: - dmam_free_coherent(dev_ctx->priv->dev, MAX_DATA_SIZE_PER_USER, - dev_ctx->non_secure_mem.ptr, - dev_ctx->non_secure_mem.dma_addr); - -exit: - up(&dev_ctx->fops_lock); - return err; -} - -/* Close a char device. */ -static int ele_mu_fops_close(struct inode *nd, struct file *fp) -{ - struct ele_mu_device_ctx *dev_ctx = container_of(fp->private_data, - struct ele_mu_device_ctx, miscdev); - struct ele_mu_priv *priv = dev_ctx->priv; - struct ele_buf_desc *b_desc; - - /* Avoid race if closed at the same time */ - if (down_trylock(&dev_ctx->fops_lock)) - return -EBUSY; - - /* The device context has not been opened */ - if (dev_ctx->status != MU_OPENED) - goto exit; - - /* check if this device was registered as command receiver. */ - if (priv->cmd_receiver_dev == dev_ctx) - priv->cmd_receiver_dev = NULL; - - /* check if this device was registered as waiting response. */ - if (priv->waiting_rsp_dev == dev_ctx) { - priv->waiting_rsp_dev = NULL; - mutex_unlock(&priv->mu_cmd_lock); - } - - /* Unmap secure memory shared buffer. */ - if (dev_ctx->secure_mem.ptr) - devm_iounmap(dev_ctx->dev, dev_ctx->secure_mem.ptr); - - dev_ctx->secure_mem.ptr = NULL; - dev_ctx->secure_mem.dma_addr = 0; - dev_ctx->secure_mem.size = 0; - dev_ctx->secure_mem.pos = 0; - - /* Free non-secure shared buffer. */ - dmam_free_coherent(dev_ctx->priv->dev, MAX_DATA_SIZE_PER_USER, - dev_ctx->non_secure_mem.ptr, - dev_ctx->non_secure_mem.dma_addr); - - dev_ctx->non_secure_mem.ptr = NULL; - dev_ctx->non_secure_mem.dma_addr = 0; - dev_ctx->non_secure_mem.size = 0; - dev_ctx->non_secure_mem.pos = 0; - - while (!list_empty(&dev_ctx->pending_in) || - !list_empty(&dev_ctx->pending_out)) { - if (!list_empty(&dev_ctx->pending_in)) - b_desc = list_first_entry_or_null(&dev_ctx->pending_in, - struct ele_buf_desc, - link); - else - b_desc = list_first_entry_or_null(&dev_ctx->pending_out, - struct ele_buf_desc, - link); - - if (!b_desc) - continue; - - /* - * Variable "mu_buff_offset" is set while dealing with MU's device memory. - * For device type memory, it is recommended to use memset_io. - */ - if (b_desc->shared_buf_ptr) { - if (dev_ctx->mu_buff_offset) - memset_io(b_desc->shared_buf_ptr, 0, b_desc->size); - else - memset(b_desc->shared_buf_ptr, 0, b_desc->size); - } - - __list_del_entry(&b_desc->link); - devm_kfree(dev_ctx->dev, b_desc); - } - - dev_ctx->status = MU_FREE; - -exit: - up(&dev_ctx->fops_lock); - return 0; -} - -/* IOCTL entry point of a char device */ -static long ele_mu_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - struct ele_mu_priv *ele_mu_priv = dev_ctx->priv; - int err = -EINVAL; - - /* Prevent race during change of device context */ - if (down_interruptible(&dev_ctx->fops_lock)) - return -EBUSY; - - switch (cmd) { - case ELE_MU_IOCTL_ENABLE_CMD_RCV: - if (!ele_mu_priv->cmd_receiver_dev) { - ele_mu_priv->cmd_receiver_dev = dev_ctx; - err = 0; - } - break; - case ELE_MU_IOCTL_SHARED_BUF_CFG: - if (ele_mu_priv->flags & SCU_MEM_CFG) - err = ele_mu_ioctl_shared_mem_cfg_handler(fp, dev_ctx, arg); - break; - case ELE_MU_IOCTL_GET_MU_INFO: - err = ele_mu_ioctl_get_mu_info(dev_ctx, arg); - break; - case ELE_MU_IOCTL_SETUP_IOBUF: - err = ele_mu_ioctl_setup_iobuf_handler(dev_ctx, arg); - break; - case ELE_MU_IOCTL_GET_SOC_INFO: - err = ele_mu_ioctl_get_soc_info_handler(dev_ctx, arg); - break; - case ELE_MU_IOCTL_GET_TIMER: - err = ele_mu_ioctl_get_time(dev_ctx, arg); - break; - case ELE_MU_IOCTL_SIGNED_MESSAGE: - if (ele_mu_priv->flags & SCU_SIGNED_MSG_CFG) - err = ele_mu_ioctl_signed_msg_handler(fp, dev_ctx, arg); - break; - default: - err = -EINVAL; - dev_dbg(ele_mu_priv->dev, - "%s: IOCTL %.8x not supported\n", - dev_ctx->miscdev.name, - cmd); - } - - up(&dev_ctx->fops_lock); - return (long)err; -} - -/* Char driver setup */ -static const struct file_operations ele_mu_fops = { - .open = ele_mu_fops_open, - .owner = THIS_MODULE, - .release = ele_mu_fops_close, - .unlocked_ioctl = ele_mu_ioctl, - .read = ele_mu_fops_read, - .write = ele_mu_fops_write, -}; - -/* interface for managed res to free a mailbox channel */ -static void if_mbox_free_channel(void *mbox_chan) -{ - mbox_free_channel(mbox_chan); -} - -/* interface for managed res to unregister a char device */ -static void if_misc_deregister(void *miscdevice) -{ - misc_deregister(miscdevice); -} - -static int ele_mu_request_channel(struct device *dev, - struct mbox_chan **chan, - struct mbox_client *cl, - const char *name) -{ - struct mbox_chan *t_chan; - int ret = 0; - - t_chan = mbox_request_channel_byname(cl, name); - if (IS_ERR(t_chan)) { - ret = PTR_ERR(t_chan); - if (ret != -EPROBE_DEFER) - dev_err(dev, - "Failed to request chan %s ret %d\n", name, - ret); - goto exit; - } - - ret = devm_add_action(dev, if_mbox_free_channel, t_chan); - if (ret) { - dev_err(dev, "failed to add devm removal of mbox %s\n", name); - goto exit; - } - - *chan = t_chan; - -exit: - return ret; -} - -static int se_probe_cleanup(struct platform_device *pdev) -{ - int ret = 0; - int i; - struct device *dev = &pdev->dev; - struct ele_mu_priv *priv; - - priv = dev_get_drvdata(dev); - - if (!priv) { - ret = -EINVAL; - dev_err(dev, "Invalid ELE-MU Priv data"); - return ret; - } - - if (priv->tx_chan) - mbox_free_channel(priv->tx_chan); - if (priv->rx_chan) - mbox_free_channel(priv->rx_chan); - - /* free the buffer in ele-mu remove, previously allocated - * in ele-mu probe to store encrypted IMEM - */ - if (priv->imem.buf) { - dmam_free_coherent(&pdev->dev, - ELE_IMEM_SIZE, - priv->imem.buf, - priv->imem.phyaddr); - priv->imem.buf = NULL; - } - - if (priv->ctxs) { - for (i = 0; i < priv->max_dev_ctx; i++) { - if (priv->ctxs[i]) { - devm_remove_action(dev, if_misc_deregister, - &priv->ctxs[i]->miscdev); - misc_deregister(&priv->ctxs[i]->miscdev); - devm_kfree(dev, priv->ctxs[i]); - } - } - devm_kfree(dev, priv->ctxs); - } - - __list_del_entry(&priv->priv_data); - - if (priv->flags & RESERVED_DMA_POOL) { - of_reserved_mem_device_release(dev); - priv->flags &= (~RESERVED_DMA_POOL); - } - - devm_kfree(dev, priv); - return ret; -} - -static int init_device_context(struct device *dev) -{ - int ret = 0; - int i; - struct ele_mu_device_ctx *dev_ctx; - struct ele_mu_priv *priv; - const struct imx_info *info; - char *devname; - - priv = dev_get_drvdata(dev); - - if (!priv) { - ret = -EINVAL; - dev_err(dev, "Invalid ELE-MU Priv data"); - return ret; - } - info = priv->info; - - priv->ctxs = devm_kzalloc(dev, sizeof(dev_ctx) * priv->max_dev_ctx, - GFP_KERNEL); - - if (!priv->ctxs) { - ret = -ENOMEM; - dev_err(dev, "Fail allocate mem for private dev-ctxs.\n"); - return ret; - } - - /* Create users */ - for (i = 0; i < priv->max_dev_ctx; i++) { - dev_ctx = devm_kzalloc(dev, sizeof(*dev_ctx), GFP_KERNEL); - if (!dev_ctx) { - ret = -ENOMEM; - dev_err(dev, - "Fail to allocate memory for device context\n"); - return ret; - } - - dev_ctx->dev = dev; - dev_ctx->status = MU_FREE; - dev_ctx->priv = priv; - - priv->ctxs[i] = dev_ctx; - - /* Default value invalid for an header. */ - init_waitqueue_head(&dev_ctx->wq); - - INIT_LIST_HEAD(&dev_ctx->pending_out); - INIT_LIST_HEAD(&dev_ctx->pending_in); - sema_init(&dev_ctx->fops_lock, 1); - - devname = devm_kasprintf(dev, GFP_KERNEL, "%s_ch%d", - info->se_name, - i); - if (!devname) { - ret = -ENOMEM; - dev_err(dev, - "Fail to allocate memory for misc dev name\n"); - return ret; - } - - dev_ctx->miscdev.name = devname; - dev_ctx->miscdev.minor = MISC_DYNAMIC_MINOR; - dev_ctx->miscdev.fops = &ele_mu_fops; - dev_ctx->miscdev.parent = dev; - ret = misc_register(&dev_ctx->miscdev); - if (ret) { - dev_err(dev, "failed to register misc device %d\n", - ret); - return ret; - } - - ret = devm_add_action(dev, if_misc_deregister, - &dev_ctx->miscdev); - if (ret) { - dev_err(dev, - "failed[%d] to add action to the misc-dev\n", - ret); - return ret; - } - } - - return ret; -} - -static void se_load_firmware(const struct firmware *fw, void *context) -{ - struct ele_mu_priv *priv = context; - const struct imx_info *info = priv->info; - phys_addr_t ele_fw_phyaddr; - u8 *se_fw_buf; - int ret; - - if (!fw) { - if (priv->fw_fail) - dev_dbg(priv->dev, - "External FW not found, using ROM FW.\n"); - else { - /*add a bit delay to wait for firmware priv released */ - msleep(20); - - /* Load firmware one more time if timeout */ - request_firmware_nowait(THIS_MODULE, - FW_ACTION_UEVENT, priv->se_img_file_to_load, - priv->dev, GFP_KERNEL, priv, - se_load_firmware); - priv->fw_fail++; - dev_dbg(priv->dev, "Value of retries = 0x%x\n", - priv->fw_fail); - } - - return; - } - - dev_info(priv->dev, "loading firmware %s\n", priv->se_img_file_to_load); - - /* allocate buffer to store the SE FW */ - se_fw_buf = dma_alloc_coherent(priv->dev, fw->size, - &ele_fw_phyaddr, GFP_KERNEL); - if (!se_fw_buf) - goto exit; - - memcpy(se_fw_buf, fw->data, fw->size); - ret = ele_fw_authenticate(priv->dev, ele_fw_phyaddr); - if (ret < 0) - dev_err(priv->dev, - "Error %pe: Authenticate & load SE firmware %s.\n", - ERR_PTR(ret), - priv->se_img_file_to_load); - - dma_free_coherent(priv->dev, - fw->size, - se_fw_buf, - ele_fw_phyaddr); - - if (priv->imem.state == ELE_IMEM_STATE_BAD && - priv->se_img_file_to_load == info->primary_fw_rfs) { - priv->se_img_file_to_load = info->fw_name_in_rfs; - request_firmware_nowait(THIS_MODULE, - FW_ACTION_UEVENT, priv->se_img_file_to_load, - priv->dev, GFP_KERNEL, priv, - se_load_firmware); - } - -exit: - release_firmware(fw); -} - - -static int se_fw_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct ele_mu_priv *priv; - const struct of_device_id *of_id = of_match_device(se_fw_match, dev); - struct imx_info *info = NULL; - int ret; - struct device_node *np; - struct imx_info_list *info_list; - - info = get_imx_info((struct imx_info_list *)of_id->data, - pdev->name, strlen(pdev->name) + 1); - - if (!info) { - dev_err(dev, "Cannot find matching dev-info. %s\n", - pdev->name); - ret = -1; - return ret; - } - - if (info->v2x_state_check) { - /* Check if it is the V2X MU, but V2X-FW is not - * loaded, then exit. - */ - if (v2x_fw_state != V2X_FW_STATE_RUNNING && - !memcmp(info->se_name, "v2x_dbg", 8)) { - ret = -1; - dev_err(dev, "Failure: V2X FW is not loaded."); - return ret; - } - } - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - dev_err(dev, "Fail allocate mem for private data\n"); - return ret; - } - priv->dev = dev; - priv->info = info; - memcpy(priv->pdev_name, pdev->name, strlen(pdev->name) + 1); - - dev_set_drvdata(dev, priv); - - list_add_tail(&priv->priv_data, &priv_data_list); - - /* - * Get the address of MU. - */ - np = pdev->dev.of_node; - if (!np) { - dev_err(dev, "Cannot find MU User entry in device tree\n"); - ret = -EOPNOTSUPP; - goto exit; - } - - info_list = (struct imx_info_list *)of_id->data; - - if (info->pre_if_config) { - /* start initializing ele fw */ - ret = info->pre_if_config(dev); - if (ret) { - dev_err(dev, "Failed to initialize scu config.\n"); - priv->flags &= (~SCU_MEM_CFG); - if ((info_list->soc_id == SOC_ID_OF_IMX8DXL) && - ((memcmp(info->se_name, "she1", 5)) || - (memcmp(info->se_name, "hsm1", 5)))) { - priv->flags &= (~SCU_SIGNED_MSG_CFG); - } - goto exit; - } - priv->flags |= SCU_MEM_CFG; - if ((info_list->soc_id == SOC_ID_OF_IMX8DXL) && - ((memcmp(info->se_name, "she1", 5)) || - (memcmp(info->se_name, "hsm1", 5)))) { - priv->flags |= SCU_SIGNED_MSG_CFG; - } - } - - /* Initialize the mutex. */ - mutex_init(&priv->mu_cmd_lock); - mutex_init(&priv->mu_lock); - - priv->cmd_receiver_dev = NULL; - priv->waiting_rsp_dev = NULL; - - /* Mailbox client configuration */ - priv->ele_mb_cl.dev = dev; - priv->ele_mb_cl.tx_block = false; - priv->ele_mb_cl.knows_txdone = true; - priv->ele_mb_cl.rx_callback = ele_mu_rx_callback; - - priv->max_dev_ctx = info->max_dev_ctx; - priv->cmd_tag = info->cmd_tag; - priv->rsp_tag = info->rsp_tag; - priv->success_tag = info->success_tag; - priv->base_api_ver = info->base_api_ver; - priv->fw_api_ver = info->fw_api_ver; - priv->abort_err_code = info->abort_err_code; - - ret = ele_mu_request_channel(dev, &priv->tx_chan, - &priv->ele_mb_cl, info->mbox_tx_name); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to request tx channel\n"); - - goto exit; - } - - ret = ele_mu_request_channel(dev, &priv->rx_chan, - &priv->ele_mb_cl, info->mbox_rx_name); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to request rx channel\n"); - - goto exit; - } - - init_completion(&priv->done); - spin_lock_init(&priv->lock); - - if (info->reserved_dma_ranges) { - ret = of_reserved_mem_device_init(dev); - if (ret) { - dev_err(dev, - "failed to init reserved memory region %d\n", - ret); - priv->flags &= (~RESERVED_DMA_POOL); - goto exit; - } - priv->flags |= RESERVED_DMA_POOL; - } - - if (info->post_if_config) { - /* start initializing ele fw */ - ret = info->post_if_config(dev); - if (ret) { - dev_err(dev, "Failed to initialize ele fw.\n"); - goto exit; - } - } - - ret = imx_fetch_soc_info(priv, info); - if (ret) { - dev_err(dev, - "failed[%d] to register SoC device\n", ret); - goto exit; - } - - /* Assumed v2x_state_check is enabled for i.MX95 only. */ - if (info->v2x_state_check) { - if (v2x_fw_state == V2X_FW_STATE_UNKNOWN && - !memcmp(info->se_name, "hsm1", 5)) { - ret = ele_get_v2x_fw_state(dev, &v2x_fw_state); - if (ret) - dev_err(dev, "Failed to start ele rng\n"); - } - - /* Check if it is the V2X MU, but V2X-FW is not - * loaded, then exit. - */ - if (v2x_fw_state != V2X_FW_STATE_RUNNING && - !memcmp(info->se_name, "v2x_she", 8)) { - ret = -1; - dev_err(dev, "Failure: V2X FW is not loaded."); - goto exit; - } - } - - /* start ele rng */ - if (info->start_rng) { - ret = info->start_rng(dev); - if (ret) - dev_err(dev, "Failed to start ele rng\n"); - } - - if (!ret && info->enable_ele_trng) { - ret = ele_trng_init(dev); - if (ret) - dev_err(dev, "Failed to init ele-trng\n"); - } - - priv->se_img_file_to_load = info->fw_name_in_rfs; - if (info->primary_fw_rfs) { - /* allocate buffer where SE store encrypted IMEM */ - priv->imem.buf = dmam_alloc_coherent(dev, ELE_IMEM_SIZE, - &priv->imem.phyaddr, - GFP_KERNEL); - if (!priv->imem.buf) { - dev_err(dev, - "dmam-alloc-failed: To store encr-IMEM.\n"); - ret = -ENOMEM; - goto exit; - } - if (priv->imem.state == ELE_IMEM_STATE_BAD) - priv->se_img_file_to_load = info->primary_fw_rfs; - } - - if (priv->se_img_file_to_load) { - ret = request_firmware_nowait(THIS_MODULE, - FW_ACTION_UEVENT, - priv->se_img_file_to_load, - dev, GFP_KERNEL, priv, - se_load_firmware); - if (ret) - dev_warn(dev, "Failed to get firmware [%s].\n", - priv->se_img_file_to_load); - ret = 0; - } - - if (info->max_dev_ctx) { - ret = init_device_context(dev); - if (ret) { - dev_err(dev, - "Failed to create device contexts.\n"); - ret = -ENOMEM; - goto exit; - } - } - - dev_info(dev, "i.MX secure-enclave: %s interface to firmware, configured.\n", - info->se_name); - - return devm_of_platform_populate(dev); - -exit: - /* if execution control reaches here, ele-mu probe fail. - * hence doing the cleanup - */ - if (se_probe_cleanup(pdev)) - dev_err(dev, "Failed clean-up.\n"); - - return ret; -} - -/** - * get_se_dev() - to fetch the refernce to the device, corresponding to an MU. - * @pdev_name: Physical device name of the secure-enclave pNode. - * - * This function returns the reference to the device, probed against an MU. - * Outside this driver or any kernel service requiring to access the secure - * services over an MU, needs the reference to the device. - * - * Context: Other module, requiring to access the secure services over an - * MU, needs the reference to the device. - * - * Return: Reference to the device. - */ -struct device *get_se_dev(const uint8_t *pdev_name) -{ - struct ele_mu_priv *priv; - - list_for_each_entry(priv, &priv_data_list, priv_data) { - if (!memcmp(priv->pdev_name, pdev_name, strlen(pdev_name) + 1)) - return priv->dev; - } - - return NULL; -} -EXPORT_SYMBOL_GPL(get_se_dev); - -static int se_fw_remove(struct platform_device *pdev) -{ - se_probe_cleanup(pdev); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int se_fw_suspend(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - const struct imx_info *info = priv->info; - - if (info && info->primary_fw_rfs) - priv->imem.size = save_imem(dev); - - return 0; -} - -static int se_fw_resume(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - const struct imx_info *info = priv->info; - int i; - - for (i = 0; i < priv->max_dev_ctx; i++) - wake_up_interruptible(&priv->ctxs[i]->wq); - - if (info && info->primary_fw_rfs) - restore_imem(dev, info->pool_name); - - return 0; -} -#endif - -static const struct dev_pm_ops se_fw_pm = { - SET_SYSTEM_SLEEP_PM_OPS(se_fw_suspend, se_fw_resume) -}; - -static struct platform_driver se_fw_driver = { - .driver = { - .name = "fsl-se-fw", - .of_match_table = se_fw_match, - .pm = &se_fw_pm, - }, - .probe = se_fw_probe, - .remove = se_fw_remove, -}; -MODULE_DEVICE_TABLE(of, se_fw_match); - -module_platform_driver(se_fw_driver); - -MODULE_AUTHOR("Pankaj Gupta "); -MODULE_DESCRIPTION("iMX Secure Enclave FW Driver."); -MODULE_LICENSE("GPL"); diff --git a/drivers/firmware/imx/se_fw.h b/drivers/firmware/imx/se_fw.h deleted file mode 100644 index 22721fab46d1..000000000000 --- a/drivers/firmware/imx/se_fw.h +++ /dev/null @@ -1,172 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2021-2024 NXP - */ - -#ifndef SE_MU_H -#define SE_MU_H - -#include -#include -#include - -#define MAX_MESSAGE_SIZE 31 -#define MAX_RECV_SIZE MAX_MESSAGE_SIZE -#define MAX_RECV_SIZE_BYTES (MAX_RECV_SIZE << 2) -#define MAX_MESSAGE_SIZE_BYTES (MAX_MESSAGE_SIZE << 2) - -#define ELE_MSG_DATA_NUM 10 - -#define MSG_TAG(x) (((x) & 0xff000000) >> 24) -#define MSG_COMMAND(x) (((x) & 0x00ff0000) >> 16) -#define MSG_SIZE(x) (((x) & 0x0000ff00) >> 8) -#define MSG_VER(x) ((x) & 0x000000ff) -#define RES_STATUS(x) ((x) & 0x000000ff) -#define RES_IND(x) (((x) & 0x0000ff00) >> 8) -#define MAX_DATA_SIZE_PER_USER (65 * 1024) -#define S4_DEFAULT_MUAP_INDEX (2) -#define S4_MUAP_DEFAULT_MAX_USERS (4) -#define MESSAGING_VERSION_6 0x6 -#define MESSAGING_VERSION_7 0x7 - -#define DEFAULT_MESSAGING_TAG_COMMAND (0x17u) -#define DEFAULT_MESSAGING_TAG_RESPONSE (0xe1u) - -#define ELE_MU_IO_FLAGS_USE_SEC_MEM (0x02u) -#define ELE_MU_IO_FLAGS_USE_SHORT_ADDR (0x04u) - -#define SOC_ID_OF_IMX95 0x9500 - -struct ele_imem_buf { - u8 *buf; - phys_addr_t phyaddr; - u32 size; - u32 state; -}; - -struct ele_buf_desc { - u8 *shared_buf_ptr; - u8 *usr_buf_ptr; - u32 size; - struct list_head link; -}; - -/* Status of a char device */ -enum mu_device_status_t { - MU_FREE, - MU_OPENED -}; - -struct ele_shared_mem { - dma_addr_t dma_addr; - u32 size; - u32 pos; - u8 *ptr; -}; - -/* Private struct for each char device instance. */ -struct ele_mu_device_ctx { - struct device *dev; - struct ele_mu_priv *priv; - struct miscdevice miscdev; - - enum mu_device_status_t status; - wait_queue_head_t wq; - struct semaphore fops_lock; - - bool signal_recvd; - u32 pending_hdr; - struct list_head pending_in; - struct list_head pending_out; - - struct ele_shared_mem secure_mem; - struct ele_shared_mem non_secure_mem; - u32 mu_buff_offset; - - u32 temp_cmd[MAX_MESSAGE_SIZE]; - u32 temp_resp[MAX_RECV_SIZE]; - u32 temp_resp_size; - struct notifier_block ele_notify; -}; - -/* Header of the messages exchange with the EdgeLock Enclave */ -struct mu_hdr { - u8 ver; - u8 size; - u8 command; - u8 tag; -} __packed; - -#define ELE_MU_HDR_SZ 4 -#define TAG_OFFSET (ELE_MU_HDR_SZ - 1) -#define CMD_OFFSET (ELE_MU_HDR_SZ - 2) -#define SZ_OFFSET (ELE_MU_HDR_SZ - 3) -#define VER_OFFSET (ELE_MU_HDR_SZ - 4) - -struct ele_api_msg { - u32 header; /* u8 Tag; u8 Command; u8 Size; u8 Ver; */ - u32 data[ELE_MSG_DATA_NUM]; -}; - -struct perf_time_frame { - struct timespec64 t_start; - struct timespec64 t_end; -}; - -struct ele_mu_priv { - struct list_head priv_data; - struct ele_mu_device_ctx *cmd_receiver_dev; - struct ele_mu_device_ctx *waiting_rsp_dev; - /* - * prevent parallel access to the MU registers - * e.g. a user trying to send a command while the other one is - * sending a response. - */ - struct mutex mu_lock; - /* - * prevent a command to be sent on the MU while another one is still - * processing. (response to a command is allowed) - */ - struct mutex mu_cmd_lock; - struct device *dev; - u8 ele_mu_did; - u8 pdev_name[20]; - u32 ele_mu_id; - u8 cmd_tag; - u8 rsp_tag; - u8 success_tag; - u8 base_api_ver; - u8 fw_api_ver; - uint16_t abort_err_code; - u32 fw_fail; - const void *info; - - struct mbox_client ele_mb_cl; - struct mbox_chan *tx_chan, *rx_chan; - struct ele_api_msg *tx_msg, *rx_msg; - struct completion done; - spinlock_t lock; - /* - * Flag to retain the state of initialization done at - * the time of ele-mu probe. - */ - uint32_t flags; - u8 max_dev_ctx; - struct ele_mu_device_ctx **ctxs; - struct ele_imem_buf imem; - struct perf_time_frame time_frame; - struct imx_sc_ipc *ipc_scu; - u8 part_owner; - u8 *se_img_file_to_load; -}; - -uint32_t get_se_soc_id(struct device *dev); -phys_addr_t get_phy_buf_mem_pool(struct device *dev, - char *mem_pool_name, - u32 **buf, - uint32_t size); -void free_phybuf_mem_pool(struct device *dev, - char *mem_pool_name, - u32 *buf, - uint32_t size); -#endif diff --git a/drivers/firmware/imx/seco.c b/drivers/firmware/imx/seco.c index 6441142e21cc..1f027833702a 100644 --- a/drivers/firmware/imx/seco.c +++ b/drivers/firmware/imx/seco.c @@ -8,7 +8,6 @@ #include #include -#include "se_fw.h" struct imx_sc_msg_seco_get_build_id { struct imx_sc_rpc_msg hdr; @@ -250,145 +249,4 @@ int imx_sc_seco_secvio_dgo_config(struct imx_sc_ipc *ipc, u8 id, u8 access, } EXPORT_SYMBOL(imx_sc_seco_secvio_dgo_config); -int imx_scu_init_fw(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - ret = imx_scu_get_handle(&priv->ipc_scu); - if (ret) { - dev_err(dev, "Fail to retrieve IPC handle\n"); - return ret; - } - - ret = imx_sc_rm_get_resource_owner(priv->ipc_scu, IMX_SC_R_SECO, &priv->part_owner); - if (ret) { - dev_err(dev, "Fail get owner of SECO resource\n"); - return ret; - } - - return ret; -} -EXPORT_SYMBOL(imx_scu_init_fw); - -int imx_scu_sec_mem_cfg(struct file *fp, uint32_t offset, uint32_t size) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - u64 high_boundary; - int ret = 0; - - high_boundary = offset; - if (high_boundary > SECURE_RAM_SIZE) { - dev_err(dev_ctx->priv->dev, "base offset is over secure memory\n"); - return -ENOMEM; - } - - high_boundary += size; - if (high_boundary > SECURE_RAM_SIZE) { - dev_err(dev_ctx->priv->dev, "total memory is over secure memory\n"); - return -ENOMEM; - } - - dev_ctx->secure_mem.dma_addr = (dma_addr_t)offset; - dev_ctx->secure_mem.size = size; - dev_ctx->secure_mem.pos = 0; - dev_ctx->secure_mem.ptr = devm_ioremap(dev_ctx->dev, - (phys_addr_t)(SECURE_RAM_BASE_ADDRESS + - (u64)dev_ctx->secure_mem.dma_addr), - dev_ctx->secure_mem.size); - if (!dev_ctx->secure_mem.ptr) { - dev_err(dev_ctx->priv->dev, "Failed to map secure memory\n"); - return -ENOMEM; - } - - return ret; -} -EXPORT_SYMBOL(imx_scu_sec_mem_cfg); - -int imx_scu_mem_access(struct file *fp) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - struct ele_mu_priv *priv = dev_ctx->priv; - u8 mr; - u64 addr; - int ret; - - addr = dev_ctx->non_secure_mem.dma_addr; - - ret = imx_sc_rm_find_memreg(priv->ipc_scu, - &mr, - addr, - addr + MAX_DATA_SIZE_PER_USER); - if (ret) { - dev_err(dev_ctx->priv->dev, - "%s: Fail find memreg\n", dev_ctx->miscdev.name); - return ret; - } - - ret = imx_sc_rm_set_memreg_permissions(priv->ipc_scu, mr, - priv->part_owner, - IMX_SC_RM_PERM_FULL); - if (ret) { - dev_err(dev_ctx->priv->dev, - "%s: Fail set permission for resource\n", - dev_ctx->miscdev.name); - return ret; - } - - return ret; -} -EXPORT_SYMBOL(imx_scu_mem_access); - -int imx_scu_signed_msg(struct file *fp, - uint8_t *msg, - uint32_t size, - uint32_t *error) -{ - struct ele_mu_device_ctx *dev_ctx - = container_of(fp->private_data, - struct ele_mu_device_ctx, - miscdev); - struct ele_mu_priv *priv = dev_ctx->priv; - struct ele_shared_mem *shared_mem = &dev_ctx->non_secure_mem; - int err; - u64 addr; - u32 pos; - - /* Check there is enough space in the shared memory. */ - if (size >= shared_mem->size - shared_mem->pos) { - dev_err(dev_ctx->priv->dev, - "Not enough mem: %d left, %d required\n", - shared_mem->size - shared_mem->pos, size); - return -ENOMEM; - } - - /* Allocate space in shared memory. 8 bytes aligned. */ - pos = shared_mem->pos; - - /* get physical address from the pos */ - addr = (u64)shared_mem->dma_addr + pos; - - /* copy signed message from user space to this allocated buffer */ - err = copy_from_user(shared_mem->ptr + pos, msg, size); - if (err) { - dev_err(dev_ctx->priv->dev, - "Failed to signed message from user: %d\n", - err); - return -EFAULT; - } - - *error = imx_sc_seco_sab_msg(priv->ipc_scu, addr); - err = *error; - if (err) { - dev_err(dev_ctx->priv->dev, "Failt to send signed message\n"); - } - - return err; -} -EXPORT_SYMBOL(imx_scu_signed_msg); diff --git a/drivers/firmware/imx/seco_mu.c b/drivers/firmware/imx/seco_mu.c deleted file mode 100644 index 9d747aad47db..000000000000 --- a/drivers/firmware/imx/seco_mu.c +++ /dev/null @@ -1,1318 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * Copyright 2019-2020, 2023 NXP - */ - -/* - * This driver allows to send messages to the SECO using a shared mailbox. The - * messages must follow the protocol defined. - */ - -/* - * Architecture of the driver: - * - * Non-Secure + Secure - * | - * | - * +---------+ +-------------+ | - * |seco_mu.c+<---->+imx-mailbox.c| | - * | | | mailbox.c +<-->+------+ +------+ - * +---+-----+ +-------------+ | MU X +<-->+ SECO | - * | +------+ +------+ - * +----------------+ | - * | | | - * v v | - * logical logical | - * receiver waiter | - * + + | - * | | | - * | | | - * | +----+------+ | - * | | | | - * | | | | - * device_ctx device_ctx device_ctx | - * | - * User 0 User 1 User Y | - * +------+ +------+ +------+ | - * |misc.c| |misc.c| |misc.c| | - * kernel space +------+ +------+ +------+ | - * | - * +------------------------------------------------------ | - * | | | | - * userspace /dev/seco_muXch0 | | | - * /dev/seco_muXch1 | | - * /dev/seco_muXchY | - * | - * - * When a user sends a command to the seco, it registers its device_ctx as - * waiter of a response from SECO - * - * A user can be registered as receiver of command by the SECO. - * - * When a message is received, the driver select the device_ctx receiving the - * message depending on the tag in the message. It selects the device_ctx - * accordingly. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_RECV_SIZE 31 -#define MAX_RECV_SIZE_BYTES (MAX_RECV_SIZE * sizeof(u32)) -#define MAX_MESSAGE_SIZE 31 -#define MAX_MESSAGE_SIZE_BYTES (MAX_MESSAGE_SIZE * sizeof(u32)) -#define MESSAGE_SIZE(hdr) (((struct she_mu_hdr *)(&(hdr)))->size) -#define MESSAGE_TAG(hdr) (((struct she_mu_hdr *)(&(hdr)))->tag) - -#define DEFAULT_MESSAGING_TAG_COMMAND (0x17u) -#define DEFAULT_MESSAGING_TAG_RESPONSE (0xe1u) - -#define SECURE_RAM_BASE_ADDRESS (0x31800000ULL) -#define SECURE_RAM_BASE_ADDRESS_SCU (0x20800000u) -#define SECURE_RAM_SIZE (0x10000ULL) - -#define SECO_MU_DEFAULT_MAX_USERS 4 - -#define SECO_MU_INTERRUPT_INDEX (0u) -#define SECO_DEFAULT_MU_INDEX (1u) -#define SECO_DEFAULT_TZ (0u) -#define DEFAULT_DID (0u) - -#define MAX_DATA_SIZE_PER_USER (65 * 1024) - -/* Header of the messages exchange with the SECO */ -struct she_mu_hdr { - u8 ver; - u8 size; - u8 command; - u8 tag; -} __packed; - -/* Status of a char device */ -enum mu_device_status_t { - MU_FREE, - MU_OPENED -}; - -struct seco_shared_mem { - dma_addr_t dma_addr; - u32 size; - u32 pos; - u8 *ptr; -}; - -struct seco_out_buffer_desc { - u8 *out_ptr; - u8 *out_usr_ptr; - u32 out_size; - struct list_head link; -}; - -/* Private struct for each char device instance. */ -struct seco_mu_device_ctx { - struct device *dev; - struct seco_mu_priv *mu_priv; - struct miscdevice miscdev; - - enum mu_device_status_t status; - wait_queue_head_t wq; - struct semaphore fops_lock; - - u32 pending_hdr; - struct list_head pending_out; - - struct seco_shared_mem secure_mem; - struct seco_shared_mem non_secure_mem; - - u32 temp_cmd[MAX_MESSAGE_SIZE]; - u32 temp_resp[MAX_RECV_SIZE]; - u32 temp_resp_size; - struct notifier_block scu_notify; - bool v2x_reset; -}; - -/* Private struct for seco MU driver. */ -struct seco_mu_priv { - struct seco_mu_device_ctx *cmd_receiver_dev; - struct seco_mu_device_ctx *waiting_rsp_dev; - /* - * prevent parallel access to the MU registers - * e.g. a user trying to send a command while the other one is - * sending a response. - */ - struct mutex mu_lock; - /* - * prevent a command to be sent on the MU while another one is still - * processing. (response to a command is allowed) - */ - struct mutex mu_cmd_lock; - struct device *dev; - u32 seco_mu_id; - u8 cmd_tag; - u8 rsp_tag; - - struct mbox_client cl; - struct mbox_chan *tx_chan; - struct mbox_chan *rx_chan; - - struct imx_sc_ipc *ipc_scu; - u8 seco_part_owner; - - int max_ctx; - struct seco_mu_device_ctx **ctxs; -}; - -static const struct seco_mu_ioctl_get_soc_info imx8dxl_a1_soc_info = { - .soc_id = 0xE, - .soc_rev = 0xa100, -}; - -static const struct seco_mu_ioctl_get_soc_info imx8dxl_b0_soc_info = { - .soc_id = 0xE, - .soc_rev = 0xb000, -}; - -static const struct soc_device_attribute soc_info_matches[] = { - { .soc_id = "i.MX8DXL", .revision = "1.1", .data = &imx8dxl_a1_soc_info}, - { .soc_id = "i.MX8DXL", .revision = "1.2", .data = &imx8dxl_b0_soc_info}, -}; - -/* macro to log operation of a misc device */ -#define miscdev_dbg(p_miscdev, fmt, va_args...) \ - ({ \ - struct miscdevice *_p_miscdev = p_miscdev; \ - dev_dbg((_p_miscdev)->parent, "%s: " fmt, (_p_miscdev)->name, \ - ##va_args); \ - }) - -#define miscdev_info(p_miscdev, fmt, va_args...) \ - ({ \ - struct miscdevice *_p_miscdev = p_miscdev; \ - dev_info((_p_miscdev)->parent, "%s: " fmt, (_p_miscdev)->name, \ - ##va_args); \ - }) - -#define miscdev_err(p_miscdev, fmt, va_args...) \ - ({ \ - struct miscdevice *_p_miscdev = p_miscdev; \ - dev_err((_p_miscdev)->parent, "%s: " fmt, (_p_miscdev)->name, \ - ##va_args); \ - }) - -/* macro to log operation of a device context */ -#define devctx_dbg(p_devctx, fmt, va_args...) \ - miscdev_dbg(&((p_devctx)->miscdev), fmt, ##va_args) -#define devctx_info(p_devctx, fmt, va_args...) \ - miscdev_info(&((p_devctx)->miscdev), fmt, ##va_args) -#define devctx_err(p_devctx, fmt, va_args...) \ - miscdev_err((&(p_devctx)->miscdev), fmt, ##va_args) - -#define IMX_SC_RM_PERM_FULL 7U /* Full access */ - -/* Give access to SECU to the memory we want to share */ -static int seco_mu_setup_seco_memory_access(struct seco_mu_device_ctx *dev_ctx, - u64 addr, u32 len) -{ - struct seco_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - int ret; - u8 mr; - - ret = imx_sc_rm_find_memreg(priv->ipc_scu, &mr, addr, addr + len); - if (ret) { - devctx_err(dev_ctx, "Fail find memreg\n"); - goto exit; - } - - ret = imx_sc_rm_set_memreg_permissions(priv->ipc_scu, mr, - priv->seco_part_owner, - IMX_SC_RM_PERM_FULL); - if (ret) { - devctx_err(dev_ctx, "Fail set permission for resource\n"); - goto exit; - } - -exit: - return ret; -} - -/* - * File operations for user-space - */ -/* Open a char device. */ -static int seco_mu_fops_open(struct inode *nd, struct file *fp) -{ - struct seco_mu_device_ctx *dev_ctx = container_of(fp->private_data, - struct seco_mu_device_ctx, miscdev); - int err; - - /* Avoid race if opened at the same time */ - if (down_trylock(&dev_ctx->fops_lock)) - return -EBUSY; - - /* Authorize only 1 instance. */ - if (dev_ctx->status != MU_FREE) { - err = -EBUSY; - goto exit; - } - - /* - * Allocate some memory for data exchanges with SECO. - * This will be used for data not requiring secure memory. - */ - dev_ctx->non_secure_mem.ptr = dmam_alloc_coherent(dev_ctx->dev, - MAX_DATA_SIZE_PER_USER, - &dev_ctx->non_secure_mem.dma_addr, - GFP_KERNEL); - if (!dev_ctx->non_secure_mem.ptr) { - err = -ENOMEM; - devctx_err(dev_ctx, "Failed to map shared memory with SECO\n"); - goto exit; - } - - err = seco_mu_setup_seco_memory_access(dev_ctx, - dev_ctx->non_secure_mem.dma_addr, - MAX_DATA_SIZE_PER_USER); - if (err) { - err = -EPERM; - devctx_err(dev_ctx, - "Failed to share access to shared memory\n"); - goto free_coherent; - } - - dev_ctx->non_secure_mem.size = MAX_DATA_SIZE_PER_USER; - dev_ctx->non_secure_mem.pos = 0; - dev_ctx->status = MU_OPENED; - - dev_ctx->pending_hdr = 0; - dev_ctx->v2x_reset = 0; - - goto exit; - -free_coherent: - dmam_free_coherent(dev_ctx->mu_priv->dev, MAX_DATA_SIZE_PER_USER, - dev_ctx->non_secure_mem.ptr, - dev_ctx->non_secure_mem.dma_addr); - -exit: - up(&dev_ctx->fops_lock); - return err; -} - -/* Close a char device. */ -static int seco_mu_fops_close(struct inode *nd, struct file *fp) -{ - struct seco_mu_device_ctx *dev_ctx = container_of(fp->private_data, - struct seco_mu_device_ctx, miscdev); - struct seco_mu_priv *mu_priv = dev_ctx->mu_priv; - struct seco_out_buffer_desc *out_buf_desc; - - /* Avoid race if closed at the same time */ - if (down_trylock(&dev_ctx->fops_lock)) - return -EBUSY; - - /* The device context has not been opened */ - if (dev_ctx->status != MU_OPENED) - goto exit; - - /* check if this device was registered as command receiver. */ - if (mu_priv->cmd_receiver_dev == dev_ctx) - mu_priv->cmd_receiver_dev = NULL; - - /* check if this device was registered as waiting response. */ - if (mu_priv->waiting_rsp_dev == dev_ctx) { - mu_priv->waiting_rsp_dev = NULL; - mutex_unlock(&mu_priv->mu_cmd_lock); - } - - /* Unmap secure memory shared buffer. */ - if (dev_ctx->secure_mem.ptr) - devm_iounmap(dev_ctx->dev, dev_ctx->secure_mem.ptr); - - dev_ctx->secure_mem.ptr = NULL; - dev_ctx->secure_mem.dma_addr = 0; - dev_ctx->secure_mem.size = 0; - dev_ctx->secure_mem.pos = 0; - - /* Free non-secure shared buffer. */ - dmam_free_coherent(dev_ctx->mu_priv->dev, MAX_DATA_SIZE_PER_USER, - dev_ctx->non_secure_mem.ptr, - dev_ctx->non_secure_mem.dma_addr); - - dev_ctx->non_secure_mem.ptr = NULL; - dev_ctx->non_secure_mem.dma_addr = 0; - dev_ctx->non_secure_mem.size = 0; - dev_ctx->non_secure_mem.pos = 0; - - while (!list_empty(&dev_ctx->pending_out)) { - out_buf_desc = list_first_entry_or_null(&dev_ctx->pending_out, - struct seco_out_buffer_desc, - link); - __list_del_entry(&out_buf_desc->link); - devm_kfree(dev_ctx->dev, out_buf_desc); - } - - dev_ctx->status = MU_FREE; - -exit: - up(&dev_ctx->fops_lock); - return 0; -} - -/* Write a message to the MU. */ -static ssize_t seco_mu_fops_write(struct file *fp, const char __user *buf, - size_t size, loff_t *ppos) -{ - struct seco_mu_device_ctx *dev_ctx = container_of(fp->private_data, - struct seco_mu_device_ctx, miscdev); - struct seco_mu_priv *mu_priv = dev_ctx->mu_priv; - u32 nb_words = 0, header; - int err; - - devctx_dbg(dev_ctx, "write from buf (%p)%ld, ppos=%lld\n", buf, size, - ((ppos) ? *ppos : 0)); - - if (down_interruptible(&dev_ctx->fops_lock)) - return -EBUSY; - - if (dev_ctx->status != MU_OPENED) { - err = -EINVAL; - goto exit; - } - - if (size < sizeof(struct she_mu_hdr)) { - devctx_err(dev_ctx, "User buffer too small(%ld < %lu)\n", size, - sizeof(struct she_mu_hdr)); - err = -ENOSPC; - goto exit; - } - - if (size > MAX_MESSAGE_SIZE_BYTES) { - devctx_err(dev_ctx, "User buffer too big(%ld > %lu)\n", size, - MAX_MESSAGE_SIZE_BYTES); - err = -ENOSPC; - goto exit; - } - - /* Copy data to buffer */ - err = (int)copy_from_user(dev_ctx->temp_cmd, buf, size); - if (err) { - err = -EFAULT; - devctx_err(dev_ctx, "Fail copy message from user\n"); - goto exit; - } - - print_hex_dump_debug("from user ", DUMP_PREFIX_OFFSET, 4, 4, - dev_ctx->temp_cmd, size, false); - - header = dev_ctx->temp_cmd[0]; - - /* Check the message is valid according to tags */ - if (MESSAGE_TAG(header) == mu_priv->cmd_tag) { - /* - * unlocked in seco_mu_receive_work_handler when the - * response to this command is received. - */ - mutex_lock(&mu_priv->mu_cmd_lock); - mu_priv->waiting_rsp_dev = dev_ctx; - } else if (MESSAGE_TAG(header) == mu_priv->rsp_tag) { - /* Check the device context can send the command */ - if (dev_ctx != mu_priv->cmd_receiver_dev) { - devctx_err(dev_ctx, - "This channel is not configured to send response to SECO\n"); - err = -EPERM; - goto exit; - } - } else { - devctx_err(dev_ctx, "The message does not have a valid TAG\n"); - err = -EINVAL; - goto exit; - } - - /* - * Check that the size passed as argument matches the size - * carried in the message. - */ - nb_words = MESSAGE_SIZE(header); - if (nb_words * sizeof(u32) != size) { - devctx_err(dev_ctx, "User buffer too small\n"); - goto exit; - } - - mutex_lock(&mu_priv->mu_lock); - - /* Send message */ - devctx_dbg(dev_ctx, "sending message\n"); - err = mbox_send_message(mu_priv->tx_chan, dev_ctx->temp_cmd); - if (err < 0) { - devctx_err(dev_ctx, "Failed to send message\n"); - goto unlock; - } - - err = nb_words * (u32)sizeof(u32); - -unlock: - mutex_unlock(&mu_priv->mu_lock); - -exit: - up(&dev_ctx->fops_lock); - return err; -} - -/* - * Read a message from the MU. - * Blocking until a message is available. - */ -static ssize_t seco_mu_fops_read(struct file *fp, char __user *buf, - size_t size, loff_t *ppos) -{ - struct seco_mu_device_ctx *dev_ctx = container_of(fp->private_data, - struct seco_mu_device_ctx, miscdev); - u32 data_size = 0, size_to_copy = 0; - struct seco_out_buffer_desc *b_desc; - int err; - - devctx_dbg(dev_ctx, "read to buf %p(%ld), ppos=%lld\n", buf, size, - ((ppos) ? *ppos : 0)); - - if (down_interruptible(&dev_ctx->fops_lock)) - return -EBUSY; - - if (dev_ctx->status != MU_OPENED) { - err = -EINVAL; - goto exit; - } - - if (dev_ctx->v2x_reset) { - err = -EINVAL; - goto exit; - } - - /* Wait until the complete message is received on the MU. */ - err = wait_event_interruptible(dev_ctx->wq, dev_ctx->pending_hdr != 0); - if (err) { - devctx_err(dev_ctx, "Interrupted by signal\n"); - goto exit; - } - - if (dev_ctx->v2x_reset) { - err = -EINVAL; - dev_ctx->v2x_reset = 0; - goto exit; - } - - devctx_dbg(dev_ctx, "%s %s\n", __func__, - "message received, start transmit to user"); - - /* Check that the size passed as argument is larger than - * the one carried in the message. - */ - data_size = dev_ctx->temp_resp_size * sizeof(u32); - size_to_copy = data_size; - if (size_to_copy > size) { - devctx_dbg(dev_ctx, "User buffer too small (%ld < %d)\n", - size, size_to_copy); - size_to_copy = size; - } - - /* We may need to copy the output data to user before - * delivering the completion message. - */ - while (!list_empty(&dev_ctx->pending_out)) { - b_desc = list_first_entry_or_null(&dev_ctx->pending_out, - struct seco_out_buffer_desc, - link); - if (b_desc->out_usr_ptr && b_desc->out_ptr) { - devctx_dbg(dev_ctx, "Copy output data to user\n"); - err = (int)copy_to_user(b_desc->out_usr_ptr, - b_desc->out_ptr, - b_desc->out_size); - if (err) { - devctx_err(dev_ctx, - "Failed to copy output data to user\n"); - err = -EFAULT; - goto exit; - } - } - __list_del_entry(&b_desc->link); - devm_kfree(dev_ctx->dev, b_desc); - } - - /* Copy data from the buffer */ - print_hex_dump_debug("to user ", DUMP_PREFIX_OFFSET, 4, 4, - dev_ctx->temp_resp, size_to_copy, false); - err = (int)copy_to_user(buf, dev_ctx->temp_resp, size_to_copy); - if (err) { - devctx_err(dev_ctx, "Failed to copy to user\n"); - err = -EFAULT; - goto exit; - } - - err = size_to_copy; - - /* free memory allocated on the shared buffers. */ - dev_ctx->secure_mem.pos = 0; - dev_ctx->non_secure_mem.pos = 0; - - dev_ctx->pending_hdr = 0; - -exit: - up(&dev_ctx->fops_lock); - return err; -} - -/* Configure the shared memory according to user config */ -static int -seco_mu_ioctl_shared_mem_cfg_handler(struct seco_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct seco_mu_ioctl_shared_mem_cfg cfg; - int err = -EINVAL; - u64 high_boundary; - - /* Check if not already configured. */ - if (dev_ctx->secure_mem.dma_addr != 0u) { - devctx_err(dev_ctx, "Shared memory not configured\n"); - goto exit; - } - - err = (int)copy_from_user(&cfg, (u8 *)arg, - sizeof(cfg)); - if (err) { - devctx_err(dev_ctx, "Fail copy shared memory config to user\n"); - err = -EFAULT; - goto exit; - } - - devctx_dbg(dev_ctx, "cfg offset: %u(%d)\n", cfg.base_offset, cfg.size); - - high_boundary = cfg.base_offset; - if (high_boundary > SECURE_RAM_SIZE) { - devctx_err(dev_ctx, "base offset is over secure memory\n"); - err = -ENOMEM; - goto exit; - } - - high_boundary += cfg.size; - if (high_boundary > SECURE_RAM_SIZE) { - devctx_err(dev_ctx, "total memory is over secure memory\n"); - err = -ENOMEM; - goto exit; - } - - dev_ctx->secure_mem.dma_addr = (dma_addr_t)cfg.base_offset; - dev_ctx->secure_mem.size = cfg.size; - dev_ctx->secure_mem.pos = 0; - dev_ctx->secure_mem.ptr = devm_ioremap(dev_ctx->dev, - (phys_addr_t)(SECURE_RAM_BASE_ADDRESS + - (u64)dev_ctx->secure_mem.dma_addr), - dev_ctx->secure_mem.size); - if (!dev_ctx->secure_mem.ptr) { - devctx_err(dev_ctx, "Failed to map secure memory\n"); - err = -ENOMEM; - goto exit; - } - -exit: - return err; -} - -/* - * Copy a buffer of daa to/from the user and return the address to use in - * messages - */ -static int seco_mu_ioctl_setup_iobuf_handler(struct seco_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct seco_out_buffer_desc *out_buf_desc; - struct seco_mu_ioctl_setup_iobuf io; - struct seco_shared_mem *shared_mem; - int err = -EINVAL; - u32 pos; - u8 *addr; - - struct seco_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - - err = (int)copy_from_user(&io, - (u8 *)arg, - sizeof(io)); - if (err) { - devctx_err(dev_ctx, "Failed copy iobuf config from user\n"); - err = -EFAULT; - goto exit; - } - - /* Function call to retrieve MU Buffer address */ - if (io.flags & SECO_MU_IO_FLAGS_SHE_V2X) - addr = get_mu_buf(priv->tx_chan); - - devctx_dbg(dev_ctx, "io [buf: %p(%d) flag: %x]\n", - io.user_buf, io.length, io.flags); - - if (io.length == 0 || !io.user_buf) { - /* - * Accept NULL pointers since some buffers are optional - * in SECO commands. In this case we should return 0 as - * pointer to be embedded into the message. - * Skip all data copy part of code below. - */ - io.seco_addr = 0; - goto copy; - } - - /* Select the shared memory to be used for this buffer. */ - if (!(io.flags & SECO_MU_IO_FLAGS_SHE_V2X)) { - if (io.flags & SECO_MU_IO_FLAGS_USE_SEC_MEM) { - /* App requires to use secure memory for this buffer.*/ - shared_mem = &dev_ctx->secure_mem; - } else { - /* No specific requirement for this buffer. */ - shared_mem = &dev_ctx->non_secure_mem; - } - } - - /* Check there is enough space in the shared memory. */ - if (!(io.flags & SECO_MU_IO_FLAGS_SHE_V2X) && - (io.length >= shared_mem->size - shared_mem->pos)) { - devctx_err(dev_ctx, "Not enough space in shared memory\n"); - err = -ENOMEM; - goto exit; - } - - if (!(io.flags & SECO_MU_IO_FLAGS_SHE_V2X)) { - /* Allocate space in shared memory. 8 bytes aligned. */ - pos = shared_mem->pos; - shared_mem->pos += round_up(io.length, 8u); - io.seco_addr = (u64)shared_mem->dma_addr + pos; - } else { - if (io.length > MAX_DATA_SIZE_PER_USER) { - devctx_err(dev_ctx, "Buffer length exceeded the max limit\n"); - err = -ENOMEM; - goto exit; - } - - io.seco_addr = (u64)addr; - } - - if ((io.flags & SECO_MU_IO_FLAGS_USE_SEC_MEM) && - !(io.flags & SECO_MU_IO_FLAGS_USE_SHORT_ADDR)) - /*Add base address to get full address.*/ - io.seco_addr += SECURE_RAM_BASE_ADDRESS_SCU; - - if (io.flags & SECO_MU_IO_FLAGS_IS_INPUT) { - /* - * buffer is input: - * copy data from user space to this allocated buffer. - */ - if (io.flags & SECO_MU_IO_FLAGS_SHE_V2X) { - err = (int)copy_from_user(addr, io.user_buf, io.length); - } else { - err = (int)copy_from_user(shared_mem->ptr + pos, - io.user_buf, - io.length); - } - if (err) { - devctx_err(dev_ctx, - "Failed copy data to shared memory\n"); - err = -EFAULT; - goto exit; - } - } else { - /* - * buffer is output: - * add an entry in the "pending buffers" list so data - * can be copied to user space when receiving SECO - * response. - */ - out_buf_desc = devm_kmalloc(dev_ctx->dev, sizeof(*out_buf_desc), - GFP_KERNEL); - if (!out_buf_desc) { - err = -ENOMEM; - devctx_err(dev_ctx, - "Failed allocating mem for pending buffer\n" - ); - goto exit; - } - - if (io.flags & SECO_MU_IO_FLAGS_SHE_V2X) - out_buf_desc->out_ptr = addr; - else - out_buf_desc->out_ptr = shared_mem->ptr + pos; - out_buf_desc->out_usr_ptr = io.user_buf; - out_buf_desc->out_size = io.length; - list_add_tail(&out_buf_desc->link, &dev_ctx->pending_out); - } - -copy: - /* Provide the seco address to user space only if success. */ - err = (int)copy_to_user((u8 *)arg, &io, - sizeof(io)); - if (err) { - devctx_err(dev_ctx, "Failed to copy iobuff setup to user\n"); - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -/* Retrieve info about the MU */ -static int seco_mu_ioctl_get_mu_info_handler(struct seco_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct seco_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - struct seco_mu_ioctl_get_mu_info info; - int err = -EINVAL; - - info.seco_mu_idx = (u8)priv->seco_mu_id; - info.interrupt_idx = SECO_MU_INTERRUPT_INDEX; - info.tz = SECO_DEFAULT_TZ; - info.did = 0; - info.cmd_tag = (u8)priv->cmd_tag; - info.rsp_tag = (u8)priv->rsp_tag; - info.success_tag = 0; - info.base_api_ver = 0; - info.fw_api_ver = 0; - - err = imx_sc_rm_get_did(priv->ipc_scu, &info.did); - if (err) { - devctx_err(dev_ctx, "Get did failed\n"); - goto exit; - } - - devctx_dbg(dev_ctx, - "info [mu_idx: %d, irq_idx: %d, tz: 0x%x, did: 0x%x]\n", - info.seco_mu_idx, info.interrupt_idx, info.tz, info.did); - - err = (int)copy_to_user((u8 *)arg, &info, - sizeof(info)); - if (err) { - devctx_err(dev_ctx, "Failed to copy mu info to user\n"); - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -static int seco_mu_ioctl_signed_msg_handler(struct seco_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - struct seco_shared_mem *shared_mem = &dev_ctx->non_secure_mem; - struct seco_mu_priv *priv = dev_get_drvdata(dev_ctx->dev); - struct seco_mu_ioctl_signed_message msg; - int err = -EINVAL; - u64 addr; - u32 pos; - - err = (int)copy_from_user(&msg, - (u8 *)arg, - sizeof(msg)); - if (err) { - devctx_err(dev_ctx, "Failed to copy from user: %d\n", err); - err = -EFAULT; - goto exit; - } - - /* Check there is enough space in the shared memory. */ - if (msg.msg_size >= shared_mem->size - shared_mem->pos) { - devctx_err(dev_ctx, "Not enough mem: %d left, %d required\n", - shared_mem->size - shared_mem->pos, msg.msg_size); - err = -ENOMEM; - goto exit; - } - - /* Allocate space in shared memory. 8 bytes aligned. */ - pos = shared_mem->pos; - - /* get physical address from the pos */ - addr = (u64)shared_mem->dma_addr + pos; - - /* copy signed message from user space to this allocated buffer */ - err = (int)copy_from_user(shared_mem->ptr + pos, msg.message, - msg.msg_size); - if (err) { - devctx_err(dev_ctx, "Failed to signed message from user: %d\n", - err); - err = -EFAULT; - goto exit; - } - - /* Send the message to SECO through SCU */ - msg.error_code = imx_sc_seco_sab_msg(priv->ipc_scu, addr); - - err = (int)copy_to_user((u8 *)arg, &msg, - sizeof(msg)); - if (err) { - devctx_err(dev_ctx, "Failed to copy to user: %d\n", err); - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -/* IOCTL to provide SoC information */ -static int seco_mu_ioctl_get_soc_info_handler(struct seco_mu_device_ctx *dev_ctx, - unsigned long arg) -{ - const struct soc_device_attribute *imx_soc_match; - struct seco_mu_ioctl_get_soc_info *soc_info; - int err = -EINVAL; - - imx_soc_match = soc_device_match(soc_info_matches); - if (!imx_soc_match || !imx_soc_match->data) - goto exit; - - soc_info = (struct seco_mu_ioctl_get_soc_info *)(imx_soc_match->data); - - err = (int)copy_to_user((u8 *)arg, - (u8 *)soc_info, - sizeof(struct seco_mu_ioctl_get_soc_info)); - if (err) { - devctx_err(dev_ctx, "Failed to copy to user: %d\n", err); - err = -EFAULT; - goto exit; - } - -exit: - return err; -} - -/* IOCTL entry point of a char device */ -static long seco_mu_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) -{ - struct seco_mu_device_ctx *dev_ctx = container_of(fp->private_data, - struct seco_mu_device_ctx, miscdev); - struct seco_mu_priv *mu_priv = dev_ctx->mu_priv; - int err = -EINVAL; - - /* Prevent race during change of device context */ - if (down_interruptible(&dev_ctx->fops_lock)) - return -EBUSY; - - switch (cmd) { - case SECO_MU_IOCTL_ENABLE_CMD_RCV: - if (!mu_priv->cmd_receiver_dev) { - devctx_dbg(dev_ctx, "setting as receiver\n"); - mu_priv->cmd_receiver_dev = dev_ctx; - err = 0; - }; - break; - case SECO_MU_IOCTL_SHARED_BUF_CFG: - err = seco_mu_ioctl_shared_mem_cfg_handler(dev_ctx, arg); - break; - case SECO_MU_IOCTL_SETUP_IOBUF: - err = seco_mu_ioctl_setup_iobuf_handler(dev_ctx, arg); - break; - case SECO_MU_IOCTL_GET_MU_INFO: - err = seco_mu_ioctl_get_mu_info_handler(dev_ctx, arg); - break; - case SECO_MU_IOCTL_SIGNED_MESSAGE: - err = seco_mu_ioctl_signed_msg_handler(dev_ctx, arg); - break; - case SECO_MU_IOCTL_GET_SOC_INFO: - err = seco_mu_ioctl_get_soc_info_handler(dev_ctx, arg); - break; - default: - err = -EINVAL; - devctx_dbg(dev_ctx, "IOCTL %.8x not supported\n", cmd); - } - - up(&dev_ctx->fops_lock); - return (long)err; -} - -/* - * Callback called by mailbox FW when data are received - */ -static void seco_mu_rx_callback(struct mbox_client *c, void *msg) -{ - struct device *dev = c->dev; - struct seco_mu_priv *priv = dev_get_drvdata(dev); - struct seco_mu_device_ctx *dev_ctx; - bool is_response = false; - int msg_size; - u32 header; - - dev_dbg(dev, "Message received on mailbox\n"); - - /* The function can be called with NULL msg */ - if (!msg) { - dev_err(dev, "Message is invalid\n"); - return; - } - - if (IS_ERR(msg)) { - dev_err(dev, "Error during reception of message: %ld\n", - PTR_ERR(msg)); - return; - } - - header = *(u32 *)msg; - - dev_dbg(dev, "Selecting device\n"); - - /* Incoming command: wake up the receiver if any. */ - if (MESSAGE_TAG(header) == priv->cmd_tag) { - dev_dbg(dev, "Selecting cmd receiver\n"); - dev_ctx = priv->cmd_receiver_dev; - } else if (MESSAGE_TAG(header) == priv->rsp_tag) { - dev_dbg(dev, "Selecting rsp waiter\n"); - dev_ctx = priv->waiting_rsp_dev; - is_response = true; - } else { - dev_err(dev, "Failed to select a device for message: %.8x\n", - header); - return; - } - - if (!dev_ctx) { - dev_err(dev, "No device context selected for message: %.8x\n", - header); - return; - } - - /* Init reception */ - msg_size = MESSAGE_SIZE(header); - if (msg_size > MAX_RECV_SIZE) { - devctx_err(dev_ctx, "Message is too big (%d > %d)", msg_size, - MAX_RECV_SIZE); - return; - } - - memcpy(dev_ctx->temp_resp, msg, msg_size * sizeof(u32)); - dev_ctx->temp_resp_size = msg_size; - - /* Allow user to read */ - dev_ctx->pending_hdr = dev_ctx->temp_resp[0]; - wake_up_interruptible(&dev_ctx->wq); - - if (is_response) { - /* Allow user to send new command */ - mutex_unlock(&priv->mu_cmd_lock); - } -} - -#define SECO_FW_VER_FEAT_MASK (0x0000FFF0u) -#define SECO_FW_VER_FEAT_SHIFT (0x04u) -#define SECO_FW_VER_FEAT_MIN_ALL_MU (0x04u) - -/* - * Get SECO FW version and check if it supports receiving commands on all MUs - * The version is retrieved through SCU since this is the only communication - * channel to SECO always present. - */ -static int seco_mu_check_all_mu_supported(struct device *dev) -{ - struct seco_mu_priv *priv = dev_get_drvdata(dev); - u32 seco_ver; - int ret; - - ret = imx_sc_seco_build_info(priv->ipc_scu, &seco_ver, NULL); - if (ret) { - dev_err(dev, "failed to retrieve SECO build info\n"); - goto exit; - } - - if (((seco_ver & SECO_FW_VER_FEAT_MASK) >> SECO_FW_VER_FEAT_SHIFT) - < SECO_FW_VER_FEAT_MIN_ALL_MU) { - dev_err(dev, "current SECO FW do not support MU with Linux\n"); - ret = -ENOTSUPP; - goto exit; - } - -exit: - return ret; -} - -/* Char driver setup */ -static const struct file_operations seco_mu_fops = { - .open = seco_mu_fops_open, - .owner = THIS_MODULE, - .read = seco_mu_fops_read, - .release = seco_mu_fops_close, - .write = seco_mu_fops_write, - .unlocked_ioctl = seco_mu_ioctl, -}; - -/* interface for managed res to free a mailbox channel */ -static void if_mbox_free_channel(void *mbox_chan) -{ - mbox_free_channel(mbox_chan); -} - -/* interface for managed res to unregister a char device */ -static void if_misc_deregister(void *miscdevice) -{ - misc_deregister(miscdevice); -} - -static int seco_mu_request_channel(struct device *dev, - struct mbox_chan **chan, - const char *name) -{ - struct seco_mu_priv *priv = dev_get_drvdata(dev); - struct mbox_chan *t_chan; - int ret = 0; - - t_chan = mbox_request_channel_byname(&priv->cl, name); - if (IS_ERR(t_chan)) { - ret = PTR_ERR(t_chan); - if (ret != -EPROBE_DEFER) - dev_err(dev, - "Failed to request chan %s ret %d\n", name, - ret); - goto exit; - } - - ret = devm_add_action(dev, if_mbox_free_channel, t_chan); - if (ret) { - dev_err(dev, "failed to add devm removal of mbox %s\n", name); - goto exit; - } - - *chan = t_chan; - -exit: - return ret; -} - -static int imx_sc_v2x_reset_notify(struct notifier_block *nb, - unsigned long event, void *group) -{ - struct seco_mu_device_ctx *dev_ctx = container_of(nb, - struct seco_mu_device_ctx, scu_notify); - - if (!(event & IMX_SC_IRQ_V2X_RESET)) - return 0; - - dev_ctx->v2x_reset = true; - - wake_up_interruptible(&dev_ctx->wq); - return 0; -} -/* Driver probe.*/ -static int seco_mu_probe(struct platform_device *pdev) -{ - struct seco_mu_device_ctx *dev_ctx; - struct device *dev = &pdev->dev; - struct seco_mu_priv *priv; - struct device_node *np; - int max_nb_users = 0; - char *devname; - int ret; - int i; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - dev_err(dev, "Fail allocate mem for private data\n"); - goto exit; - } - priv->dev = dev; - dev_set_drvdata(dev, priv); - - /* - * Get the address of MU to be used for communication with the SCU - */ - np = pdev->dev.of_node; - if (!np) { - dev_err(dev, "Cannot find MU User entry in device tree\n"); - ret = -ENOTSUPP; - goto exit; - } - - ret = imx_scu_get_handle(&priv->ipc_scu); - if (ret) { - dev_err(dev, "Fail to retrieve IPC handle\n"); - goto exit; - } - - ret = imx_sc_rm_get_resource_owner(priv->ipc_scu, IMX_SC_R_SECO, - &priv->seco_part_owner); - if (ret) { - dev_err(dev, "Fail get owner of SECO resource\n"); - goto exit; - } - - ret = seco_mu_check_all_mu_supported(dev); - if (ret) { - dev_err(dev, "Fail seco_mu_check_all_mu_supported\n"); - goto exit; - } - - /* Initialize the mutex. */ - mutex_init(&priv->mu_cmd_lock); - mutex_init(&priv->mu_lock); - - priv->cmd_receiver_dev = NULL; - priv->waiting_rsp_dev = NULL; - - ret = of_property_read_u32(np, "fsl,seco_mu_id", &priv->seco_mu_id); - if (ret) { - dev_warn(dev, "%s: Not able to read mu_id", __func__); - priv->seco_mu_id = SECO_DEFAULT_MU_INDEX; - } - - ret = of_property_read_u32(np, "fsl,seco_max_users", &max_nb_users); - if (ret) { - dev_warn(dev, "%s: Not able to read mu_max_user", __func__); - max_nb_users = SECO_MU_DEFAULT_MAX_USERS; - } - - ret = of_property_read_u8(np, "fsl,cmd_tag", &priv->cmd_tag); - if (ret) - priv->cmd_tag = DEFAULT_MESSAGING_TAG_COMMAND; - - ret = of_property_read_u8(np, "fsl,rsp_tag", &priv->rsp_tag); - if (ret) - priv->rsp_tag = DEFAULT_MESSAGING_TAG_RESPONSE; - - /* Mailbox client configuration */ - priv->cl.dev = dev; - priv->cl.knows_txdone = true; - priv->cl.rx_callback = seco_mu_rx_callback; - - ret = seco_mu_request_channel(dev, &priv->tx_chan, "txdb"); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to request txdb channel\n"); - - goto exit; - } - - ret = seco_mu_request_channel(dev, &priv->rx_chan, "rxdb"); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to request rxdb channel\n"); - - goto exit; - } - - priv->max_ctx = max_nb_users; - priv->ctxs = devm_kzalloc(dev, sizeof(dev_ctx) * max_nb_users, GFP_KERNEL); - - /* Create users */ - for (i = 0; i < max_nb_users; i++) { - dev_ctx = devm_kzalloc(dev, sizeof(*dev_ctx), GFP_KERNEL); - if (!dev_ctx) { - ret = -ENOMEM; - dev_err(dev, - "Fail to allocate memory for device context\n"); - goto exit; - } - - dev_ctx->dev = dev; - dev_ctx->status = MU_FREE; - dev_ctx->mu_priv = priv; - - priv->ctxs[i] = dev_ctx; - - /* Default value invalid for an header. */ - init_waitqueue_head(&dev_ctx->wq); - - INIT_LIST_HEAD(&dev_ctx->pending_out); - sema_init(&dev_ctx->fops_lock, 1); - - devname = devm_kasprintf(dev, GFP_KERNEL, "seco_mu%d_ch%d", - priv->seco_mu_id, i); - if (!devname) { - ret = -ENOMEM; - dev_err(dev, - "Fail to allocate memory for misc dev name\n"); - goto exit; - } - - dev_ctx->miscdev.name = devname; - dev_ctx->miscdev.minor = MISC_DYNAMIC_MINOR; - dev_ctx->miscdev.fops = &seco_mu_fops; - dev_ctx->miscdev.parent = dev; - ret = misc_register(&dev_ctx->miscdev); - if (ret) { - dev_err(dev, "failed to register misc device %d\n", - ret); - goto exit; - } - - ret = devm_add_action(dev, if_misc_deregister, - &dev_ctx->miscdev); - - dev_ctx->scu_notify.notifier_call = imx_sc_v2x_reset_notify; - - ret = imx_scu_irq_register_notifier(&dev_ctx->scu_notify); - if (ret) { - dev_err(&pdev->dev, "v2x reqister scu notifier failed.\n"); - return ret; - } - - if (ret) - dev_warn(dev, - "failed to add managed removal of miscdev\n"); - } - - ret = imx_scu_irq_group_enable(IMX_SC_IRQ_GROUP_WAKE, - IMX_SC_IRQ_V2X_RESET, true); - if (ret) { - dev_warn(&pdev->dev, "v2x Enable irq failed.\n"); - return ret; - } - -exit: - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int secu_mu_resume(struct device *dev) -{ - struct seco_mu_priv *priv = dev_get_drvdata(dev); - int i=0; - - for (i = 0; i < priv->max_ctx; i++) { - priv->ctxs[i]->v2x_reset = true; - wake_up_interruptible(&priv->ctxs[i]->wq); - } - return 0; -} -#endif - -static const struct of_device_id seco_mu_match[] = { - { - .compatible = "fsl,imx-seco-mu", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, seco_mu_match); - -static const struct dev_pm_ops secu_mu_pm = { - SET_SYSTEM_SLEEP_PM_OPS(NULL, secu_mu_resume) -}; - -static struct platform_driver seco_mu_driver = { - .driver = { - .name = "seco_mu", - .of_match_table = seco_mu_match, - .pm = &secu_mu_pm, - }, - .probe = seco_mu_probe, -}; - -module_platform_driver(seco_mu_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("IMX Seco MU"); -MODULE_AUTHOR("NXP"); diff --git a/drivers/firmware/imx/v2x_base_msg.c b/drivers/firmware/imx/v2x_base_msg.c deleted file mode 100644 index 09d14c25d894..000000000000 --- a/drivers/firmware/imx/v2x_base_msg.c +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2021-2023 NXP - */ - -#include -#include - -#include - -#include "ele_common.h" - -/* - * v2x_start_rng() - prepare and send the command to start - * initialization of the ELE RNG context - * - * returns: 0 on success. - */ -int v2x_start_rng(struct device *dev) -{ - struct ele_mu_priv *priv = dev_get_drvdata(dev); - int ret; - unsigned int status; - - mutex_lock(&priv->mu_cmd_lock); - ret = imx_se_alloc_tx_rx_buf(priv); - if (ret) - goto exit; - - ret = plat_fill_cmd_msg_hdr(priv, - (struct mu_hdr *)&priv->tx_msg->header, - V2X_START_RNG_REQ, - V2X_START_RNG_REQ_MSG_SZ, - true); - if (ret) - goto exit; - - ret = imx_ele_msg_send_rcv(priv); - if (ret < 0) - goto exit; - - ret = validate_rsp_hdr(priv, - priv->rx_msg->header, - V2X_START_RNG_REQ, - V2X_START_RNG_RSP_MSG_SZ, - true); - if (ret) - goto exit; - - status = RES_STATUS(priv->rx_msg->data[0]); - if (status != priv->success_tag) { - /* Initialization in progress for: - * P-TRNG at bit 0 - * S-TRNG at bit 1 - * Any of the bit is set, it in progress. - */ - if (priv->rx_msg->data[1] & 0x3) - goto exit; - - dev_err(dev, "Command Id[%d], Response Failure = 0x%x", - V2X_START_RNG_REQ, status); - ret = -1; - } - -exit: - imx_se_free_tx_rx_buf(priv); - mutex_unlock(&priv->mu_cmd_lock); - - return ret; -} diff --git a/include/linux/firmware/imx/ele_base_msg.h b/include/linux/firmware/imx/ele_base_msg.h deleted file mode 100644 index 5e554de66011..000000000000 --- a/include/linux/firmware/imx/ele_base_msg.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2021-2024 NXP - * - * Header file for the ELE Base API(s). - */ - -#ifndef ELE_BASE_MSG_H -#define ELE_BASE_MSG_H - -#include - -#define WORD_SZ 4 -#define ELE_NONE_VAL 0x0 - -#define ELE_SUCCESS_IND 0xD6 - -#define ELE_GET_INFO_REQ 0xDA -#define ELE_GET_INFO_REQ_MSG_SZ 0x10 -#define ELE_GET_INFO_RSP_MSG_SZ 0x08 - -#define ELE_GET_INFO_BUFF_SZ 0x100 -#define ELE_GET_INFO_READ_SZ 0xA0 -#define DEVICE_GET_INFO_SZ 0x100 - -#define GET_INFO_SOC_INFO_WORD_OFFSET 1 -#define GET_INFO_UUID_WORD_OFFSET 3 -#define GET_INFO_SL_NUM_MSB_WORD_OFF \ - (GET_INFO_UUID_WORD_OFFSET + 3) -#define GET_INFO_SL_NUM_LSB_WORD_OFF \ - (GET_INFO_UUID_WORD_OFFSET + 0) - -#define ELE_PING_REQ 0x01 -#define ELE_PING_REQ_SZ 0x04 -#define ELE_PING_RSP_SZ 0x08 - -#define ELE_START_RNG_REQ 0xA3 -#define ELE_START_RNG_REQ_MSG_SZ 0x04 -#define ELE_START_RNG_RSP_MSG_SZ 0x08 - -#define ELE_GET_TRNG_STATE_REQ 0xA4 -#define ELE_GET_TRNG_STATE_REQ_MSG_SZ 0x04 -#define ELE_GET_TRNG_STATE_RSP_MSG_SZ 0x0C -#define ELE_TRNG_STATE_OK 0x203 -#define ELE_GET_TRNG_STATE_RETRY_COUNT 0x5 -#define CSAL_TRNG_STATE_MASK 0x0000ffff - -#define ELE_SERVICE_SWAP_REQ 0xDF -#define ELE_SERVICE_SWAP_REQ_MSG_SZ 0x18 -#define ELE_SERVICE_SWAP_RSP_MSG_SZ 0x0C -#define ELE_IMEM_SIZE 0x10000 -#define ELE_IMEM_STATE_OK 0xCA -#define ELE_IMEM_STATE_BAD 0xFE -#define ELE_IMEM_STATE_WORD 0x27 -#define ELE_IMEM_STATE_MASK 0x00ff0000 -#define ELE_IMEM_EXPORT 0x1 -#define ELE_IMEM_IMPORT 0x2 - -#define ELE_FW_AUTH_REQ 0x02 -#define ELE_FW_AUTH_REQ_SZ 0x10 -#define ELE_FW_AUTH_RSP_MSG_SZ 0x08 - -#define ELE_READ_FUSE_REQ 0x97 -#define ELE_READ_FUSE_REQ_MSG_SZ 0x08 -#define ELE_READ_FUSE_RSP_MSG_SZ 0x0C -#define ELE_READ_FUSE_OTP_UNQ_ID_RSP_MSG_SZ \ - 0x1C -#define OTP_UNIQ_ID 0x01 -#define OTFAD_CONFIG 0x2 - -#define ELE_GET_STATE 0xB2 -#define ELE_GET_STATE_REQ_SZ 0x04 -#define ELE_GET_STATE_RSP_SZ 0x10 - -#define ELE_WRITE_FUSE 0xD6 -#define ELE_WRITE_FUSE_REQ_MSG_SZ 12 -#define ELE_WRITE_FUSE_RSP_MSG_SZ 12 - -#define V2X_FW_STATE_UNKNOWN 0x00 -#define V2X_FW_STATE_RUNNING 0x15 - -#define ELE_VOLT_CHANGE_START_REQ 0x12 -#define ELE_VOLT_CHANGE_FINISH_REQ 0x13 -#define ELE_VOLT_CHANGE_REQ_MSG_SZ 0x4 -#define ELE_VOLT_CHANGE_RSP_MSG_SZ 0x8 - -int ele_get_info(struct device *dev, phys_addr_t addr, u32 data_size); -int ele_ping(struct device *dev); -int ele_start_rng(struct device *dev); -int ele_get_trng_state(struct device *dev); -int ele_service_swap(struct device *dev, - phys_addr_t addr, - u32 addr_size, u16 flag); -int ele_get_v2x_fw_state(struct device *dev, uint32_t *state); -int ele_write_fuse(struct device *dev, uint16_t fuse_index, u32 value, bool block); -int ele_voltage_change_req(struct device *dev, bool start); - -int read_common_fuse(struct device *dev, - uint16_t fuse_id, u32 *value); - -int ele_fw_authenticate(struct device *dev, phys_addr_t addr); -#endif diff --git a/include/linux/firmware/imx/ele_mu_ioctl.h b/include/linux/firmware/imx/ele_mu_ioctl.h deleted file mode 100644 index 349eefe7eff9..000000000000 --- a/include/linux/firmware/imx/ele_mu_ioctl.h +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause*/ -/* - * Copyright 2019-2024 NXP - */ - -#ifndef ELE_MU_IOCTL_H -#define ELE_MU_IOCTL_H - -/* IOCTL definitions. */ - -struct ele_mu_ioctl_setup_iobuf { - u8 *user_buf; - u32 length; - u32 flags; - u64 ele_addr; -}; - -struct ele_mu_ioctl_shared_mem_cfg { - u32 base_offset; - u32 size; -}; - -struct ele_mu_ioctl_get_mu_info { - u8 ele_mu_id; - u8 interrupt_idx; - u8 tz; - u8 did; - u8 cmd_tag; - u8 rsp_tag; - u8 success_tag; - u8 base_api_ver; - u8 fw_api_ver; -}; - -struct ele_mu_ioctl_signed_message { - u8 *message; - u32 msg_size; - u32 error_code; -}; - -struct ele_mu_ioctl_get_soc_info { - u16 soc_id; - u16 soc_rev; - u8 board_type; -}; - -struct ele_time_frame { - struct timespec64 t_start; - struct timespec64 t_end; -}; - -/* IO Buffer Flags */ -#define ELE_MU_IO_FLAGS_IS_OUTPUT (0x00u) -#define ELE_MU_IO_FLAGS_IS_INPUT (0x01u) -#define ELE_MU_IO_FLAGS_USE_SEC_MEM (0x02u) -#define ELE_MU_IO_FLAGS_USE_SHORT_ADDR (0x04u) -#define ELE_MU_IO_DATA_BUF_SHE_V2X (0x08u) -#define ELE_MU_IO_FLAGS_IS_IN_OUT (0x10u) - -/* IOCTLS */ -#define ELE_MU_IOCTL 0x0A /* like MISC_MAJOR. */ - -/* - * ioctl to designated the current fd as logical-reciever. - * This is ioctl is send when the nvm-daemon, a slave to the - * firmware is started by the user. - */ -#define ELE_MU_IOCTL_ENABLE_CMD_RCV _IO(ELE_MU_IOCTL, 0x01) - -/* - * ioctl to get configure the SCU shared buffer. - */ -#define ELE_MU_IOCTL_SHARED_BUF_CFG _IOW(ELE_MU_IOCTL, 0x02, \ - struct ele_mu_ioctl_shared_mem_cfg) -/* - * ioctl to get the buffer allocated from the memory, which is shared - * between kernel and FW. - * Post allocation, the kernel tagged the allocated memory with: - * Output - * Input - * Input-Output - * Short address - * Secure-memory - */ -#define ELE_MU_IOCTL_SETUP_IOBUF _IOWR(ELE_MU_IOCTL, 0x03, \ - struct ele_mu_ioctl_setup_iobuf) - -/* - * ioctl to get the mu information, that is used to exchange message - * with FW, from user-spaced. - */ -#define ELE_MU_IOCTL_GET_MU_INFO _IOR(ELE_MU_IOCTL, 0x04, \ - struct ele_mu_ioctl_get_mu_info) - -/* - * ioctl to send signed message to SE. - */ -#define ELE_MU_IOCTL_SIGNED_MESSAGE _IOR(ELE_MU_IOCTL, 0x05, \ - struct ele_mu_ioctl_signed_message) - -/* - * ioctl to get SoC Info from user-space. - */ -#define ELE_MU_IOCTL_GET_SOC_INFO _IOR(ELE_MU_IOCTL, 0x06, \ - struct ele_mu_ioctl_get_soc_info) - -/* - * ioctl to capture the timestamp at the request to FW and response from FW - * for a crypto operation - */ -#define ELE_MU_IOCTL_GET_TIMER _IOR(ELE_MU_IOCTL, 0x08, struct ele_time_frame) -#endif diff --git a/include/linux/firmware/imx/se_fw_inc.h b/include/linux/firmware/imx/se_fw_inc.h deleted file mode 100644 index 01cf62ebbd83..000000000000 --- a/include/linux/firmware/imx/se_fw_inc.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2023 NXP - */ - -#ifndef SE_FW_INC_H -#define SE_FW_INC_H - -struct device *get_se_dev(const uint8_t *pdev_name); -#endif /* SE_FW_INC_H */ diff --git a/include/linux/firmware/imx/seco_mu_ioctl.h b/include/linux/firmware/imx/seco_mu_ioctl.h deleted file mode 100644 index 1c74a515d18d..000000000000 --- a/include/linux/firmware/imx/seco_mu_ioctl.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause*/ -/* - * Copyright 2019-2020, 2023 NXP - */ - -#ifndef SECO_MU_IOCTL_H -#define SECO_MU_IOCTL_H - -/* IOCTL definitions. */ -struct seco_mu_ioctl_setup_iobuf { - u8 *user_buf; - u32 length; - u32 flags; - u64 seco_addr; -}; - -struct seco_mu_ioctl_shared_mem_cfg { - u32 base_offset; - u32 size; -}; - -struct seco_mu_ioctl_get_mu_info { - u8 seco_mu_idx; - u8 interrupt_idx; - u8 tz; - u8 did; - u8 cmd_tag; - u8 rsp_tag; - u8 success_tag; - u8 base_api_ver; - u8 fw_api_ver; -}; - -struct seco_mu_ioctl_signed_message { - u8 *message; - u32 msg_size; - u32 error_code; -}; - -struct seco_mu_ioctl_get_soc_info { - u16 soc_id; - u16 soc_rev; -}; - -#define SECO_MU_IO_FLAGS_IS_INPUT (0x01u) -#define SECO_MU_IO_FLAGS_USE_SEC_MEM (0x02u) -#define SECO_MU_IO_FLAGS_USE_SHORT_ADDR (0x04u) -#define SECO_MU_IO_FLAGS_SHE_V2X (0x08u) - -#define SECO_MU_IOCTL 0x0A /* like MISC_MAJOR. */ -#define SECO_MU_IOCTL_ENABLE_CMD_RCV _IO(SECO_MU_IOCTL, 0x01) -#define SECO_MU_IOCTL_SHARED_BUF_CFG _IOW(SECO_MU_IOCTL, 0x02, \ - struct seco_mu_ioctl_shared_mem_cfg) -#define SECO_MU_IOCTL_SETUP_IOBUF _IOWR(SECO_MU_IOCTL, 0x03, \ - struct seco_mu_ioctl_setup_iobuf) -#define SECO_MU_IOCTL_GET_MU_INFO _IOR(SECO_MU_IOCTL, 0x04, \ - struct seco_mu_ioctl_get_mu_info) -#define SECO_MU_IOCTL_SIGNED_MESSAGE _IOWR(SECO_MU_IOCTL, 0x05, \ - struct seco_mu_ioctl_signed_message) -#define SECO_MU_IOCTL_GET_SOC_INFO _IOR(SECO_MU_IOCTL, 0x06, \ - struct seco_mu_ioctl_get_soc_info) - -#endif diff --git a/include/linux/firmware/imx/svc/seco.h b/include/linux/firmware/imx/svc/seco.h index 56119e3380a2..a9176330f8a7 100644 --- a/include/linux/firmware/imx/svc/seco.h +++ b/include/linux/firmware/imx/svc/seco.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2020 NXP + * Copyright 2020, 2024 NXP * * Header file containing the public API for the System Controller (SC) * Security Controller (SECO) function. @@ -42,10 +42,6 @@ int imx_sc_seco_secvio_config(struct imx_sc_ipc *ipc, u8 id, u8 access, u32 *data4, u8 size); int imx_sc_seco_secvio_dgo_config(struct imx_sc_ipc *ipc, u8 id, u8 access, u32 *data); -int imx_scu_init_fw(struct device *dev); -int imx_scu_sec_mem_cfg(struct file *fp, uint32_t offset, uint32_t size); -int imx_scu_mem_access(struct file *fp); -int imx_scu_signed_msg(struct file *fp, uint8_t *msg, uint32_t size, uint32_t *error); #else /* IS_ENABLED(CONFIG_IMX_SCU) */ static inline int imx_sc_seco_build_info(struct imx_sc_ipc *ipc, uint32_t *version, @@ -81,29 +77,6 @@ int imx_sc_seco_secvio_dgo_config(struct imx_sc_ipc *ipc, u8 id, u8 access, return -EOPNOTSUPP; } -static inline -int imx_scu_init_fw(struct device *dev) -{ - return -EOPNOTSUPP; -} - -static inline -int imx_scu_sec_mem_cfg(struct file *fp, uint32_t offset, uint32_t size) -{ - return -EOPNOTSUPP; -} - -static inline -int imx_scu_signed_msg(struct file *fp, uint8_t *msg, uint32_t size, uint32_t *error) -{ - return -EOPNOTSUPP; -} - -static inline -int imx_scu_mem_access(struct file *fp)//device *dev) -{ - return -EOPNOTSUPP; -} #endif /* IS_ENABLED(CONFIG_IMX_SCU) */ #endif /* _SC_SECO_API_H */ diff --git a/include/linux/firmware/imx/v2x_base_msg.h b/include/linux/firmware/imx/v2x_base_msg.h deleted file mode 100644 index 116ba327236e..000000000000 --- a/include/linux/firmware/imx/v2x_base_msg.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright 2021-2023 NXP - * - * Header file for the ELE Base API(s). - */ - -#ifndef V2X_BASE_MSG_H -#define V2X_BASE_MSG_H - -#include - -#define WORD_SZ 4 - -#define V2X_START_RNG_REQ 0x0E -#define V2X_START_RNG_REQ_MSG_SZ 0x04 -#define V2X_START_RNG_RSP_MSG_SZ 0x0C - -int v2x_start_rng(struct device *dev); -#endif