mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2026-01-27 12:35:36 +01:00
LF-13910-7: drivers: firmware: imx: add support for i.MX95 soc
add support for i.MX95 soc Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com> Acked-by: Rahul Kumar Yadav <rahulkumar.yadav@nxp.com> Acked-by: Vabhav Sharma <vabhav.sharma@nxp.com> Acked-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com> Reviewed-by: Gaurav Jain <gaurav.jain@nxp.com> Acked-by: Jason Liu <jason.hui.liu@nxp.com>
This commit is contained in:
parent
b47a70ecb1
commit
9e7d5cc9f6
|
|
@ -48,7 +48,7 @@ config IMX_SEC_ENCLAVE
|
|||
|
||||
help
|
||||
It is possible to use APIs exposed by the iMX Secure Enclave HW IP called:
|
||||
- EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93),
|
||||
- EdgeLock Enclave Firmware (for i.MX8ULP, i.MX93, i.MX95),
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o imx-scu-irq.o rm.o imx-scu-soc.o seco
|
|||
obj-${CONFIG_IMX_SCMI_MISC_CONTROL} += sm-misc.o
|
||||
obj-$(CONFIG_IMX_SCMI_BBM_CONTROL) += sm-bbm.o
|
||||
obj-$(CONFIG_IMX_ISPMU) += isp-mu.o
|
||||
sec_enclave-objs = se_ctrl.o ele_common.o ele_base_msg.o ele_fw_api.o
|
||||
sec_enclave-objs = se_ctrl.o ele_common.o ele_base_msg.o ele_fw_api.o v2x_base_msg.o v2x_common.o
|
||||
obj-${CONFIG_IMX_SEC_ENCLAVE} += sec_enclave.o
|
||||
sec_enclave-${CONFIG_IMX_ELE_TRNG} += ele_trng.o
|
||||
|
|
|
|||
|
|
@ -702,3 +702,53 @@ int imx_se_voltage_change_req(void *se_if_data, bool start)
|
|||
return ele_voltage_change_req((struct se_if_priv *)se_if_data, start);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_se_voltage_change_req);
|
||||
|
||||
int ele_get_v2x_fw_state(struct se_if_priv *priv, uint32_t *state)
|
||||
{
|
||||
struct se_api_msg *tx_msg __free(kfree) = NULL;
|
||||
struct se_api_msg *rx_msg __free(kfree) = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!priv) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
tx_msg = kzalloc(ELE_GET_STATE_REQ_SZ, GFP_KERNEL);
|
||||
if (!tx_msg) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rx_msg = kzalloc(ELE_GET_STATE_RSP_SZ, GFP_KERNEL);
|
||||
if (!rx_msg) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = se_fill_cmd_msg_hdr(priv,
|
||||
(struct se_msg_hdr *)&tx_msg->header,
|
||||
ELE_GET_STATE,
|
||||
ELE_GET_STATE_REQ_SZ,
|
||||
true);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ret = ele_msg_send_rcv(priv->priv_dev_ctx,
|
||||
tx_msg,
|
||||
ELE_GET_STATE_REQ_SZ,
|
||||
rx_msg,
|
||||
ELE_GET_STATE_RSP_SZ);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
ret = se_val_rsp_hdr_n_status(priv,
|
||||
rx_msg,
|
||||
ELE_GET_STATE,
|
||||
ELE_GET_STATE_RSP_SZ,
|
||||
true);
|
||||
if (!ret)
|
||||
*state = 0xFF & rx_msg->data[1];
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,10 @@ struct ele_dev_info {
|
|||
#define ELE_VOLT_CHANGE_REQ_MSG_SZ 0x4
|
||||
#define ELE_VOLT_CHANGE_RSP_MSG_SZ 0x8
|
||||
|
||||
#define ELE_GET_STATE 0xB2
|
||||
#define ELE_GET_STATE_REQ_SZ 0x04
|
||||
#define ELE_GET_STATE_RSP_SZ 0x10
|
||||
|
||||
int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info);
|
||||
int ele_fetch_soc_info(struct se_if_priv *priv, void *data);
|
||||
int ele_ping(struct se_if_priv *priv);
|
||||
|
|
@ -120,4 +124,5 @@ int ele_write_fuse(struct se_if_priv *priv, u16 fuse_index,
|
|||
int ele_voltage_change_req(struct se_if_priv *priv, bool start);
|
||||
int read_common_fuse(struct se_if_priv *priv,
|
||||
u16 fuse_id, u32 *value);
|
||||
int ele_get_v2x_fw_state(struct se_if_priv *priv, uint32_t *state);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
* Copyright 2024-2025 NXP
|
||||
*/
|
||||
|
||||
#include <uapi/linux/se_ioctl.h>
|
||||
|
||||
#include "ele_base_msg.h"
|
||||
#include "ele_common.h"
|
||||
#include "v2x_base_msg.h"
|
||||
|
||||
extern u32 se_rcv_msg_timeout;
|
||||
|
||||
|
|
@ -194,6 +197,12 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
|
|||
header = msg;
|
||||
rx_msg_sz = header->size << 2;
|
||||
|
||||
if (priv->if_defs->se_if_type == SE_TYPE_ID_V2X_DBG &&
|
||||
header->tag == V2X_DBG_MU_MSG_RSP_TAG) {
|
||||
header->tag = priv->if_defs->rsp_tag;
|
||||
header->ver = priv->if_defs->base_api_ver;
|
||||
}
|
||||
|
||||
/* Incoming command: wake up the receiver if any. */
|
||||
if (header->tag == priv->if_defs->cmd_tag) {
|
||||
se_clbk_hdl = &priv->cmd_receiver_clbk_hdl;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "ele_fw_api.h"
|
||||
#include "ele_trng.h"
|
||||
#include "se_ctrl.h"
|
||||
#include "v2x_base_msg.h"
|
||||
#include "v2x_common.h"
|
||||
|
||||
#define MAX_SOC_INFO_DATA_SZ 256
|
||||
#define MBOX_TX_NAME "tx"
|
||||
|
|
@ -61,6 +63,7 @@ struct se_if_node_info {
|
|||
u8 se_if_did;
|
||||
struct se_if_defines if_defs;
|
||||
u8 *pool_name;
|
||||
u32 mu_buff_size;
|
||||
bool reserved_dma_ranges;
|
||||
int (*start_rng)(struct se_if_priv *priv);
|
||||
int (*init_trng)(struct se_if_priv *priv);
|
||||
|
|
@ -112,6 +115,7 @@ static struct se_if_node_info_list imx8ulp_info = {
|
|||
{
|
||||
.se_if_id = 0,
|
||||
.se_if_did = 7,
|
||||
.mu_buff_size = 0,
|
||||
.if_defs = {
|
||||
.se_if_type = SE_TYPE_ID_HSM,
|
||||
.se_instance_id = 0,
|
||||
|
|
@ -139,6 +143,7 @@ static struct se_if_node_info_list imx93_info = {
|
|||
.info = {
|
||||
{
|
||||
.se_if_id = 0,
|
||||
.mu_buff_size = 0,
|
||||
.if_defs = {
|
||||
.se_if_type = SE_TYPE_ID_HSM,
|
||||
.se_instance_id = 0,
|
||||
|
|
@ -157,9 +162,97 @@ static struct se_if_node_info_list imx93_info = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct se_if_node_info_list imx95_info = {
|
||||
.num_mu = 4,
|
||||
.soc_id = SOC_ID_OF_IMX95,
|
||||
.soc_register = false,
|
||||
.se_fetch_soc_info = ele_fetch_soc_info,
|
||||
.load_hsm_fw = {
|
||||
.prim_fw_nm_in_rfs = NULL,
|
||||
.seco_fw_nm_in_rfs = NULL,
|
||||
.is_fw_loaded = true,
|
||||
.handle_susp_resm = false,
|
||||
},
|
||||
.info = {
|
||||
{
|
||||
.se_if_id = 0,
|
||||
.mu_buff_size = 0,
|
||||
.if_defs = {
|
||||
.se_if_type = SE_TYPE_ID_HSM,
|
||||
.se_instance_id = 0,
|
||||
.cmd_tag = 0x17,
|
||||
.rsp_tag = 0xe1,
|
||||
.success_tag = ELE_SUCCESS_IND,
|
||||
.base_api_ver = MESSAGING_VERSION_6,
|
||||
.fw_api_ver = MESSAGING_VERSION_7,
|
||||
},
|
||||
.reserved_dma_ranges = false,
|
||||
.start_rng = ele_start_rng,
|
||||
.init_trng = ele_trng_init,
|
||||
.se_if_early_init = NULL,
|
||||
.se_if_late_init = v2x_late_init,
|
||||
},
|
||||
{
|
||||
.se_if_id = 1,
|
||||
.mu_buff_size = 0,
|
||||
.if_defs = {
|
||||
.se_if_type = SE_TYPE_ID_V2X_DBG,
|
||||
.se_instance_id = 0,
|
||||
.cmd_tag = 0x1a,
|
||||
.rsp_tag = 0xe4,
|
||||
.success_tag = ELE_SUCCESS_IND,
|
||||
.base_api_ver = MESSAGING_VERSION_2,
|
||||
.fw_api_ver = MESSAGING_VERSION_2,
|
||||
},
|
||||
.reserved_dma_ranges = false,
|
||||
.start_rng = v2x_start_rng,
|
||||
.init_trng = NULL,
|
||||
.se_if_early_init = v2x_early_init,
|
||||
.se_if_late_init = NULL,
|
||||
},
|
||||
{
|
||||
.se_if_id = 2,
|
||||
.mu_buff_size = 16,
|
||||
.if_defs = {
|
||||
.se_if_type = SE_TYPE_ID_V2X_SV,
|
||||
.se_instance_id = 0,
|
||||
.cmd_tag = 0x18,
|
||||
.rsp_tag = 0xe2,
|
||||
.success_tag = ELE_SUCCESS_IND,
|
||||
.base_api_ver = MESSAGING_VERSION_2,
|
||||
.fw_api_ver = MESSAGING_VERSION_2,
|
||||
},
|
||||
.reserved_dma_ranges = false,
|
||||
.start_rng = NULL,
|
||||
.init_trng = NULL,
|
||||
.se_if_early_init = v2x_early_init,
|
||||
.se_if_late_init = NULL,
|
||||
},
|
||||
{
|
||||
.se_if_id = 3,
|
||||
.mu_buff_size = 256,
|
||||
.if_defs = {
|
||||
.se_if_type = SE_TYPE_ID_V2X_SHE,
|
||||
.se_instance_id = 0,
|
||||
.cmd_tag = 0x1a,
|
||||
.rsp_tag = 0xe4,
|
||||
.success_tag = ELE_SUCCESS_IND,
|
||||
.base_api_ver = MESSAGING_VERSION_2,
|
||||
.fw_api_ver = MESSAGING_VERSION_2,
|
||||
},
|
||||
.reserved_dma_ranges = false,
|
||||
.start_rng = NULL,
|
||||
.init_trng = NULL,
|
||||
.se_if_early_init = v2x_early_init,
|
||||
.se_if_late_init = NULL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id se_match[] = {
|
||||
{ .compatible = "fsl,imx8ulp-se", .data = (void *)&imx8ulp_info},
|
||||
{ .compatible = "fsl,imx93-se", .data = (void *)&imx93_info},
|
||||
{ .compatible = "fsl,imx95-se", .data = (void *)&imx95_info},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
@ -303,6 +396,8 @@ void *imx_get_se_data_info(u32 soc_id, u32 idx)
|
|||
info_list = &imx8ulp_info; break;
|
||||
case SOC_ID_OF_IMX93:
|
||||
info_list = &imx93_info; break;
|
||||
case SOC_ID_OF_IMX95:
|
||||
info_list = &imx95_info; break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -665,8 +760,12 @@ static int se_dev_ctx_cpy_out_data(struct se_if_device_ctx *dev_ctx)
|
|||
}
|
||||
}
|
||||
|
||||
if (b_desc->shared_buf_ptr)
|
||||
memset(b_desc->shared_buf_ptr, 0, b_desc->size);
|
||||
if (b_desc->shared_buf_ptr) {
|
||||
if (dev_ctx->priv->mu_mem.pos)
|
||||
memset_io(b_desc->shared_buf_ptr, 0, b_desc->size);
|
||||
else
|
||||
memset(b_desc->shared_buf_ptr, 0, b_desc->size);
|
||||
}
|
||||
|
||||
list_del(&b_desc->link);
|
||||
kfree(b_desc);
|
||||
|
|
@ -689,10 +788,13 @@ static void se_dev_ctx_shared_mem_cleanup(struct se_if_device_ctx *dev_ctx)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
list_for_each_entry_safe(b_desc, temp,
|
||||
pending_lists[i], link) {
|
||||
if (b_desc->shared_buf_ptr)
|
||||
memset(b_desc->shared_buf_ptr, 0, b_desc->size);
|
||||
list_for_each_entry_safe(b_desc, temp, pending_lists[i], link) {
|
||||
if (b_desc->shared_buf_ptr) {
|
||||
if (dev_ctx->priv->mu_mem.pos)
|
||||
memset_io(b_desc->shared_buf_ptr, 0, b_desc->size);
|
||||
else
|
||||
memset(b_desc->shared_buf_ptr, 0, b_desc->size);
|
||||
}
|
||||
|
||||
list_del(&b_desc->link);
|
||||
kfree(b_desc);
|
||||
|
|
@ -928,6 +1030,7 @@ static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
|
|||
|
||||
exit:
|
||||
se_dev_ctx_shared_mem_cleanup(dev_ctx);
|
||||
priv->mu_mem.pos = 0;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &cmd_snd_rcv_rsp_info,
|
||||
sizeof(cmd_snd_rcv_rsp_info))) {
|
||||
|
|
@ -1014,8 +1117,11 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
|
|||
goto copy;
|
||||
}
|
||||
|
||||
/* No specific requirement for this buffer. */
|
||||
shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem;
|
||||
/* Select the shared memory to be used for this buffer. */
|
||||
if (io.flags & SE_IO_BUF_FLAGS_USE_MU_BUF)
|
||||
shared_mem = &dev_ctx->priv->mu_mem;
|
||||
else
|
||||
shared_mem = &dev_ctx->se_shared_mem_mgmt.non_secure_mem;
|
||||
|
||||
/* Check there is enough space in the shared memory. */
|
||||
dev_dbg(dev_ctx->priv->dev,
|
||||
|
|
@ -1038,7 +1144,11 @@ static int se_ioctl_setup_iobuf_handler(struct se_if_device_ctx *dev_ctx,
|
|||
shared_mem->pos += round_up(io.length, 8u);
|
||||
io.ele_addr = (u64)shared_mem->dma_addr + pos;
|
||||
|
||||
memset(shared_mem->ptr + pos, 0, io.length);
|
||||
if (dev_ctx->priv->mu_mem.pos)
|
||||
memset_io(shared_mem->ptr + pos, 0, io.length);
|
||||
else
|
||||
memset(shared_mem->ptr + pos, 0, io.length);
|
||||
|
||||
if ((io.flags & SE_IO_BUF_FLAGS_IS_INPUT) ||
|
||||
(io.flags & SE_IO_BUF_FLAGS_IS_IN_OUT)) {
|
||||
/*
|
||||
|
|
@ -1479,6 +1589,13 @@ static int se_if_probe(struct platform_device *pdev)
|
|||
priv->if_defs = &info->if_defs;
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
if (info->se_if_early_init) {
|
||||
/* start initializing ele fw */
|
||||
ret = info->se_if_early_init(priv);
|
||||
if (ret)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
list_add_tail(&priv->priv_data, &priv_data_list);
|
||||
|
||||
ret = devm_add_action(dev, se_if_probe_cleanup, pdev);
|
||||
|
|
@ -1501,6 +1618,12 @@ static int se_if_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto exit;
|
||||
|
||||
if (info->mu_buff_size) {
|
||||
/* TODO: to get func get_mu_buf(), part of imx-mailbox.c */
|
||||
priv->mu_mem.ptr = get_mu_buf(priv->tx_chan);
|
||||
priv->mu_mem.size = info->mu_buff_size;
|
||||
priv->mu_mem.dma_addr = (u64)priv->mu_mem.ptr;
|
||||
}
|
||||
mutex_init(&priv->se_if_cmd_lock);
|
||||
|
||||
init_completion(&priv->waiting_rsp_clbk_hdl.done);
|
||||
|
|
@ -1619,6 +1742,12 @@ static int se_suspend(struct device *dev)
|
|||
int ret = 0;
|
||||
|
||||
se_rcv_msg_timeout = SE_RCV_MSG_DEFAULT_TIMEOUT;
|
||||
|
||||
if (priv->if_defs->se_if_type == SE_TYPE_ID_V2X_DBG) {
|
||||
dev_err(dev, "V2X-FW: Suspend/resume not supported.");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
load_fw = get_load_fw_instance(priv);
|
||||
|
||||
if (load_fw->imem_mgmt)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#define RES_STATUS(x) FIELD_GET(0x000000ff, x)
|
||||
#define MAX_DATA_SIZE_PER_USER (65 * 1024)
|
||||
#define MAX_NVM_MSG_LEN (256)
|
||||
#define MESSAGING_VERSION_2 0x2
|
||||
#define MESSAGING_VERSION_6 0x6
|
||||
#define MESSAGING_VERSION_7 0x7
|
||||
#define NODE_NAME "secure-enclave"
|
||||
|
|
@ -130,6 +131,7 @@ struct se_if_priv {
|
|||
struct mbox_client se_mb_cl;
|
||||
struct mbox_chan *tx_chan, *rx_chan;
|
||||
|
||||
struct se_shared_mem mu_mem;
|
||||
struct gen_pool *mem_pool;
|
||||
const struct se_if_defines *if_defs;
|
||||
struct se_lg_fl_info lg_fl_info;
|
||||
|
|
|
|||
75
drivers/firmware/imx/v2x_base_msg.c
Normal file
75
drivers/firmware/imx/v2x_base_msg.c
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2024 NXP
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include "ele_common.h"
|
||||
#include "v2x_base_msg.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 se_if_priv *priv)
|
||||
{
|
||||
struct se_api_msg *tx_msg __free(kfree) = NULL;
|
||||
struct se_api_msg *rx_msg __free(kfree) = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!priv) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
tx_msg = kzalloc(V2X_START_RNG_REQ_MSG_SZ, GFP_KERNEL);
|
||||
if (!tx_msg) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rx_msg = kzalloc(V2X_START_RNG_RSP_MSG_SZ, GFP_KERNEL);
|
||||
if (!rx_msg) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = se_fill_cmd_msg_hdr(priv,
|
||||
(struct se_msg_hdr *)&tx_msg->header,
|
||||
V2X_START_RNG_REQ,
|
||||
V2X_START_RNG_REQ_MSG_SZ,
|
||||
true);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ret = ele_msg_send_rcv(priv->priv_dev_ctx,
|
||||
tx_msg,
|
||||
V2X_START_RNG_REQ_MSG_SZ,
|
||||
rx_msg,
|
||||
V2X_START_RNG_RSP_MSG_SZ);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
ret = se_val_rsp_hdr_n_status(priv,
|
||||
rx_msg,
|
||||
V2X_START_RNG_REQ,
|
||||
V2X_START_RNG_RSP_MSG_SZ,
|
||||
true);
|
||||
if (ret) {
|
||||
/* Initialization in progress for:
|
||||
* P-TRNG at bit 0
|
||||
* S-TRNG at bit 1
|
||||
* Any of the bit is set, it in progress.
|
||||
*/
|
||||
if (rx_msg->data[1] & 0x3)
|
||||
goto exit;
|
||||
|
||||
ret = -1;
|
||||
}
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
18
drivers/firmware/imx/v2x_base_msg.h
Normal file
18
drivers/firmware/imx/v2x_base_msg.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* Header file for the V2X Base API(s).
|
||||
*/
|
||||
|
||||
#ifndef V2X_BASE_MSG_H
|
||||
#define V2X_BASE_MSG_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#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 se_if_priv *priv);
|
||||
#endif
|
||||
90
drivers/firmware/imx/v2x_common.c
Normal file
90
drivers/firmware/imx/v2x_common.c
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2024 NXP
|
||||
*/
|
||||
|
||||
#include <linux/firmware/imx/se_api.h>
|
||||
#include <uapi/linux/se_ioctl.h>
|
||||
|
||||
#include "ele_base_msg.h"
|
||||
#include "ele_fw_api.h"
|
||||
#include "v2x_base_msg.h"
|
||||
#include "v2x_common.h"
|
||||
|
||||
static u32 v2x_fw_state;
|
||||
|
||||
#define V2X_FW_AUTH_DBG_COMPLETE 0x15
|
||||
#define V2X_FW_AUTH_NORM_COMPLETE 0x13
|
||||
|
||||
static bool is_v2x_fw_running(u32 v2x_fw_state)
|
||||
{
|
||||
if (v2x_fw_state == V2X_FW_AUTH_DBG_COMPLETE ||
|
||||
v2x_fw_state == V2X_FW_AUTH_NORM_COMPLETE)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int v2x_early_init(struct se_if_priv *priv)
|
||||
{
|
||||
struct se_if_priv *ele_priv;
|
||||
int ret = 0;
|
||||
|
||||
if (!is_v2x_fw_running(v2x_fw_state)) {
|
||||
ele_priv = imx_get_se_data_info(get_se_soc_id(priv), 0);
|
||||
if (!ele_priv) {
|
||||
ret = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ele_v2x_fw_authenticate(ele_priv, V2X_FW_IMG_DDR_ADDR);
|
||||
if (ret) {
|
||||
dev_err(ele_priv->dev,
|
||||
"failure: v2x fw loading.");
|
||||
ret = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ele_get_v2x_fw_state(ele_priv, &v2x_fw_state);
|
||||
if (ret)
|
||||
dev_warn(priv->dev, "Failed to fetch the v2x-fw-state via ELE.");
|
||||
|
||||
if (!is_v2x_fw_running(v2x_fw_state)) {
|
||||
dev_err(priv->dev,
|
||||
"failure: v2x fw state [0x%x]is not loaded.",
|
||||
v2x_fw_state);
|
||||
ret = -EPERM;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int v2x_late_init(struct se_if_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (priv->if_defs->se_if_type == SE_TYPE_ID_HSM) {
|
||||
ret = ele_init_fw(priv);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "ELE INIT FW failed.");
|
||||
ret = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
if (ele_get_v2x_fw_state(priv, &v2x_fw_state)) {
|
||||
dev_warn(priv->dev, "Failed to fetch the v2x-fw-state via ELE.");
|
||||
v2x_fw_state = V2X_FW_STATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
if (!is_v2x_fw_running(v2x_fw_state)) {
|
||||
if (ele_v2x_fw_authenticate(priv, V2X_FW_IMG_DDR_ADDR))
|
||||
dev_warn(priv->dev, "failure: v2x fw loading.");
|
||||
|
||||
if (ele_get_v2x_fw_state(priv, &v2x_fw_state)) {
|
||||
dev_warn(priv->dev, "Failed to fetch the v2x-fw-state via ELE.");
|
||||
v2x_fw_state = V2X_FW_STATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
17
drivers/firmware/imx/v2x_common.h
Normal file
17
drivers/firmware/imx/v2x_common.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2024 NXP
|
||||
*/
|
||||
|
||||
#ifndef __V2X_COMMON_H__
|
||||
#define __V2X_COMMON_H__
|
||||
|
||||
#include "se_ctrl.h"
|
||||
|
||||
#define V2X_FW_STATE_UNKNOWN 0x00
|
||||
#define V2X_FW_STATE_RUNNING 0x15
|
||||
|
||||
int v2x_early_init(struct se_if_priv *priv);
|
||||
int v2x_late_init(struct se_if_priv *priv);
|
||||
|
||||
#endif /*__V2X_COMMON_H__ */
|
||||
Loading…
Reference in New Issue
Block a user