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:
parent
438219c466
commit
45242d9214
4 changed files with 42 additions and 2 deletions
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}")
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue