[U-Boot] [PATCH 04/41] imx8: add IPC communication support between ACore and SCU
Peng Fan
peng.fan at nxp.com
Mon May 28 12:24:49 UTC 2018
The IPC communication is based on Message Unit(MU) between ACore
and SCU.
Add the lowlevel MU initialization, message send/receive code.
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
arch/arm/include/asm/arch-imx8/fsl_mu_hal.h | 54 +++++++++++++++
arch/arm/include/asm/arch-imx8/sci/sci.h | 39 +++++++++++
arch/arm/mach-imx/imx8/Makefile | 1 +
arch/arm/mach-imx/imx8/fsl_mu_hal.c | 28 ++++++++
arch/arm/mach-imx/imx8/sci/ipc.c | 100 ++++++++++++++++++++++++++++
5 files changed, 222 insertions(+)
create mode 100644 arch/arm/include/asm/arch-imx8/fsl_mu_hal.h
create mode 100644 arch/arm/include/asm/arch-imx8/sci/sci.h
create mode 100644 arch/arm/mach-imx/imx8/fsl_mu_hal.c
create mode 100644 arch/arm/mach-imx/imx8/sci/ipc.c
diff --git a/arch/arm/include/asm/arch-imx8/fsl_mu_hal.h b/arch/arm/include/asm/arch-imx8/fsl_mu_hal.h
new file mode 100644
index 0000000000..a7b9518604
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8/fsl_mu_hal.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ */
+
+#ifndef __FSL_MU_HAL_H__
+#define __FSL_MU_HAL_H__
+
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+struct mu_type {
+ u32 tr[4];
+ u32 rr[4];
+ u32 sr;
+ u32 cr;
+};
+
+#define MU_SR_GIP0_MASK BIT(31)
+#define MU_SR_RF0_MASK BIT(27)
+#define MU_SR_TE0_MASK BIT(23)
+#define MU_CR_GIE0_MASK BIT(31)
+#define MU_CR_RIE0_MASK BIT(27)
+#define MU_CR_TIE0_MASK BIT(23)
+#define MU_CR_GIR0_MASK BIT(19)
+
+#define MU_CR_GIEn_MASK 0xF0000000u
+#define MU_CR_RIEn_MASK 0x0F000000u
+#define MU_CR_TIEn_MASK 0x00F00000u
+#define MU_CR_GIRn_MASK 0x000F0000u
+#define MU_CR_Fn_MASK 0x7u
+#define MU_CR_NMI_MASK 0x8u
+
+#define MU_CR_GIRn_NMI_MASK (MU_CR_GIRn_MASK | MU_CR_NMI_MASK)
+
+#define MU_TR_COUNT 4
+#define MU_RR_COUNT 4
+
+static inline void mu_hal_init(struct mu_type *base)
+{
+ /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+ clrbits_le32(&base->cr, MU_CR_GIEn_MASK | MU_CR_RIEn_MASK |
+ MU_CR_TIEn_MASK | MU_CR_GIRn_MASK | MU_CR_Fn_MASK);
+}
+
+static inline void mu_hal_enablerxfullint(struct mu_type *base, u32 index)
+{
+ clrsetbits_le32(&base->cr, MU_CR_GIRn_NMI_MASK,
+ MU_CR_RIE0_MASK >> index);
+}
+
+void mu_hal_sendmsg(struct mu_type *base, u32 regindex, u32 msg);
+void mu_hal_receivemsg(struct mu_type *base, u32 regindex, u32 *msg);
+#endif /* __FSL_MU_HAL_H__ */
diff --git a/arch/arm/include/asm/arch-imx8/sci/sci.h b/arch/arm/include/asm/arch-imx8/sci/sci.h
new file mode 100644
index 0000000000..589dba0653
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8/sci/sci.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ */
+
+#ifndef _SC_SCI_H
+#define _SC_SCI_H
+
+/*!
+ * This type is used to declare a handle for an IPC communication
+ * channel. Its meaning is specific to the IPC implementation.
+ */
+typedef u64 sc_ipc_t;
+
+/*!
+ * This type is used to declare an ID for an IPC communication
+ * channel. Its meaning is specific to the IPC implementation.
+ */
+typedef u64 sc_ipc_id_t;
+
+#include <asm/arch/sci/types.h>
+#include <asm/arch/sci/ipc.h>
+#include <asm/arch/sci/svc/misc/api.h>
+#include <asm/arch/sci/svc/pad/api.h>
+#include <asm/arch/sci/svc/pm/api.h>
+#include <asm/arch/sci/svc/rm/api.h>
+#include <asm/arch/sci/svc/timer/api.h>
+
+#define MU_BASE_ADDR(id) (0x5D1B0000U + (id * 0x10000))
+
+#define SC_IPC_AP_CH0 (MU_BASE_ADDR(0))
+#define SC_IPC_AP_CH1 (MU_BASE_ADDR(1))
+#define SC_IPC_AP_CH2 (MU_BASE_ADDR(2))
+#define SC_IPC_AP_CH3 (MU_BASE_ADDR(3))
+#define SC_IPC_AP_CH4 (MU_BASE_ADDR(4))
+
+#define SC_IPC_CH SC_IPC_AP_CH1
+
+#endif
diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile
index cfb7e34653..8ae0518c16 100644
--- a/arch/arm/mach-imx/imx8/Makefile
+++ b/arch/arm/mach-imx/imx8/Makefile
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-y += fsl_mu_hal.o sci/ipc.o
obj-y += sci/svc/misc/rpc_clnt.o
obj-y += sci/svc/pad/rpc_clnt.o
obj-y += sci/svc/pm/rpc_clnt.o
diff --git a/arch/arm/mach-imx/imx8/fsl_mu_hal.c b/arch/arm/mach-imx/imx8/fsl_mu_hal.c
new file mode 100644
index 0000000000..87b8d5a355
--- /dev/null
+++ b/arch/arm/mach-imx/imx8/fsl_mu_hal.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <log.h>
+#include <asm/arch/fsl_mu_hal.h>
+
+void mu_hal_sendmsg(struct mu_type *base, u32 regindex, u32 msg)
+{
+ assert(regindex < MU_TR_COUNT);
+ u32 mask = MU_SR_TE0_MASK >> regindex;
+ /* Wait TX register to be empty. */
+ while (!(readl(&base->sr) & mask))
+ ;
+ writel(msg, &base->tr[regindex]);
+}
+
+void mu_hal_receivemsg(struct mu_type *base, u32 regindex, u32 *msg)
+{
+ assert(regindex < MU_TR_COUNT);
+ u32 mask = MU_SR_RF0_MASK >> regindex;
+
+ /* Wait RX register to be full. */
+ while (!(readl(&base->sr) & mask))
+ ;
+ *msg = readl(&base->rr[regindex]);
+}
diff --git a/arch/arm/mach-imx/imx8/sci/ipc.c b/arch/arm/mach-imx/imx8/sci/ipc.c
new file mode 100644
index 0000000000..7af10de027
--- /dev/null
+++ b/arch/arm/mach-imx/imx8/sci/ipc.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <asm/arch/fsl_mu_hal.h>
+#include <asm/arch/sci/sci.h>
+#include <asm/arch/sci/ipc.h>
+#include <asm/arch/sci/rpc.h>
+
+void sc_ipc_read(sc_ipc_t ipc, void *data)
+{
+ struct mu_type *base = (struct mu_type *)ipc;
+ sc_rpc_msg_t *msg = (sc_rpc_msg_t *)data;
+ u8 count = 0;
+
+ /* Check parms */
+ if (!base || !msg)
+ return;
+
+ /* Read first word */
+ mu_hal_receivemsg(base, 0, (u32 *)msg);
+ count++;
+
+ /* Check size */
+ if (msg->size > SC_RPC_MAX_MSG) {
+ *((u32 *)msg) = 0;
+ return;
+ }
+
+ /* Read remaining words */
+ while (count < msg->size) {
+ mu_hal_receivemsg(base, count % MU_RR_COUNT,
+ &msg->DATA.u32[count - 1]);
+ count++;
+ }
+}
+
+void sc_ipc_write(sc_ipc_t ipc, void *data)
+{
+ struct mu_type *base = (struct mu_type *)ipc;
+ sc_rpc_msg_t *msg = (sc_rpc_msg_t *)data;
+ u8 count = 0;
+
+ /* Check parms */
+ if (!base || !msg)
+ return;
+
+ /* Check size */
+ if (msg->size > SC_RPC_MAX_MSG)
+ return;
+
+ /* Write first word */
+ mu_hal_sendmsg(base, 0, *((u32 *)msg));
+ count++;
+
+ /* Write remaining words */
+ while (count < msg->size) {
+ mu_hal_sendmsg(base, count % MU_TR_COUNT,
+ msg->DATA.u32[count - 1]);
+ count++;
+ }
+}
+
+void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, sc_bool_t no_resp)
+{
+ sc_ipc_write(ipc, msg);
+ if (!no_resp)
+ sc_ipc_read(ipc, msg);
+}
+
+sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id)
+{
+ struct mu_type *base = (struct mu_type *)id;
+ u32 i;
+
+ /* Get MU base associated with IPC channel */
+ if (!ipc || !base)
+ return SC_ERR_IPC;
+
+ /* Init MU */
+ mu_hal_init(base);
+
+ /* Enable all RX interrupts */
+ for (i = 0; i < MU_RR_COUNT; i++)
+ mu_hal_enablerxfullint(base, i);
+
+ /* Return MU address as handle */
+ *ipc = (sc_ipc_t)id;
+
+ return SC_ERR_NONE;
+}
+
+void sc_ipc_close(sc_ipc_t ipc)
+{
+ struct mu_type *base = (struct mu_type *)ipc;
+
+ if (base)
+ mu_hal_init(base);
+}
--
2.14.1
More information about the U-Boot
mailing list