summaryrefslogtreecommitdiff
path: root/chip/mt8192_scp
diff options
context:
space:
mode:
authorTzung-Bi Shih <tzungbi@chromium.org>2020-06-30 09:45:43 +0800
committerCommit Bot <commit-bot@chromium.org>2020-07-14 09:14:11 +0000
commit5c6eac1194777f8530d030e586e94c26c545d6df (patch)
tree482be6af6dbfc4d27d9db8004436d3d22743c52e /chip/mt8192_scp
parent1f73f33656bafa76680be4375e3c9f362d5d5c19 (diff)
downloadchrome-ec-5c6eac1194777f8530d030e586e94c26c545d6df.tar.gz
chip/mt8192_scp: support IPI handler
Supports IPI handler which handles IPI messages from AP. BRANCH=none BUG=b:146213943 BUG=b:156223050 TEST=make BOARD=asurada_scp Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> Change-Id: Ie24ff872c94d79a5559248c64c5618659f6d028d Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2275711 Reviewed-by: Eric Yilun Lin <yllin@chromium.org>
Diffstat (limited to 'chip/mt8192_scp')
-rw-r--r--chip/mt8192_scp/build.mk6
-rw-r--r--chip/mt8192_scp/intc.c2
-rw-r--r--chip/mt8192_scp/ipi.c54
-rw-r--r--chip/mt8192_scp/ipi_chip.h25
-rw-r--r--chip/mt8192_scp/ipi_table.c67
-rw-r--r--chip/mt8192_scp/registers.h3
6 files changed, 155 insertions, 2 deletions
diff --git a/chip/mt8192_scp/build.mk b/chip/mt8192_scp/build.mk
index 966c1a29ef..277b2d8f6d 100644
--- a/chip/mt8192_scp/build.mk
+++ b/chip/mt8192_scp/build.mk
@@ -15,7 +15,11 @@ chip-y+=intc.o
chip-y+=system.o
chip-y+=uart.o
+ifeq ($(CONFIG_IPI),y)
+$(out)/RW/chip/$(CHIP)/ipi_table.o: $(out)/ipi_table_gen.inc
+endif
+
# Optional chip modules
chip-$(CONFIG_COMMON_TIMER)+=hrtimer.o
-chip-$(CONFIG_IPI)+=ipi.o
+chip-$(CONFIG_IPI)+=ipi.o ipi_table.o
chip-$(CONFIG_WATCHDOG)+=watchdog.o
diff --git a/chip/mt8192_scp/intc.c b/chip/mt8192_scp/intc.c
index 3afb0980ea..a5aa1bccd5 100644
--- a/chip/mt8192_scp/intc.c
+++ b/chip/mt8192_scp/intc.c
@@ -36,7 +36,7 @@ static struct {
uint8_t group;
} irqs[SCP_INTC_IRQ_COUNT] = {
/* 0 */
- [SCP_IRQ_GIPC_IN0] = { INTC_GRP_0 },
+ [SCP_IRQ_GIPC_IN0] = { INTC_GRP_7 },
[SCP_IRQ_GIPC_IN1] = { INTC_GRP_0 },
[SCP_IRQ_GIPC_IN2] = { INTC_GRP_0 },
[SCP_IRQ_GIPC_IN3] = { INTC_GRP_0 },
diff --git a/chip/mt8192_scp/ipi.c b/chip/mt8192_scp/ipi.c
index fdbcde3811..cc78c7878c 100644
--- a/chip/mt8192_scp/ipi.c
+++ b/chip/mt8192_scp/ipi.c
@@ -3,6 +3,7 @@
* found in the LICENSE file.
*/
+#include "atomic.h"
#include "common.h"
#include "console.h"
#include "hooks.h"
@@ -20,6 +21,29 @@ static uint8_t init_done;
static struct mutex ipi_lock;
static struct ipc_shared_obj *const ipi_send_buf =
(struct ipc_shared_obj *)CONFIG_IPC_SHARED_OBJ_ADDR;
+static struct ipc_shared_obj *const ipi_recv_buf =
+ (struct ipc_shared_obj *)(CONFIG_IPC_SHARED_OBJ_ADDR +
+ sizeof(struct ipc_shared_obj));
+
+static uint32_t disable_irq_count;
+
+void ipi_disable_irq(void)
+{
+ if (atomic_inc(&disable_irq_count, 1) == 0)
+ task_disable_irq(SCP_IRQ_GIPC_IN0);
+}
+
+void ipi_enable_irq(void)
+{
+ if (atomic_dec(&disable_irq_count, 1) == 1) {
+ int pending = SCP_GIPC_IN_SET;
+
+ task_enable_irq(SCP_IRQ_GIPC_IN0);
+
+ if (init_done && pending)
+ task_trigger_irq(SCP_IRQ_GIPC_IN0);
+ }
+}
static int ipi_is_busy(void)
{
@@ -51,6 +75,7 @@ int ipi_send(int32_t id, const void *buf, uint32_t len, int wait)
return EC_ERROR_INVAL;
}
+ ipi_disable_irq();
mutex_lock(&ipi_lock);
if (ipi_is_busy()) {
@@ -85,6 +110,7 @@ int ipi_send(int32_t id, const void *buf, uint32_t len, int wait)
ret = EC_SUCCESS;
error:
mutex_unlock(&ipi_lock);
+ ipi_enable_irq();
return ret;
}
@@ -108,14 +134,42 @@ static void ipi_enable_deferred(void)
init_done = 0;
return;
}
+
+ task_enable_irq(SCP_IRQ_GIPC_IN0);
}
DECLARE_DEFERRED(ipi_enable_deferred);
static void ipi_init(void)
{
memset(ipi_send_buf, 0, sizeof(struct ipc_shared_obj));
+ memset(ipi_recv_buf, 0, sizeof(struct ipc_shared_obj));
/* enable IRQ after all tasks are up */
hook_call_deferred(&ipi_enable_deferred_data, 0);
}
DECLARE_HOOK(HOOK_INIT, ipi_init, HOOK_PRIO_DEFAULT);
+
+static void ipi_handler(void)
+{
+ if (ipi_recv_buf->id >= IPI_COUNT) {
+ CPRINTS("invalid IPI, id=%d", ipi_recv_buf->id);
+ return;
+ }
+
+ CPRINTS("IPI %d", ipi_recv_buf->id);
+
+ ipi_handler_table[ipi_recv_buf->id](
+ ipi_recv_buf->id, ipi_recv_buf->buffer, ipi_recv_buf->len);
+}
+
+static void irq_group7_handler(void)
+{
+ extern volatile int ec_int;
+
+ if (SCP_GIPC_IN_SET & GIPC_IN(0)) {
+ ipi_handler();
+ SCP_GIPC_IN_CLR = GIPC_IN(0);
+ task_clear_pending_irq(ec_int);
+ }
+}
+DECLARE_IRQ(7, irq_group7_handler, 0);
diff --git a/chip/mt8192_scp/ipi_chip.h b/chip/mt8192_scp/ipi_chip.h
index 1fa30275d9..13345fc6e2 100644
--- a/chip/mt8192_scp/ipi_chip.h
+++ b/chip/mt8192_scp/ipi_chip.h
@@ -63,4 +63,29 @@ void ipi_disable_irq(void);
/* Enable IPI IRQ. */
void ipi_enable_irq(void);
+/* IPI tables */
+extern void (*const ipi_handler_table[])(int32_t, void *, uint32_t);
+extern int *const ipi_wakeup_table[];
+
+/* Helper macros to build the IPI handler and wakeup functions. */
+#define IPI_HANDLER(id) CONCAT3(ipi_, id, _handler)
+#define IPI_WAKEUP(id) CONCAT3(ipi_, id, _wakeup)
+
+/*
+ * Macro to declare an IPI handler.
+ * _id: The ID of the IPI
+ * handler: The IPI handler function
+ * is_wakeup_src: Declare IPI ID as a wake-up source or not
+ */
+#define DECLARE_IPI(_id, handler, is_wakeup_src) \
+ struct ipi_num_check##_id { \
+ int dummy1[_id < IPI_COUNT ? 1 : -1]; \
+ int dummy2[is_wakeup_src == 0 || is_wakeup_src == 1 ? 1 : -1]; \
+ }; \
+ void __keep IPI_HANDLER(_id)(int32_t id, void *buf, uint32_t len) \
+ { \
+ handler(id, buf, len); \
+ } \
+ const int __keep IPI_WAKEUP(_id) = is_wakeup_src
+
#endif /* __CROS_EC_IPI_CHIP_H */
diff --git a/chip/mt8192_scp/ipi_table.c b/chip/mt8192_scp/ipi_table.c
new file mode 100644
index 0000000000..8fe3f1e598
--- /dev/null
+++ b/chip/mt8192_scp/ipi_table.c
@@ -0,0 +1,67 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * IPI handlers declaration
+ */
+
+#include "common.h"
+#include "ipi_chip.h"
+
+typedef void (*ipi_handler_t)(int32_t id, void *data, uint32_t len);
+
+#ifndef PASS
+#define PASS 1
+#endif
+
+#define ipi_arguments int32_t id, void *data, uint32_t len
+
+#if PASS == 1
+void ipi_handler_undefined(ipi_arguments) { }
+
+const int ipi_wakeup_undefined;
+
+#define table(type, name, x) x
+
+#define ipi_x_func(suffix, args, number) \
+ extern void __attribute__( \
+ (used, weak, alias(STRINGIFY(ipi_##suffix##_undefined)))) \
+ ipi_##number##_##suffix(args);
+
+#define ipi_x_var(suffix, number) \
+ extern int __attribute__( \
+ (weak, alias(STRINGIFY(ipi_##suffix##_undefined)))) \
+ ipi_##number##_##suffix;
+
+#endif /* PASS == 1 */
+
+#if PASS == 2
+
+#undef table
+#undef ipi_x_func
+#undef ipi_x_var
+
+#define table(type, name, x) \
+ type const name[] \
+ __attribute__((aligned(4), used, section(".rodata.ipi"))) = {x}
+
+#define ipi_x_var(suffix, number) \
+ [number < IPI_COUNT ? number : -1] = &ipi_##number##_##suffix,
+
+#define ipi_x_func(suffix, args, number) ipi_x_var(suffix, number)
+
+#endif /* PASS == 2 */
+
+/*
+ * Include generated IPI table (by util/gen_ipi_table). The contents originate
+ * from IPI_COUNT definition in board.h
+ */
+#include "ipi_table_gen.inc"
+
+#if PASS == 1
+#undef PASS
+#define PASS 2
+#include "ipi_table.c"
+BUILD_ASSERT(ARRAY_SIZE(ipi_handler_table) == IPI_COUNT);
+BUILD_ASSERT(ARRAY_SIZE(ipi_wakeup_table) == IPI_COUNT);
+#endif
diff --git a/chip/mt8192_scp/registers.h b/chip/mt8192_scp/registers.h
index 5620dcb6dc..dbf0aed64d 100644
--- a/chip/mt8192_scp/registers.h
+++ b/chip/mt8192_scp/registers.h
@@ -68,6 +68,9 @@
#define SCP_SCP2APMCU_IPC_SET REG32(SCP_REG_BASE + 0x24080)
#define SCP_SCP2SPM_IPC_SET REG32(SCP_REG_BASE + 0x24090)
#define IPC_SCP2HOST BIT(0)
+#define SCP_GIPC_IN_SET REG32(SCP_REG_BASE + 0x24098)
+#define SCP_GIPC_IN_CLR REG32(SCP_REG_BASE + 0x2409C)
+#define GIPC_IN(n) BIT(n)
/* UART */
#define SCP_UART_COUNT 2