Files
opensbi/platform/generic/andes/ae350.c
Ben Zong-You Xie 2b93ce0954 platform: andes: Change all occurrences of andes45 to andes
To make the framework suit all Andes CPUs, change all occurrences of
andes45 to andes.

In addition, we fix some coding style problems and remove an unused
macro in andes.h.

Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
2024-05-09 17:57:51 +05:30

124 lines
2.7 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2022 Andes Technology Corporation
*
* Authors:
* Yu Chien Peter Lin <peterlin@andestech.com>
*/
#include <platform_override.h>
#include <andes/andes_pmu.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi_utils/sys/atcsmu.h>
#include <sbi/riscv_asm.h>
#include <sbi/sbi_bitops.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_hsm.h>
#include <sbi/sbi_ipi.h>
#include <sbi/sbi_init.h>
#include <andes/andes.h>
static struct smu_data smu = { 0 };
extern void __ae350_enable_coherency_warmboot(void);
extern void __ae350_disable_coherency(void);
static int ae350_hart_start(u32 hartid, ulong saddr)
{
/*
* Don't send wakeup command when:
* 1) boot-time
* 2) the target hart is non-sleepable 25-series hart0
*/
if (!sbi_init_count(hartid) || (is_andes(25) && hartid == 0))
return sbi_ipi_raw_send(sbi_hartid_to_hartindex(hartid));
/* Write wakeup command to the sleep hart */
smu_set_command(&smu, WAKEUP_CMD, hartid);
return 0;
}
static int ae350_hart_stop(void)
{
int rc;
u32 hartid = current_hartid();
/**
* For Andes AX25MP, the hart0 shares power domain with
* L2-cache, instead of turning it off, it should fall
* through and jump to warmboot_addr.
*/
if (is_andes(25) && hartid == 0)
return SBI_ENOTSUPP;
if (!smu_support_sleep_mode(&smu, DEEPSLEEP_MODE, hartid))
return SBI_ENOTSUPP;
/**
* disable all events, the current hart will be
* woken up from reset vector when other hart
* writes its PCS (power control slot) control
* register
*/
smu_set_wakeup_events(&smu, 0x0, hartid);
smu_set_command(&smu, DEEP_SLEEP_CMD, hartid);
rc = smu_set_reset_vector(&smu,
(ulong)__ae350_enable_coherency_warmboot,
hartid);
if (rc)
goto fail;
__ae350_disable_coherency();
wfi();
fail:
/* It should never reach here */
sbi_hart_hang();
return 0;
}
static const struct sbi_hsm_device andes_smu = {
.name = "andes_smu",
.hart_start = ae350_hart_start,
.hart_stop = ae350_hart_stop,
};
static void ae350_hsm_device_init(void)
{
int rc;
void *fdt;
fdt = fdt_get_address();
rc = fdt_parse_compat_addr(fdt, (uint64_t *)&smu.addr,
"andestech,atcsmu");
if (!rc) {
sbi_hsm_set_device(&andes_smu);
}
}
static int ae350_final_init(bool cold_boot, const struct fdt_match *match)
{
if (cold_boot)
ae350_hsm_device_init();
return 0;
}
static const struct fdt_match andes_ae350_match[] = {
{ .compatible = "andestech,ae350" },
{ },
};
const struct platform_override andes_ae350 = {
.match_table = andes_ae350_match,
.final_init = ae350_final_init,
.extensions_init = andes_pmu_extensions_init,
.pmu_init = andes_pmu_init,
};