154 lines
3.5 KiB
C
154 lines
3.5 KiB
C
/*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*
|
|
* Copyright (c) 2019 Andes Technology Corporation
|
|
*
|
|
* Authors:
|
|
* Zong Li <zong@andestech.com>
|
|
* Nylon Chen <nylon7@andestech.com>
|
|
*/
|
|
|
|
#include <sbi/riscv_asm.h>
|
|
#include <sbi/riscv_encoding.h>
|
|
#include <sbi/sbi_console.h>
|
|
#include <sbi/sbi_const.h>
|
|
#include <sbi/sbi_ipi.h>
|
|
#include <sbi/sbi_platform.h>
|
|
#include <sbi/sbi_trap.h>
|
|
#include <sbi_utils/fdt/fdt_helper.h>
|
|
#include <sbi_utils/fdt/fdt_fixup.h>
|
|
#include <sbi_utils/irqchip/plic.h>
|
|
#include <sbi_utils/serial/fdt_serial.h>
|
|
#include <sbi_utils/timer/fdt_timer.h>
|
|
#include "platform.h"
|
|
#include "plicsw.h"
|
|
#include "cache.h"
|
|
|
|
static struct plic_data plic = {
|
|
.addr = AE350_PLIC_ADDR,
|
|
.num_src = AE350_PLIC_NUM_SOURCES,
|
|
};
|
|
|
|
/* Platform final initialization. */
|
|
static int ae350_final_init(bool cold_boot)
|
|
{
|
|
void *fdt;
|
|
|
|
if (!cold_boot)
|
|
return 0;
|
|
|
|
fdt = fdt_get_address();
|
|
fdt_fixups(fdt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Initialize the platform interrupt controller for current HART. */
|
|
static int ae350_irqchip_init(bool cold_boot)
|
|
{
|
|
u32 hartid = current_hartid();
|
|
int ret;
|
|
|
|
if (cold_boot) {
|
|
ret = plic_cold_irqchip_init(&plic);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
return plic_warm_irqchip_init(&plic, 2 * hartid, 2 * hartid + 1);
|
|
}
|
|
|
|
static struct sbi_ipi_device plicsw_ipi = {
|
|
.name = "ae350_plicsw",
|
|
.ipi_send = plicsw_ipi_send,
|
|
.ipi_clear = plicsw_ipi_clear
|
|
};
|
|
|
|
/* Initialize IPI for current HART. */
|
|
static int ae350_ipi_init(bool cold_boot)
|
|
{
|
|
int ret;
|
|
|
|
if (cold_boot) {
|
|
ret = plicsw_cold_ipi_init(AE350_PLICSW_ADDR,
|
|
AE350_HART_COUNT);
|
|
if (ret)
|
|
return ret;
|
|
|
|
sbi_ipi_set_device(&plicsw_ipi);
|
|
}
|
|
|
|
return plicsw_warm_ipi_init();
|
|
}
|
|
|
|
/* Vendor-Specific SBI handler */
|
|
static int ae350_vendor_ext_provider(long extid, long funcid,
|
|
const struct sbi_trap_regs *regs, unsigned long *out_value,
|
|
struct sbi_trap_info *out_trap)
|
|
{
|
|
int ret = 0;
|
|
switch (funcid) {
|
|
case SBI_EXT_ANDES_GET_MCACHE_CTL_STATUS:
|
|
*out_value = csr_read(CSR_MCACHECTL);
|
|
break;
|
|
case SBI_EXT_ANDES_GET_MMISC_CTL_STATUS:
|
|
*out_value = csr_read(CSR_MMISCCTL);
|
|
break;
|
|
case SBI_EXT_ANDES_SET_MCACHE_CTL:
|
|
ret = mcall_set_mcache_ctl(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_SET_MMISC_CTL:
|
|
ret = mcall_set_mmisc_ctl(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_ICACHE_OP:
|
|
ret = mcall_icache_op(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_DCACHE_OP:
|
|
ret = mcall_dcache_op(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_L1CACHE_I_PREFETCH:
|
|
ret = mcall_l1_cache_i_prefetch_op(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_L1CACHE_D_PREFETCH:
|
|
ret = mcall_l1_cache_d_prefetch_op(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_NON_BLOCKING_LOAD_STORE:
|
|
ret = mcall_non_blocking_load_store(regs->a0);
|
|
break;
|
|
case SBI_EXT_ANDES_WRITE_AROUND:
|
|
ret = mcall_write_around(regs->a0);
|
|
break;
|
|
default:
|
|
sbi_printf("Unsupported vendor sbi call : %ld\n", funcid);
|
|
asm volatile("ebreak");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* Platform descriptor. */
|
|
const struct sbi_platform_operations platform_ops = {
|
|
.final_init = ae350_final_init,
|
|
|
|
.console_init = fdt_serial_init,
|
|
|
|
.irqchip_init = ae350_irqchip_init,
|
|
|
|
.ipi_init = ae350_ipi_init,
|
|
|
|
.timer_init = fdt_timer_init,
|
|
|
|
.vendor_ext_provider = ae350_vendor_ext_provider
|
|
};
|
|
|
|
const struct sbi_platform platform = {
|
|
.opensbi_version = OPENSBI_VERSION,
|
|
.platform_version =
|
|
SBI_PLATFORM_VERSION(CONFIG_PLATFORM_ANDES_AE350_MAJOR_VER,
|
|
CONFIG_PLATFORM_ANDES_AE350_MINOR_VER),
|
|
.name = CONFIG_PLATFORM_ANDES_AE350_NAME,
|
|
.features = SBI_PLATFORM_DEFAULT_FEATURES,
|
|
.hart_count = AE350_HART_COUNT,
|
|
.hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
|
|
.platform_ops_addr = (unsigned long)&platform_ops
|
|
};
|