diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index 047736942..91d55f371 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -64,7 +64,8 @@ CONFIG_SOF_LOG_LEVEL_INF=y CONFIG_ZEPHYR_LOG=y CONFIG_INTEL_ADSP_IPC=y - +CONFIG_WATCHDOG=y +CONFIG_LL_WATCHDOG=y # Temporary disabled options CONFIG_TRACE=n diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 4a392005c..aeabdc67d 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -625,6 +625,7 @@ endif config LL_WATCHDOG bool "Enable watchdog support in ll scheduler" default n + depends on ACE help Select if you want to protect ll scheduler with a watchdog timer. The watchdog is enabled after creating a ll thread for specified diff --git a/src/platform/intel/ace/lib/watchdog.c b/src/platform/intel/ace/lib/watchdog.c new file mode 100644 index 000000000..c77410c09 --- /dev/null +++ b/src/platform/intel/ace/lib/watchdog.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2023 Intel Corporation + * + * Author: Adrian Warecki + */ + +#include +#include +#include +#include +#include + +#include +#include + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(adsp_watchdog), okay) +#include +#include +#include + +LOG_MODULE_REGISTER(wdt, CONFIG_SOF_LOG_LEVEL); + +/* 13c8bc59-c4fa-4ad1-b93a-ce97cd30acc7 */ +DECLARE_SOF_UUID("wdt", wdt_uuid, 0x13c8bc59, 0xc4fa, 0x4ad1, + 0xb9, 0x3a, 0xce, 0x97, 0xcd, 0x30, 0xac, 0xc7); + +DECLARE_TR_CTX(wdt_tr, SOF_UUID(wdt_uuid), LOG_LEVEL_INFO); + +static const struct device *const watchdog = DEVICE_DT_GET(DT_NODELABEL(adsp_watchdog)); +static struct ipc_msg secondary_timeout_ipc; + +static void watchdog_primary_core_action_on_timeout(void) +{ + struct ipc4_watchdog_timeout_notification notif; + + /* Send Watchdog Timeout IPC notification */ + ipc4_notification_watchdog_init(¬if, cpu_get_id(), true); + intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, + notif.primary.dat, notif.extension.dat); +} + +static void watchdog_secondary_core_action_on_timeout(void) +{ + struct idc_msg msg; + + /* Send Watchdog Timeout IDC notification */ + msg.header = IDC_MSG_SECONDARY_CORE_CRASHED | IDC_SCC_CORE(cpu_get_id()) | + IDC_SCC_REASON(IDC_SCC_REASON_WATCHDOG); + msg.extension = 0; + msg.core = 0; + msg.size = 0; + msg.payload = NULL; + idc_send_msg(&msg, IDC_NON_BLOCKING); +} + +/* This function is called by idc handler on primary core */ +void watchdog_secondary_core_timeout(int core) +{ + struct ipc4_watchdog_timeout_notification notif; + + /* Send Watchdog Timeout IPC notification */ + ipc4_notification_watchdog_init(¬if, core, true); + secondary_timeout_ipc.header = notif.primary.dat; + secondary_timeout_ipc.extension = notif.extension.dat; + ipc_msg_send(&secondary_timeout_ipc, NULL, true); +} + +static void watchdog_timeout(const struct device *dev, int core) +{ + if (core == PLATFORM_PRIMARY_CORE_ID) + watchdog_primary_core_action_on_timeout(); + else + watchdog_secondary_core_action_on_timeout(); +} + +void watchdog_init(void) +{ + int i, ret; + const struct wdt_timeout_cfg watchdog_config = { + .window.max = LL_WATCHDOG_TIMEOUT_US / 1000, + .callback = watchdog_timeout, + }; + + secondary_timeout_ipc.tx_data = NULL; + secondary_timeout_ipc.tx_size = 0; + list_init(&secondary_timeout_ipc.list); + + ret = wdt_install_timeout(watchdog, &watchdog_config); + if (ret) { + tr_warn(&wdt_tr, "Watchdog install timeout error %d", ret); + return; + } + + for (i = 0; i < CONFIG_CORE_COUNT; i++) + intel_adsp_watchdog_pause(watchdog, i); + + ret = wdt_setup(watchdog, 0); + if (ret) + tr_warn(&wdt_tr, "Watchdog setup error %d", ret); +} + +void watchdog_enable(int core) +{ + intel_adsp_watchdog_resume(watchdog, core); +} + +void watchdog_disable(int core) +{ + intel_adsp_watchdog_pause(watchdog, core); +} + +void watchdog_feed(int core) +{ + wdt_feed(watchdog, core); +} +#else +void watchdog_enable(int core) {} +void watchdog_disable(int core) {} +void watchdog_feed(int core) {} +void watchdog_init(void) {} +void watchdog_secondary_core_timeout(int core) {} +#endif diff --git a/src/platform/intel/ace/platform.c b/src/platform/intel/ace/platform.c index 447a6e47c..78a4e4f6e 100644 --- a/src/platform/intel/ace/platform.c +++ b/src/platform/intel/ace/platform.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -102,6 +103,8 @@ int platform_init(struct sof *sof) ipc_init(sof); idc_init(); + watchdog_init(); + /* show heap status */ heap_trace_all(1); diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 9e3fec502..bb066d99d 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -459,6 +459,10 @@ if (CONFIG_ACE_VERSION_1_5) ${SOF_PLATFORM_PATH}/intel/ace/lps_wait.c ) + zephyr_library_sources_ifdef(CONFIG_LL_WATCHDOG + ${SOF_PLATFORM_PATH}/intel/ace/lib/watchdog.c + ) + set(PLATFORM "meteorlake") zephyr_include_directories(${SOF_PLATFORM_PATH}/intel/ace/include)