summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranck LENORMAND <franck.lenormand@nxp.com>2020-03-04 13:20:05 +0100
committerFranck LENORMAND <franck.lenormand@nxp.com>2020-03-13 17:11:58 +0100
commit2ccb9a596aab4d465eb82e3b7e0d153e9f54bd7c (patch)
treee41dd375fda53be6894fe56fe321ba3c24b142ce
parentccf07c0822eb0d9fdd0251d92fb21a52a9be1ef0 (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.c42
-rw-r--r--drivers/firmware/imx/seco.c187
-rw-r--r--drivers/gpio/gpio-mxc.c1
-rw-r--r--include/dt-bindings/firmware/imx/rsrc.h3
-rw-r--r--include/linux/firmware/imx/sci.h4
-rw-r--r--include/linux/firmware/imx/svc/seco.h30
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 */