linuxOS_D21X/source/opensbi/platform/generic/sifive_fu540.c
2024-11-29 16:33:21 +08:00

115 lines
2.7 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
*
* Authors:
* Anup Patel <anup.patel@wdc.com>
*/
#include <platform_override.h>
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/fdt/fdt_fixup.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_hsm.h>
#include <sbi/sbi_string.h>
#include <sbi/riscv_encoding.h>
#include <sbi/riscv_asm.h>
#include <sbi/riscv_io.h>
#define AIC_SRAM_BASE 0x00100000
extern void aic_suspend_resume();
extern u32 aic_suspend_resume_size;
static void (*aic_suspend_resume_fn)();
static u64 sifive_fu540_tlbr_flush_limit(const struct fdt_match *match)
{
/*
* The sfence.vma by virtual address does not work on
* SiFive FU540 so we return remote TLB flush limit as zero.
*/
return 0;
}
static int sifive_fu540_fdt_fixup(void *fdt, const struct fdt_match *match)
{
/*
* SiFive Freedom U540 has an erratum that prevents S-mode software
* to access a PMP protected region using 1GB page table mapping, so
* always add the no-map attribute on this platform.
*/
fdt_reserved_memory_nomap_fixup(fdt);
return 0;
}
static inline void icache_invalid(void)
{
__asm__ __volatile__("fence");
__asm__ __volatile__("fence.i");
__asm__ __volatile__(".long 0x0100000b");
__asm__ __volatile__("fence");
__asm__ __volatile__("fence.i");
}
static inline void dcache_clean_invalid(void)
{
__asm__ __volatile__("fence");
__asm__ __volatile__("fence.i");
__asm__ __volatile__(".long 0x0030000b");
__asm__ __volatile__("fence");
__asm__ __volatile__("fence.i");
}
static int artinchip_hart_suspend(u32 suspend_type, ulong raddr)
{
unsigned long saved_mie;
if (suspend_type) {
sbi_memcpy((void *)AIC_SRAM_BASE, aic_suspend_resume,
aic_suspend_resume_size);
aic_suspend_resume_fn = (void *)AIC_SRAM_BASE;
saved_mie = csr_read(CSR_MIE);
//Only enable SEIE
csr_write(CSR_MIE, MIP_SEIP);
icache_invalid();
dcache_clean_invalid();
aic_suspend_resume_fn();
csr_write(CSR_MIE, saved_mie);
}
return 0;
}
static const struct sbi_hsm_device artinchip_hsm_device = {
.name = "aic_hsm_device",
.hart_suspend = artinchip_hart_suspend,
};
int artinchip_early_init(bool cold_boot, const struct fdt_match *match)
{
if (cold_boot)
sbi_hsm_set_device(&artinchip_hsm_device);
return 0;
}
static const struct fdt_match sifive_fu540_match[] = {
{ .compatible = "artinchip,d211" },
{ .compatible = "sifive,fu540" },
{ .compatible = "sifive,fu540g" },
{ .compatible = "sifive,fu540-c000" },
{ .compatible = "sifive,hifive-unleashed-a00" },
{ },
};
const struct platform_override sifive_fu540 = {
.match_table = sifive_fu540_match,
.tlbr_flush_limit = sifive_fu540_tlbr_flush_limit,
.fdt_fixup = sifive_fu540_fdt_fixup,
.early_init = artinchip_early_init,
};