diff options
author | Franck LENORMAND <franck.lenormand@nxp.com> | 2020-03-04 13:20:05 +0100 |
---|---|---|
committer | Franck LENORMAND <franck.lenormand@nxp.com> | 2020-03-13 17:11:58 +0100 |
commit | 2ccb9a596aab4d465eb82e3b7e0d153e9f54bd7c (patch) | |
tree | e41dd375fda53be6894fe56fe321ba3c24b142ce | |
parent | ccf07c0822eb0d9fdd0251d92fb21a52a9be1ef0 (diff) |
SSI-87: firmware: imx: Add APIs required for secvio
The Security Violation module requires SC API for the SECO, RM, MISC
and IRQ.
This patch does:
- imx-scu-irq: Allow reuse of imx_scu_irq_get_status
- seco:
- Add imx_sc_seco_secvio_enable
- Add imx_sc_seco_secvio_config
- Add imx_sc_seco_secvio_dgo_config
Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
-rw-r--r-- | drivers/firmware/imx/imx-scu-irq.c | 42 | ||||
-rw-r--r-- | drivers/firmware/imx/seco.c | 187 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxc.c | 1 | ||||
-rw-r--r-- | include/dt-bindings/firmware/imx/rsrc.h | 3 | ||||
-rw-r--r-- | include/linux/firmware/imx/sci.h | 4 | ||||
-rw-r--r-- | include/linux/firmware/imx/svc/seco.h | 30 |
6 files changed, 251 insertions, 16 deletions
diff --git a/drivers/firmware/imx/imx-scu-irq.c b/drivers/firmware/imx/imx-scu-irq.c index d9b8f8aeb08d..369621c14105 100644 --- a/drivers/firmware/imx/imx-scu-irq.c +++ b/drivers/firmware/imx/imx-scu-irq.c @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2019 NXP + * Copyright 2019-2020 NXP * * Implementation of the SCU IRQ functions using MU. * */ #include <dt-bindings/firmware/imx/rsrc.h> -#include <linux/firmware/imx/ipc.h> +#include <linux/firmware/imx/sci.h> #include <linux/mailbox_client.h> #include <linux/suspend.h> @@ -65,29 +65,18 @@ static int imx_scu_irq_notifier_call_chain(unsigned long status, u8 *group) static void imx_scu_irq_work_handler(struct work_struct *work) { - struct imx_sc_msg_irq_get_status msg; - struct imx_sc_rpc_msg *hdr = &msg.hdr; u32 irq_status; int ret; u8 i; for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) { - hdr->ver = IMX_SC_RPC_VERSION; - hdr->svc = IMX_SC_RPC_SVC_IRQ; - hdr->func = IMX_SC_IRQ_FUNC_STATUS; - hdr->size = 2; - - msg.data.req.resource = mu_resource_id; - msg.data.req.group = i; - - ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true); + ret = imx_scu_irq_get_status(i, &irq_status); if (ret) { pr_err("get irq group %d status failed, ret %d\n", i, ret); return; } - irq_status = msg.data.resp.status; if (!irq_status) continue; @@ -96,6 +85,31 @@ static void imx_scu_irq_work_handler(struct work_struct *work) } } +int imx_scu_irq_get_status(u8 group, u32 *irq_status) +{ + struct imx_sc_msg_irq_get_status msg; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = IMX_SC_RPC_SVC_IRQ; + hdr->func = IMX_SC_IRQ_FUNC_STATUS; + hdr->size = 2; + + msg.data.req.resource = mu_resource_id; + msg.data.req.group = group; + + ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true); + if (ret) + return ret; + + if (irq_status) + *irq_status = msg.data.resp.status; + + return 0; +} +EXPORT_SYMBOL(imx_scu_irq_get_status); + int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable) { struct imx_sc_msg_irq_enable msg; diff --git a/drivers/firmware/imx/seco.c b/drivers/firmware/imx/seco.c index a24037f3354f..7f71b1d7f022 100644 --- a/drivers/firmware/imx/seco.c +++ b/drivers/firmware/imx/seco.c @@ -60,3 +60,190 @@ int imx_sc_seco_sab_msg(struct imx_sc_ipc *ipc, u64 smsg_addr) return ret; } EXPORT_SYMBOL(imx_sc_seco_sab_msg); + +int imx_sc_seco_secvio_enable(struct imx_sc_ipc *ipc) +{ + struct imx_sc_rpc_msg msg; + struct imx_sc_rpc_msg *hdr = &msg; + int ret; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = (uint8_t)IMX_SC_RPC_SVC_SECO; + hdr->func = (uint8_t)IMX_SC_SECO_FUNC_SECVIO_ENABLE; + hdr->size = 1; + + ret = imx_scu_call_rpc(ipc, &msg, true); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(imx_sc_seco_secvio_enable); + +struct imx_sc_msg_req_seco_config { + struct imx_sc_rpc_msg hdr; + u32 data0; + u32 data1; + u32 data2; + u32 data3; + u32 data4; + u8 id; + u8 access; + u8 size; +} __packed __aligned(4); + +struct imx_sc_msg_resp_seco_config { + struct imx_sc_rpc_msg hdr; + u32 data0; + u32 data1; + u32 data2; + u32 data3; + u32 data4; +} __packed; + +int imx_sc_seco_secvio_config(struct imx_sc_ipc *ipc, u8 id, u8 access, + u32 *data0, u32 *data1, u32 *data2, u32 *data3, + u32 *data4, u8 size) +{ + struct imx_sc_msg_req_seco_config msg; + struct imx_sc_msg_resp_seco_config *resp; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; + + if (!ipc) + return -EINVAL; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = (uint8_t)IMX_SC_RPC_SVC_SECO; + hdr->func = (uint8_t)IMX_SC_SECO_FUNC_SECVIO_CONFIG; + hdr->size = 7; + + /* Check the pointers on data are valid and set it if doing a write */ + switch (size) { + case 5: + if (data4) { + if (access) + msg.data4 = *data4; + } else { + return -EINVAL; + } + /* fallthrough */ + case 4: + if (data3) { + if (access) + msg.data3 = *data3; + } else { + return -EINVAL; + } + /* fallthrough */ + case 3: + if (data2) { + if (access) + msg.data2 = *data2; + } else { + return -EINVAL; + } + /* fallthrough */ + case 2: + if (data1) { + if (access) + msg.data1 = *data1; + } else { + return -EINVAL; + } + /* fallthrough */ + case 1: + if (data0) { + if (access) + msg.data0 = *data0; + } else { + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + msg.id = id; + msg.access = access; + msg.size = size; + + ret = imx_scu_call_big_rpc(ipc, &msg, true); + if (ret) + return ret; + + resp = (struct imx_sc_msg_resp_seco_config *)&msg; + + /* Pointers already checked so we just copy the data if reading */ + if (!access) + switch (size) { + case 5: + *data4 = resp->data4; + /* fallthrough */ + case 4: + *data3 = resp->data3; + /* fallthrough */ + case 3: + *data2 = resp->data2; + /* fallthrough */ + case 2: + *data1 = resp->data1; + /* fallthrough */ + case 1: + *data0 = resp->data0; + } + + return 0; +} +EXPORT_SYMBOL(imx_sc_seco_secvio_config); + +struct imx_sc_msg_req_seco_dgo_config { + struct imx_sc_rpc_msg hdr; + u32 data; + u8 id; + u8 access; +} __packed __aligned(4); + +struct imx_sc_msg_resp_seco_dgo_config { + struct imx_sc_rpc_msg hdr; + u32 data; +} __packed; + +int imx_sc_seco_secvio_dgo_config(struct imx_sc_ipc *ipc, u8 id, u8 access, + u32 *data) +{ + struct imx_sc_msg_req_seco_dgo_config msg; + struct imx_sc_msg_resp_seco_dgo_config *resp; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; + + if (!ipc) + return -EINVAL; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = (uint8_t)IMX_SC_RPC_SVC_SECO; + hdr->func = (uint8_t)IMX_SC_SECO_FUNC_SECVIO_DGO_CONFIG; + hdr->size = 3; + + if (access) { + if (data) + msg.data = *data; + else + return -EINVAL; + } + + msg.access = access; + msg.id = id; + + ret = imx_scu_call_rpc(ipc, &msg, true); + if (ret) + return ret; + + resp = (struct imx_sc_msg_resp_seco_dgo_config *)&msg; + + if (!access && data) + *data = resp->data; + + return 0; +} +EXPORT_SYMBOL(imx_sc_seco_secvio_dgo_config); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 1844dcc59443..3967edc3f156 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -28,7 +28,6 @@ #define IMX_SC_PAD_FUNC_GET_WAKEUP 9 #define IMX_SC_PAD_FUNC_SET_WAKEUP 4 #define IMX_SC_PAD_WAKEUP_OFF 0 -#define IMX_SC_IRQ_GROUP_WAKE 3 #define IMX_SC_IRQ_PAD (1 << 1) #endif diff --git a/include/dt-bindings/firmware/imx/rsrc.h b/include/dt-bindings/firmware/imx/rsrc.h index cfae34a7611c..126760ab3b11 100644 --- a/include/dt-bindings/firmware/imx/rsrc.h +++ b/include/dt-bindings/firmware/imx/rsrc.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Freescale Semiconductor, Inc. - * Copyright 2017-2018 NXP + * Copyright 2017-2018,2020 NXP */ #ifndef __DT_BINDINGS_RSCRC_IMX_H @@ -51,6 +51,7 @@ #define IMX_SC_R_DC_1_BLIT2 38 #define IMX_SC_R_DC_1_BLIT_OUT 39 #define IMX_SC_R_DC_1_WARP 42 +#define IMX_SC_R_SECVIO 44 #define IMX_SC_R_DC_1_VIDEO0 45 #define IMX_SC_R_DC_1_VIDEO1 46 #define IMX_SC_R_DC_1_FRAC0 47 diff --git a/include/linux/firmware/imx/sci.h b/include/linux/firmware/imx/sci.h index 5d5e3094181e..e749594436bb 100644 --- a/include/linux/firmware/imx/sci.h +++ b/include/linux/firmware/imx/sci.h @@ -17,8 +17,12 @@ #include <linux/firmware/imx/svc/rm.h> #include <linux/firmware/imx/svc/seco.h> +#define IMX_SC_IRQ_GROUP_WAKE 3U /* Wakeup interrupts */ +#define IMX_SC_IRQ_SECVIO BIT(6) /* Security violation */ + int imx_scu_enable_general_irq_channel(struct device *dev); int imx_scu_irq_register_notifier(struct notifier_block *nb); int imx_scu_irq_unregister_notifier(struct notifier_block *nb); int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable); +int imx_scu_irq_get_status(u8 group, u32 *irq_status); #endif /* _SC_SCI_H */ diff --git a/include/linux/firmware/imx/svc/seco.h b/include/linux/firmware/imx/svc/seco.h index 00480b32ac63..d0dd803a1a52 100644 --- a/include/linux/firmware/imx/svc/seco.h +++ b/include/linux/firmware/imx/svc/seco.h @@ -23,12 +23,21 @@ enum imx_sc_seco_func { IMX_SC_SECO_FUNC_UNKNOWN = 0, IMX_SC_SECO_FUNC_BUILD_INFO = 16, IMX_SC_SECO_FUNC_SAB_MSG = 23, + IMX_SC_SECO_FUNC_SECVIO_ENABLE = 25, + IMX_SC_SECO_FUNC_SECVIO_CONFIG = 26, + IMX_SC_SECO_FUNC_SECVIO_DGO_CONFIG = 27, }; #if IS_ENABLED(CONFIG_IMX_SCU) int imx_sc_seco_build_info(struct imx_sc_ipc *ipc, uint32_t *version, uint32_t *commit); int imx_sc_seco_sab_msg(struct imx_sc_ipc *ipc, u64 smsg_addr); +int imx_sc_seco_secvio_enable(struct imx_sc_ipc *ipc); +int imx_sc_seco_secvio_config(struct imx_sc_ipc *ipc, u8 id, u8 access, + u32 *data0, u32 *data1, u32 *data2, u32 *data3, + u32 *data4, u8 size); +int imx_sc_seco_secvio_dgo_config(struct imx_sc_ipc *ipc, u8 id, u8 access, + u32 *data); #else /* IS_ENABLED(CONFIG_IMX_SCU) */ static inline int imx_sc_seco_build_info(struct imx_sc_ipc *ipc, uint32_t *version, @@ -42,6 +51,27 @@ int imx_sc_seco_sab_msg(struct imx_sc_ipc *ipc, u64 smsg_addr) { return -EOPNOTSUPP; } + +static inline +int imx_sc_seco_secvio_enable(struct imx_sc_ipc *ipc) +{ + return -EOPNOTSUPP; +} + +static inline +int imx_sc_seco_secvio_config(struct imx_sc_ipc *ipc, u8 id, u8 access, + u32 *data0, u32 *data1, u32 *data2, u32 *data3, + u32 *data4, u8 size) +{ + return -EOPNOTSUPP; +} + +static inline +int imx_sc_seco_secvio_dgo_config(struct imx_sc_ipc *ipc, u8 id, u8 access, + u32 *data) +{ + return -EOPNOTSUPP; +} #endif /* IS_ENABLED(CONFIG_IMX_SCU) */ #endif /* _SC_SECO_API_H */ |