From 45242d921402b06ec72fcb8f8b9ba86f0dc1aad0 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sun, 23 Jan 2022 10:33:19 -0800 Subject: [PATCH] tests/intel_adsp: MP core power fixups for older cAVS platforms On cAVS before 2.5, core power was controlled by the host. Add a command to the cavstool.py script to allow us to do that under test command so we can exercise multiprocessor startup/shutdown outside of SOF. Signed-off-by: Andy Ross --- soc/xtensa/intel_adsp/common/include/soc.h | 5 ++++ soc/xtensa/intel_adsp/common/mp_cavs.c | 9 +++++-- soc/xtensa/intel_adsp/tools/cavstool.py | 2 ++ tests/boards/intel_adsp/smoke/src/cpus.c | 28 ++++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/soc/xtensa/intel_adsp/common/include/soc.h b/soc/xtensa/intel_adsp/common/include/soc.h index 9b033de0afc..40af9155a9d 100644 --- a/soc/xtensa/intel_adsp/common/include/soc.h +++ b/soc/xtensa/intel_adsp/common/include/soc.h @@ -101,6 +101,11 @@ extern bool soc_cpus_active[CONFIG_MP_NUM_CPUS]; * responsibility. This function will hang if the other CPU fails to * reach idle. * + * @note On older cAVS hardware, core power is controlled by the host. + * This function must still be called for OS bookeeping, but it is + * insufficient without application coordination (and careful + * synchronization!) with the host x86 environment. + * * @param id CPU to halt, not current cpu or cpu 0 * @return 0 on success, -EINVAL on error */ diff --git a/soc/xtensa/intel_adsp/common/mp_cavs.c b/soc/xtensa/intel_adsp/common/mp_cavs.c index 3275d09449f..fa06a5b9348 100644 --- a/soc/xtensa/intel_adsp/common/mp_cavs.c +++ b/soc/xtensa/intel_adsp/common/mp_cavs.c @@ -202,8 +202,13 @@ int soc_adsp_halt_cpu(int id) CAVS_SHIM.pwrctl &= ~CAVS_PWRCTL_TCPDSPPG(id); CAVS_SHIM.clkctl &= ~CAVS_CLKCTL_TCPLCG(id); - /* Wait for the CPU to reach an idle state before returing */ - while (CAVS_SHIM.pwrsts & CAVS_PWRSTS_PDSPPGS(id)) { + /* If possible, wait for the other CPU to reach an idle state + * before returning. On older hardware this doesn't work + * because power is controlled by the host, so synchronization + * needs to be part of the application layer. + */ + while (IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V25) && + (CAVS_SHIM.pwrsts & CAVS_PWRSTS_PDSPPGS(id))) { } return 0; } diff --git a/soc/xtensa/intel_adsp/tools/cavstool.py b/soc/xtensa/intel_adsp/tools/cavstool.py index 3cc692e62f4..4fa1b840d15 100755 --- a/soc/xtensa/intel_adsp/tools/cavstool.py +++ b/soc/xtensa/intel_adsp/tools/cavstool.py @@ -336,6 +336,8 @@ def ipc_command(data, ext_data): asyncio.ensure_future(ipc_delay_done()) elif data == 2: # echo back ext_data as a message command send_msg = True + elif data == 3: # set ADSPCS + dsp.ADSPCS = ext_data else: log.warning(f"cavstool: Unrecognized IPC command 0x{data:x} ext 0x{ext_data:x}") diff --git a/tests/boards/intel_adsp/smoke/src/cpus.c b/tests/boards/intel_adsp/smoke/src/cpus.c index 1a424a44bac..3128ffd499a 100644 --- a/tests/boards/intel_adsp/smoke/src/cpus.c +++ b/tests/boards/intel_adsp/smoke/src/cpus.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "tests.h" #define RUN_ON_STACKSZ 2048 @@ -148,14 +149,41 @@ void halt_and_restart(int cpu) { printk("halt/restart core %d...\n", cpu); static bool alive_flag; + uint32_t all_cpus = BIT(CONFIG_MP_NUM_CPUS) - 1; + + /* On older hardware we need to get the host to turn the core + * off. Construct an ADSPCS with only this core disabled + */ + if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V25)) { + cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_ADSPCS, + (all_cpus & ~BIT(cpu)) << 16); + } soc_adsp_halt_cpu(cpu); + alive_flag = false; run_on_cpu(cpu, alive_fn, &alive_flag, false); k_msleep(100); zassert_false(alive_flag, "cpu didn't halt"); + if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V25)) { + /* Likewise need to ask the host to turn it back on, + * and give it some time to spin up before we hit it. + * We don't have a return message wired to be notified + * of completion. + */ + cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_ADSPCS, + all_cpus << 16); + k_msleep(50); + } + z_smp_start_cpu(cpu); + + if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V25)) { + /* And... startup is slow on old platforms too */ + k_msleep(50); + } + WAIT_FOR(alive_flag == true); k_thread_abort(&run_on_threads[cpu]);