diff options
Diffstat (limited to 'chip')
-rw-r--r-- | chip/mt8192_scp/build.mk | 6 | ||||
-rw-r--r-- | chip/mt8192_scp/intc.c | 2 | ||||
-rw-r--r-- | chip/mt8192_scp/ipi.c | 54 | ||||
-rw-r--r-- | chip/mt8192_scp/ipi_chip.h | 25 | ||||
-rw-r--r-- | chip/mt8192_scp/ipi_table.c | 67 | ||||
-rw-r--r-- | chip/mt8192_scp/registers.h | 3 |
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 |