RISC-V: SoCify SiFive boards and connect GEM
This series has three tasks: 1. To convert the SiFive U and E machines into SoCs and boards 2. To connect the Cadence GEM device to the SiFive U board 3. Fix some device tree problems with the SiFive U board After this series the SiFive E and U boards have their SoCs split into seperate QEMU objects, which can be used on future boards if desired. The RISC-V Virt and Spike boards have not been converted. They haven't been converted as they aren't physical boards, so it doesn't make a whole lot of sense to split them into an SoC and board. The only disadvantage with this is that they now differ to the SiFive boards. This series also connect the Cadence GEM device to the SiFive U board. There are some interrupt line changes requried before this is possible. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAls+wyEACgkQIeENKd+X cFQ6aAf+L70WdK9yznSHz2yyg6y+ElzaVAvEAPV6dqp/axI28RngirpmFGjn9XJX 5Z2000xoAbAdY4CsPRhYTNhCZ1yYeL1CWByt827LJhOji1oz6HZF3JZmECghU9A0 LPTIF58U5bKRjlG+qQxvdNn5WtFA+o5YrE8R1VpkYXNOcwCszI3MMf2gLOQRrOW3 ZYC15EaIsmwzbnhQiDMzKx4x3TNg4A1qGMkGGf6HLu0tg+sMwsxmTjAOxPAblFnp 7T66Kx+zwAFCQMyIgLGq2bGXae6nUWWTh5P/Mtlll/kBIv9uVujLZlCj0Ndb0wZi ejptUPFJr4Kr5gE8qtG+Rueb+pGWHg== =Op/V -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-pull-20180705' into staging RISC-V: SoCify SiFive boards and connect GEM This series has three tasks: 1. To convert the SiFive U and E machines into SoCs and boards 2. To connect the Cadence GEM device to the SiFive U board 3. Fix some device tree problems with the SiFive U board After this series the SiFive E and U boards have their SoCs split into seperate QEMU objects, which can be used on future boards if desired. The RISC-V Virt and Spike boards have not been converted. They haven't been converted as they aren't physical boards, so it doesn't make a whole lot of sense to split them into an SoC and board. The only disadvantage with this is that they now differ to the SiFive boards. This series also connect the Cadence GEM device to the SiFive U board. There are some interrupt line changes requried before this is possible. # gpg: Signature made Fri 06 Jul 2018 02:17:21 BST # gpg: using RSA key 21E10D29DF977054 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054 * remotes/alistair/tags/pull-riscv-pull-20180705: hw/riscv/sifive_u: Connect the Cadence GEM Ethernet device hw/riscv/sifive_u: Move the uart device tree node under /soc/ hw/riscv/sifive_u: Set the interrupt controller number of interrupts hw/riscv/sifive_u: Set the soc device tree node as a simple-bus hw/riscv/sifive_plic: Use gpios instead of irqs hw/riscv/sifive_e: Create a SiFive E SoC object hw/riscv/sifive_u: Create a SiFive U SoC object Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a428594042
@ -3,3 +3,5 @@
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
include virtio.mak
|
||||
|
||||
CONFIG_CADENCE=y
|
||||
|
@ -3,3 +3,5 @@
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
include virtio.mak
|
||||
|
||||
CONFIG_CADENCE=y
|
||||
|
@ -102,18 +102,12 @@ static void riscv_sifive_e_init(MachineState *machine)
|
||||
SiFiveEState *s = g_new0(SiFiveEState, 1);
|
||||
MemoryRegion *sys_mem = get_system_memory();
|
||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
|
||||
int i;
|
||||
|
||||
/* Initialize SOC */
|
||||
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
|
||||
/* Initialize SoC */
|
||||
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_E_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
|
||||
&error_abort);
|
||||
object_property_set_str(OBJECT(&s->soc), SIFIVE_E_CPU, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts",
|
||||
&error_abort);
|
||||
object_property_set_bool(OBJECT(&s->soc), true, "realized",
|
||||
&error_abort);
|
||||
|
||||
@ -123,6 +117,49 @@ static void riscv_sifive_e_init(MachineState *machine)
|
||||
memory_region_add_subregion(sys_mem,
|
||||
memmap[SIFIVE_E_DTIM].base, main_mem);
|
||||
|
||||
/* Mask ROM reset vector */
|
||||
uint32_t reset_vec[2] = {
|
||||
0x204002b7, /* 0x1000: lui t0,0x20400 */
|
||||
0x00028067, /* 0x1004: jr t0 */
|
||||
};
|
||||
|
||||
/* copy in the reset vector in little_endian byte order */
|
||||
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
|
||||
reset_vec[i] = cpu_to_le32(reset_vec[i]);
|
||||
}
|
||||
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
|
||||
memmap[SIFIVE_E_MROM].base, &address_space_memory);
|
||||
|
||||
if (machine->kernel_filename) {
|
||||
load_kernel(machine->kernel_filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void riscv_sifive_e_soc_init(Object *obj)
|
||||
{
|
||||
SiFiveESoCState *s = RISCV_E_SOC(obj);
|
||||
|
||||
object_initialize(&s->cpus, sizeof(s->cpus), TYPE_RISCV_HART_ARRAY);
|
||||
object_property_add_child(obj, "cpus", OBJECT(&s->cpus),
|
||||
&error_abort);
|
||||
object_property_set_str(OBJECT(&s->cpus), SIFIVE_E_CPU, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts",
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
const struct MemmapEntry *memmap = sifive_e_memmap;
|
||||
|
||||
SiFiveESoCState *s = RISCV_E_SOC(dev);
|
||||
MemoryRegion *sys_mem = get_system_memory();
|
||||
MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->cpus), true, "realized",
|
||||
&error_abort);
|
||||
|
||||
/* Mask ROM */
|
||||
memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
|
||||
memmap[SIFIVE_E_MROM].size, &error_fatal);
|
||||
@ -150,13 +187,14 @@ static void riscv_sifive_e_init(MachineState *machine)
|
||||
sifive_mmio_emulate(sys_mem, "riscv.sifive.e.gpio0",
|
||||
memmap[SIFIVE_E_GPIO0].base, memmap[SIFIVE_E_GPIO0].size);
|
||||
sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART0].base,
|
||||
serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART0_IRQ]);
|
||||
serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ));
|
||||
sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi0",
|
||||
memmap[SIFIVE_E_QSPI0].base, memmap[SIFIVE_E_QSPI0].size);
|
||||
sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm0",
|
||||
memmap[SIFIVE_E_PWM0].base, memmap[SIFIVE_E_PWM0].size);
|
||||
/* sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART1].base,
|
||||
serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART1_IRQ]); */
|
||||
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic),
|
||||
SIFIVE_E_UART1_IRQ)); */
|
||||
sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi1",
|
||||
memmap[SIFIVE_E_QSPI1].base, memmap[SIFIVE_E_QSPI1].size);
|
||||
sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm1",
|
||||
@ -171,23 +209,6 @@ static void riscv_sifive_e_init(MachineState *machine)
|
||||
memmap[SIFIVE_E_XIP].size, &error_fatal);
|
||||
memory_region_set_readonly(xip_mem, true);
|
||||
memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, xip_mem);
|
||||
|
||||
/* Mask ROM reset vector */
|
||||
uint32_t reset_vec[2] = {
|
||||
0x204002b7, /* 0x1000: lui t0,0x20400 */
|
||||
0x00028067, /* 0x1004: jr t0 */
|
||||
};
|
||||
|
||||
/* copy in the reset vector in little_endian byte order */
|
||||
for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
|
||||
reset_vec[i] = cpu_to_le32(reset_vec[i]);
|
||||
}
|
||||
rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
|
||||
memmap[SIFIVE_E_MROM].base, &address_space_memory);
|
||||
|
||||
if (machine->kernel_filename) {
|
||||
load_kernel(machine->kernel_filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void riscv_sifive_e_machine_init(MachineClass *mc)
|
||||
@ -198,3 +219,27 @@ static void riscv_sifive_e_machine_init(MachineClass *mc)
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init)
|
||||
|
||||
static void riscv_sifive_e_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = riscv_sifive_e_soc_realize;
|
||||
/* Reason: Uses serial_hds in realize function, thus can't be used twice */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo riscv_sifive_e_soc_type_info = {
|
||||
.name = TYPE_RISCV_E_SOC,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(SiFiveESoCState),
|
||||
.instance_init = riscv_sifive_e_soc_init,
|
||||
.class_init = riscv_sifive_e_soc_class_init,
|
||||
};
|
||||
|
||||
static void riscv_sifive_e_soc_register_types(void)
|
||||
{
|
||||
type_register_static(&riscv_sifive_e_soc_type_info);
|
||||
}
|
||||
|
||||
type_init(riscv_sifive_e_soc_register_types)
|
||||
|
@ -435,7 +435,6 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level)
|
||||
static void sifive_plic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SiFivePLICState *plic = SIFIVE_PLIC(dev);
|
||||
int i;
|
||||
|
||||
memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
|
||||
TYPE_SIFIVE_PLIC, plic->aperture_size);
|
||||
@ -448,10 +447,7 @@ static void sifive_plic_realize(DeviceState *dev, Error **errp)
|
||||
plic->claimed = g_new0(uint32_t, plic->bitfield_words);
|
||||
plic->enable = g_new0(uint32_t, plic->bitfield_words * plic->num_addrs);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
|
||||
plic->irqs = g_new0(qemu_irq, plic->num_sources + 1);
|
||||
for (i = 0; i <= plic->num_sources; i++) {
|
||||
plic->irqs[i] = qemu_allocate_irq(sifive_plic_irq_request, plic, i);
|
||||
}
|
||||
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
|
||||
}
|
||||
|
||||
static void sifive_plic_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -60,8 +60,11 @@ static const struct MemmapEntry {
|
||||
[SIFIVE_U_UART0] = { 0x10013000, 0x1000 },
|
||||
[SIFIVE_U_UART1] = { 0x10023000, 0x1000 },
|
||||
[SIFIVE_U_DRAM] = { 0x80000000, 0x0 },
|
||||
[SIFIVE_U_GEM] = { 0x100900FC, 0x2000 },
|
||||
};
|
||||
|
||||
#define GEM_REVISION 0x10070109
|
||||
|
||||
static uint64_t load_kernel(const char *kernel_filename)
|
||||
{
|
||||
uint64_t kernel_entry, kernel_high;
|
||||
@ -97,7 +100,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
|
||||
qemu_fdt_add_subnode(fdt, "/soc");
|
||||
qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
|
||||
qemu_fdt_setprop_string(fdt, "/soc", "compatible", "ucbbar,spike-bare-soc");
|
||||
qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
|
||||
qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
|
||||
qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
|
||||
|
||||
@ -116,10 +119,10 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
|
||||
qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
|
||||
|
||||
for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) {
|
||||
for (cpu = s->soc.cpus.num_harts - 1; cpu >= 0; cpu--) {
|
||||
nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
|
||||
char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
|
||||
char *isa = riscv_isa_string(&s->soc.harts[cpu]);
|
||||
char *isa = riscv_isa_string(&s->soc.cpus.harts[cpu]);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
|
||||
SIFIVE_U_CLOCK_FREQ);
|
||||
@ -140,8 +143,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
cells = g_new0(uint32_t, s->soc.num_harts * 4);
|
||||
for (cpu = 0; cpu < s->soc.num_harts; cpu++) {
|
||||
cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4);
|
||||
for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) {
|
||||
nodename =
|
||||
g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
|
||||
uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename);
|
||||
@ -159,12 +162,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
0x0, memmap[SIFIVE_U_CLINT].base,
|
||||
0x0, memmap[SIFIVE_U_CLINT].size);
|
||||
qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
|
||||
cells, s->soc.num_harts * sizeof(uint32_t) * 4);
|
||||
cells, s->soc.cpus.num_harts * sizeof(uint32_t) * 4);
|
||||
g_free(cells);
|
||||
g_free(nodename);
|
||||
|
||||
cells = g_new0(uint32_t, s->soc.num_harts * 4);
|
||||
for (cpu = 0; cpu < s->soc.num_harts; cpu++) {
|
||||
cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4);
|
||||
for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) {
|
||||
nodename =
|
||||
g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
|
||||
uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename);
|
||||
@ -181,20 +184,41 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0");
|
||||
qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
|
||||
qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
|
||||
cells, s->soc.num_harts * sizeof(uint32_t) * 4);
|
||||
cells, s->soc.cpus.num_harts * sizeof(uint32_t) * 4);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "reg",
|
||||
0x0, memmap[SIFIVE_U_PLIC].base,
|
||||
0x0, memmap[SIFIVE_U_PLIC].size);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control");
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "riscv,max-priority", 7);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 4);
|
||||
qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 0x35);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "phandle", 2);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", 2);
|
||||
plic_phandle = qemu_fdt_get_phandle(fdt, nodename);
|
||||
g_free(cells);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/uart@%lx",
|
||||
nodename = g_strdup_printf("/soc/ethernet@%lx",
|
||||
(long)memmap[SIFIVE_U_GEM].base);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "cdns,macb");
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "reg",
|
||||
0x0, memmap[SIFIVE_U_GEM].base,
|
||||
0x0, memmap[SIFIVE_U_GEM].size);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control");
|
||||
qemu_fdt_setprop_string(fdt, nodename, "phy-mode", "gmii");
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 1);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/soc/ethernet@%lx/ethernet-phy@0",
|
||||
(long)memmap[SIFIVE_U_GEM].base);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0);
|
||||
g_free(nodename);
|
||||
|
||||
nodename = g_strdup_printf("/soc/uart@%lx",
|
||||
(long)memmap[SIFIVE_U_UART0].base);
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0");
|
||||
@ -217,17 +241,12 @@ static void riscv_sifive_u_init(MachineState *machine)
|
||||
SiFiveUState *s = g_new0(SiFiveUState, 1);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
int i;
|
||||
|
||||
/* Initialize SOC */
|
||||
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
|
||||
/* Initialize SoC */
|
||||
object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_U_SOC);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
|
||||
&error_abort);
|
||||
object_property_set_str(OBJECT(&s->soc), SIFIVE_U_CPU, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts",
|
||||
&error_abort);
|
||||
object_property_set_bool(OBJECT(&s->soc), true, "realized",
|
||||
&error_abort);
|
||||
|
||||
@ -235,17 +254,11 @@ static void riscv_sifive_u_init(MachineState *machine)
|
||||
memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
|
||||
machine->ram_size, &error_fatal);
|
||||
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base,
|
||||
main_mem);
|
||||
main_mem);
|
||||
|
||||
/* create device tree */
|
||||
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
|
||||
|
||||
/* boot rom */
|
||||
memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
|
||||
memmap[SIFIVE_U_MROM].size, &error_fatal);
|
||||
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
|
||||
mask_rom);
|
||||
|
||||
if (machine->kernel_filename) {
|
||||
load_kernel(machine->kernel_filename);
|
||||
}
|
||||
@ -284,6 +297,43 @@ static void riscv_sifive_u_init(MachineState *machine)
|
||||
rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
|
||||
memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
|
||||
&address_space_memory);
|
||||
}
|
||||
|
||||
static void riscv_sifive_u_soc_init(Object *obj)
|
||||
{
|
||||
SiFiveUSoCState *s = RISCV_U_SOC(obj);
|
||||
|
||||
object_initialize(&s->cpus, sizeof(s->cpus), TYPE_RISCV_HART_ARRAY);
|
||||
object_property_add_child(obj, "cpus", OBJECT(&s->cpus),
|
||||
&error_abort);
|
||||
object_property_set_str(OBJECT(&s->cpus), SIFIVE_U_CPU, "cpu-type",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts",
|
||||
&error_abort);
|
||||
|
||||
object_initialize(&s->gem, sizeof(s->gem), TYPE_CADENCE_GEM);
|
||||
qdev_set_parent_bus(DEVICE(&s->gem), sysbus_get_default());
|
||||
}
|
||||
|
||||
static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SiFiveUSoCState *s = RISCV_U_SOC(dev);
|
||||
const struct MemmapEntry *memmap = sifive_u_memmap;
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
qemu_irq plic_gpios[SIFIVE_U_PLIC_NUM_SOURCES];
|
||||
int i;
|
||||
Error *err = NULL;
|
||||
NICInfo *nd = &nd_table[0];
|
||||
|
||||
object_property_set_bool(OBJECT(&s->cpus), true, "realized",
|
||||
&error_abort);
|
||||
|
||||
/* boot rom */
|
||||
memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
|
||||
memmap[SIFIVE_U_MROM].size, &error_fatal);
|
||||
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
|
||||
mask_rom);
|
||||
|
||||
/* MMIO */
|
||||
s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base,
|
||||
@ -298,12 +348,32 @@ static void riscv_sifive_u_init(MachineState *machine)
|
||||
SIFIVE_U_PLIC_CONTEXT_STRIDE,
|
||||
memmap[SIFIVE_U_PLIC].size);
|
||||
sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
|
||||
serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
|
||||
serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ));
|
||||
/* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
|
||||
serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]); */
|
||||
serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic),
|
||||
SIFIVE_U_UART1_IRQ)); */
|
||||
sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
|
||||
memmap[SIFIVE_U_CLINT].size, smp_cpus,
|
||||
SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
|
||||
|
||||
for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) {
|
||||
plic_gpios[i] = qdev_get_gpio_in(DEVICE(s->plic), i);
|
||||
}
|
||||
|
||||
if (nd->used) {
|
||||
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
|
||||
qdev_set_nic_properties(DEVICE(&s->gem), nd);
|
||||
}
|
||||
object_property_set_int(OBJECT(&s->gem), GEM_REVISION, "revision",
|
||||
&error_abort);
|
||||
object_property_set_bool(OBJECT(&s->gem), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem), 0, memmap[SIFIVE_U_GEM].base);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gem), 0,
|
||||
plic_gpios[SIFIVE_U_GEM_IRQ]);
|
||||
}
|
||||
|
||||
static void riscv_sifive_u_machine_init(MachineClass *mc)
|
||||
@ -314,3 +384,27 @@ static void riscv_sifive_u_machine_init(MachineClass *mc)
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init)
|
||||
|
||||
static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = riscv_sifive_u_soc_realize;
|
||||
/* Reason: Uses serial_hds in realize function, thus can't be used twice */
|
||||
dc->user_creatable = false;
|
||||
}
|
||||
|
||||
static const TypeInfo riscv_sifive_u_soc_type_info = {
|
||||
.name = TYPE_RISCV_U_SOC,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(SiFiveUSoCState),
|
||||
.instance_init = riscv_sifive_u_soc_init,
|
||||
.class_init = riscv_sifive_u_soc_class_init,
|
||||
};
|
||||
|
||||
static void riscv_sifive_u_soc_register_types(void)
|
||||
{
|
||||
type_register_static(&riscv_sifive_u_soc_type_info);
|
||||
}
|
||||
|
||||
type_init(riscv_sifive_u_soc_register_types)
|
||||
|
@ -380,11 +380,11 @@ static void riscv_virt_board_init(MachineState *machine)
|
||||
for (i = 0; i < VIRTIO_COUNT; i++) {
|
||||
sysbus_create_simple("virtio-mmio",
|
||||
memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
|
||||
SIFIVE_PLIC(s->plic)->irqs[VIRTIO_IRQ + i]);
|
||||
qdev_get_gpio_in(DEVICE(s->plic), VIRTIO_IRQ + i));
|
||||
}
|
||||
|
||||
serial_mm_init(system_memory, memmap[VIRT_UART0].base,
|
||||
0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193,
|
||||
0, qdev_get_gpio_in(DEVICE(s->plic), UART0_IRQ), 399193,
|
||||
serial_hd(0), DEVICE_LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,25 @@
|
||||
#ifndef HW_SIFIVE_E_H
|
||||
#define HW_SIFIVE_E_H
|
||||
|
||||
#define TYPE_RISCV_E_SOC "riscv.sifive.e.soc"
|
||||
#define RISCV_E_SOC(obj) \
|
||||
OBJECT_CHECK(SiFiveESoCState, (obj), TYPE_RISCV_E_SOC)
|
||||
|
||||
typedef struct SiFiveESoCState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
RISCVHartArrayState cpus;
|
||||
DeviceState *plic;
|
||||
} SiFiveESoCState;
|
||||
|
||||
typedef struct SiFiveEState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
RISCVHartArrayState soc;
|
||||
DeviceState *plic;
|
||||
SiFiveESoCState soc;
|
||||
} SiFiveEState;
|
||||
|
||||
enum {
|
||||
|
@ -56,7 +56,6 @@ typedef struct SiFivePLICState {
|
||||
uint32_t *claimed;
|
||||
uint32_t *enable;
|
||||
QemuMutex lock;
|
||||
qemu_irq *irqs;
|
||||
|
||||
/* config */
|
||||
char *hart_config;
|
||||
|
@ -19,13 +19,28 @@
|
||||
#ifndef HW_SIFIVE_U_H
|
||||
#define HW_SIFIVE_U_H
|
||||
|
||||
#include "hw/net/cadence_gem.h"
|
||||
|
||||
#define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
|
||||
#define RISCV_U_SOC(obj) \
|
||||
OBJECT_CHECK(SiFiveUSoCState, (obj), TYPE_RISCV_U_SOC)
|
||||
|
||||
typedef struct SiFiveUSoCState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
RISCVHartArrayState cpus;
|
||||
DeviceState *plic;
|
||||
CadenceGEMState gem;
|
||||
} SiFiveUSoCState;
|
||||
|
||||
typedef struct SiFiveUState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
RISCVHartArrayState soc;
|
||||
DeviceState *plic;
|
||||
SiFiveUSoCState soc;
|
||||
void *fdt;
|
||||
int fdt_size;
|
||||
} SiFiveUState;
|
||||
@ -37,12 +52,14 @@ enum {
|
||||
SIFIVE_U_PLIC,
|
||||
SIFIVE_U_UART0,
|
||||
SIFIVE_U_UART1,
|
||||
SIFIVE_U_DRAM
|
||||
SIFIVE_U_DRAM,
|
||||
SIFIVE_U_GEM
|
||||
};
|
||||
|
||||
enum {
|
||||
SIFIVE_U_UART0_IRQ = 3,
|
||||
SIFIVE_U_UART1_IRQ = 4
|
||||
SIFIVE_U_UART1_IRQ = 4,
|
||||
SIFIVE_U_GEM_IRQ = 0x35
|
||||
};
|
||||
|
||||
enum {
|
||||
|
Loading…
Reference in New Issue
Block a user