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 <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2022-01-23 10:33:19 -08:00 committed by Anas Nashif
commit 45242d9214
4 changed files with 42 additions and 2 deletions

View file

@ -101,6 +101,11 @@ extern bool soc_cpus_active[CONFIG_MP_NUM_CPUS];
* responsibility. This function will hang if the other CPU fails to * responsibility. This function will hang if the other CPU fails to
* reach idle. * 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 * @param id CPU to halt, not current cpu or cpu 0
* @return 0 on success, -EINVAL on error * @return 0 on success, -EINVAL on error
*/ */

View file

@ -202,8 +202,13 @@ int soc_adsp_halt_cpu(int id)
CAVS_SHIM.pwrctl &= ~CAVS_PWRCTL_TCPDSPPG(id); CAVS_SHIM.pwrctl &= ~CAVS_PWRCTL_TCPDSPPG(id);
CAVS_SHIM.clkctl &= ~CAVS_CLKCTL_TCPLCG(id); CAVS_SHIM.clkctl &= ~CAVS_CLKCTL_TCPLCG(id);
/* Wait for the CPU to reach an idle state before returing */ /* If possible, wait for the other CPU to reach an idle state
while (CAVS_SHIM.pwrsts & CAVS_PWRSTS_PDSPPGS(id)) { * 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; return 0;
} }

View file

@ -336,6 +336,8 @@ def ipc_command(data, ext_data):
asyncio.ensure_future(ipc_delay_done()) asyncio.ensure_future(ipc_delay_done())
elif data == 2: # echo back ext_data as a message command elif data == 2: # echo back ext_data as a message command
send_msg = True send_msg = True
elif data == 3: # set ADSPCS
dsp.ADSPCS = ext_data
else: else:
log.warning(f"cavstool: Unrecognized IPC command 0x{data:x} ext 0x{ext_data:x}") log.warning(f"cavstool: Unrecognized IPC command 0x{data:x} ext 0x{ext_data:x}")

View file

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <kernel.h> #include <kernel.h>
#include <ztest.h> #include <ztest.h>
#include <cavs_ipc.h>
#include "tests.h" #include "tests.h"
#define RUN_ON_STACKSZ 2048 #define RUN_ON_STACKSZ 2048
@ -148,14 +149,41 @@ void halt_and_restart(int cpu)
{ {
printk("halt/restart core %d...\n", cpu); printk("halt/restart core %d...\n", cpu);
static bool alive_flag; 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); soc_adsp_halt_cpu(cpu);
alive_flag = false; alive_flag = false;
run_on_cpu(cpu, alive_fn, &alive_flag, false); run_on_cpu(cpu, alive_fn, &alive_flag, false);
k_msleep(100); k_msleep(100);
zassert_false(alive_flag, "cpu didn't halt"); 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); 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); WAIT_FOR(alive_flag == true);
k_thread_abort(&run_on_threads[cpu]); k_thread_abort(&run_on_threads[cpu]);