Added an API to read the common fuses only accessible to enclave-firmware. Signed-off-by: Pankaj Gupta <pankaj.gupta@xxxxxxx> --- drivers/firmware/imx/ele_base_msg.c | 80 +++++++++++++++++++++++ include/linux/firmware/imx/ele_base_msg.h | 7 ++ 2 files changed, 87 insertions(+) diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c index b19ab8abeeb8..9785fcdcc29d 100644 --- a/drivers/firmware/imx/ele_base_msg.c +++ b/drivers/firmware/imx/ele_base_msg.c @@ -190,3 +190,83 @@ int ele_service_swap(struct device *dev, return -EINVAL; } + +static int read_otp_uniq_id(struct ele_mu_priv *priv, u32 *value) +{ + unsigned int tag, command, size, ver, status; + + tag = MSG_TAG(priv->rx_msg.header); + command = MSG_COMMAND(priv->rx_msg.header); + size = MSG_SIZE(priv->rx_msg.header); + ver = MSG_VER(priv->rx_msg.header); + status = RES_STATUS(priv->rx_msg.data[0]); + + if (tag == priv->rsp_tag && + command == ELE_READ_FUSE_REQ && + size == ELE_READ_FUSE_RSP_MSG_SZ && + ver == ELE_BASE_API_VERSION && + status == priv->success_tag) { + 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]; + return 0; + } + + return -EINVAL; +} + +static int read_fuse_word(struct ele_mu_priv *priv, u32 *value) +{ + unsigned int tag, command, size, ver, status; + + tag = MSG_TAG(priv->rx_msg.header); + command = MSG_COMMAND(priv->rx_msg.header); + size = MSG_SIZE(priv->rx_msg.header); + ver = MSG_VER(priv->rx_msg.header); + status = RES_STATUS(priv->rx_msg.data[0]); + + if (tag == priv->rsp_tag && + command == ELE_READ_FUSE_REQ && + size == ELE_READ_FUSE_REQ_MSG_SZ && + ver == ELE_BASE_API_VERSION && + status == priv->success_tag) { + value[0] = priv->rx_msg.data[1]; + return 0; + } + + return -EINVAL; +} + +int read_common_fuse(struct device *dev, + uint16_t fuse_id, u32 *value) +{ + struct ele_mu_priv *priv = dev_get_drvdata(dev); + int err; + + err = plat_fill_cmd_msg_hdr(priv, + (struct mu_hdr *)&priv->tx_msg.header, + ELE_READ_FUSE_REQ, 8); + if (err) { + pr_err("Error: plat_fill_cmd_msg_hdr failed.\n"); + return err; + } + + priv->tx_msg.data[0] = fuse_id; + err = imx_ele_msg_send_rcv(priv); + if (err < 0) + return err; + + switch (fuse_id) { + case OTP_UNIQ_ID: + err = read_otp_uniq_id(priv, value); + break; + default: + err = read_fuse_word(priv, value); + break; + } + + return err; +} +EXPORT_SYMBOL_GPL(read_common_fuse); + diff --git a/include/linux/firmware/imx/ele_base_msg.h b/include/linux/firmware/imx/ele_base_msg.h index 6fbea7a8d7c9..99a135c21f56 100644 --- a/include/linux/firmware/imx/ele_base_msg.h +++ b/include/linux/firmware/imx/ele_base_msg.h @@ -47,6 +47,13 @@ #define ELE_IMEM_EXPORT 0x1 #define ELE_IMEM_IMPORT 0x2 +#define ELE_READ_FUSE_REQ 0x97 +#define ELE_READ_FUSE_RSP_MSG_SZ 0x07 +#define ELE_READ_FUSE_REQ_MSG_SZ 0x03 + +#define OTP_UNIQ_ID 0x01 +#define OTFAD_CONFIG 0x2 + #define ELE_BASE_API_VERSION 0x6 int ele_get_info(struct device *dev, phys_addr_t addr, u32 data_size); -- 2.34.1