Files
opensbi/platform/qemu/virt/platform.c
Atish Patra e0686ca844 platform: No need to pass context id for plic fixup.
PLIC DT entry fixup can be done by comparing external
interrupt number instead of context id. No need to invoke
fixup for each plic context.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
2019-01-18 10:05:12 +05:30

151 lines
3.0 KiB
C

/*
* Copyright (c) 2018 Western Digital Corporation or its affiliates.
*
* Authors:
* Anup Patel <anup.patel@wdc.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sbi/riscv_encoding.h>
#include <sbi/sbi_const.h>
#include <sbi/sbi_platform.h>
#include <plat/irqchip/plic.h>
#include <plat/serial/uart8250.h>
#include <plat/sys/clint.h>
#define VIRT_HART_COUNT 8
#define VIRT_HART_STACK_SIZE 8192
#define VIRT_TEST_ADDR 0x100000
#define VIRT_CLINT_ADDR 0x2000000
#define VIRT_PLIC_ADDR 0xc000000
#define VIRT_PLIC_NUM_SOURCES 127
#define VIRT_PLIC_NUM_PRIORITIES 7
#define VIRT_UART16550_ADDR 0x10000000
#define VIRT_UART_BAUDRATE 115200
#define VIRT_UART_SHIFTREG_ADDR 1843200
static int virt_final_init(u32 hartid, bool cold_boot)
{
void *fdt;
if (!cold_boot)
return 0;
fdt = sbi_scratch_thishart_arg1_ptr();
plic_fdt_fixup(fdt, "riscv,plic0");
return 0;
}
static u32 virt_pmp_region_count(u32 hartid)
{
return 1;
}
static int virt_pmp_region_info(u32 hartid, u32 index,
ulong *prot, ulong *addr, ulong *log2size)
{
int ret = 0;
switch (index) {
case 0:
*prot = PMP_R | PMP_W | PMP_X;
*addr = 0;
*log2size = __riscv_xlen;
break;
default:
ret = -1;
break;
};
return ret;
}
static int virt_console_init(void)
{
return uart8250_init(VIRT_UART16550_ADDR,
VIRT_UART_SHIFTREG_ADDR,
VIRT_UART_BAUDRATE, 0, 1);
}
static int virt_irqchip_init(u32 hartid, bool cold_boot)
{
int rc;
if (cold_boot) {
rc = plic_cold_irqchip_init(VIRT_PLIC_ADDR,
VIRT_PLIC_NUM_SOURCES,
VIRT_HART_COUNT);
if (rc)
return rc;
}
return plic_warm_irqchip_init(hartid,
(2 * hartid),
(2 * hartid + 1));
}
static int virt_ipi_init(u32 hartid, bool cold_boot)
{
int rc;
if (cold_boot) {
rc = clint_cold_ipi_init(VIRT_CLINT_ADDR,
VIRT_HART_COUNT);
if (rc)
return rc;
}
return clint_warm_ipi_init(hartid);
}
static int virt_timer_init(u32 hartid, bool cold_boot)
{
int rc;
if (cold_boot) {
rc = clint_cold_timer_init(VIRT_CLINT_ADDR,
VIRT_HART_COUNT);
if (rc)
return rc;
}
return clint_warm_timer_init(hartid);
}
static int virt_system_down(u32 type)
{
/* For now nothing to do. */
return 0;
}
struct sbi_platform platform = {
.name = "QEMU Virt Machine",
.features = SBI_PLATFORM_DEFAULT_FEATURES,
.hart_count = VIRT_HART_COUNT,
.hart_stack_size = VIRT_HART_STACK_SIZE,
.disabled_hart_mask = 0,
.pmp_region_count = virt_pmp_region_count,
.pmp_region_info = virt_pmp_region_info,
.final_init = virt_final_init,
.console_putc = uart8250_putc,
.console_getc = uart8250_getc,
.console_init = virt_console_init,
.irqchip_init = virt_irqchip_init,
.ipi_inject = clint_ipi_inject,
.ipi_sync = clint_ipi_sync,
.ipi_clear = clint_ipi_clear,
.ipi_init = virt_ipi_init,
.timer_value = clint_timer_value,
.timer_event_stop = clint_timer_event_stop,
.timer_event_start = clint_timer_event_start,
.timer_init = virt_timer_init,
.system_reboot = virt_system_down,
.system_shutdown = virt_system_down
};