blob: 59fe81f50dd9dedef579c2dbcef13035a16f4814 [file] [log] [blame]
/*
* Copyright (c) 2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <events.h>
#include <lfa.h>
#include <plat_topology.h>
#include <platform.h>
#include <power_management.h>
#include <psci.h>
#include <spinlock.h>
#include <test_helpers.h>
#include <tftf_lib.h>
#define RMM_X1 UL(0x564bf212a662076c)
#define RMM_X2 UL(0xd90636638fbacb92)
static uint64_t fw_id;
/*
* Test entry point function for non-lead CPUs.
* Specified by the lead CPU when bringing up other CPUs.
*/
static test_result_t non_lead_cpu_fn(void)
{
smc_args args = { .fid = LFA_ACTIVATE, .arg1 = fw_id };
smc_ret_values ret;
ret = tftf_smc(&args);
if (ret.ret0 != SMC_OK) {
tftf_testcase_printf("%s: LFA_ACTIVATE error: 0x%08lx\n",
__func__, ret.ret0);
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
}
static test_result_t test_lfa_activate_flow(uint64_t uuid1, uint64_t uuid2)
{
unsigned int lead_mpid;
unsigned int cpu_mpid, cpu_node;
int psci_ret;
lead_mpid = read_mpidr_el1() & MPID_MASK;
SKIP_TEST_IF_LESS_THAN_N_CPUS(2);
smc_args args = { .fid = LFA_GET_INFO, .arg1 = 0 };
smc_ret_values ret;
uint64_t i, j;
bool found = false;
ret = tftf_smc(&args);
if (ret.ret0 != SMC_OK) {
tftf_testcase_printf("%s: LFA_GET_INFO error: 0x%08lx\n",
__func__, ret.ret0);
return TEST_RESULT_FAIL;
}
j = ret.ret1;
for (i = 0U; i < j; i++) {
args.fid = LFA_GET_INVENTORY;
args.arg1 = i;
ret = tftf_smc(&args);
if (ret.ret0 != 0) {
tftf_testcase_printf("%s: LFA_GET_INVENTORY error: 0x%08lx\n",
__func__, ret.ret0);
return TEST_RESULT_FAIL;
}
tftf_testcase_printf("ID %lld: 0x%16lx 0x%16lx - capable: %s, pending: %s\n",
i, ret.ret1, ret.ret2,
(ret.ret4 & 0x1) ? "yes" : "no",
(ret.ret4 & 0x2) ? "yes" : "no");
if ((ret.ret1 == uuid1) && (ret.ret2 == uuid2)) {
found = true;
fw_id = i;
}
}
if (found == false) {
tftf_testcase_printf("%s: Firmware not found\n", __func__);
return TEST_RESULT_SKIPPED;
}
args.fid = LFA_PRIME;
args.arg1 = fw_id;
ret = tftf_smc(&args);
if (ret.ret0 != SMC_OK) {
tftf_testcase_printf("%s: LFA_PRIME error: 0x%08lx\n",
__func__, ret.ret0);
return TEST_RESULT_FAIL;
}
/* Power on all CPUs */
for_each_cpu(cpu_node) {
cpu_mpid = tftf_get_mpidr_from_node(cpu_node);
/* Skip lead CPU as it is already powered on */
if (cpu_mpid == lead_mpid)
continue;
psci_ret = tftf_cpu_on(cpu_mpid, (uintptr_t) non_lead_cpu_fn, 0);
if (psci_ret != PSCI_E_SUCCESS) {
tftf_testcase_printf(
"Failed to power on CPU 0x%x (%d)\n",
cpu_mpid, psci_ret);
return TEST_RESULT_SKIPPED;
}
}
args.fid = LFA_ACTIVATE;
args.arg1 = fw_id;
ret = tftf_smc(&args);
if (ret.ret0 != SMC_OK) {
tftf_testcase_printf("%s: LFA_ACTIVATE error: 0x%08lx\n", __func__, ret.ret0);
return TEST_RESULT_FAIL;
}
return TEST_RESULT_SUCCESS;
}
/*
* @Test_Aim@ Test RMM Live activation.
*/
test_result_t test_lfa_activate_rmm(void)
{
return test_lfa_activate_flow(RMM_X1, RMM_X2);
}