aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-06 10:17:51 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-07-06 10:17:51 +0100
commita428594042bad540479733548b748b78a1a234b8 (patch)
tree7488582eb85f16f96d7287162d6adeecabf29d33
parentcee35138b59c6d6b0808c5fa644e3f063832860f (diff)
parent5a7f76a3d47a75290868968682c0585d380764a4 (diff)
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>
-rw-r--r--default-configs/riscv32-softmmu.mak2
-rw-r--r--default-configs/riscv64-softmmu.mak2
-rw-r--r--hw/riscv/sifive_e.c99
-rw-r--r--hw/riscv/sifive_plic.c6
-rw-r--r--hw/riscv/sifive_u.c148
-rw-r--r--hw/riscv/virt.c4
-rw-r--r--include/hw/riscv/sifive_e.h16
-rw-r--r--include/hw/riscv/sifive_plic.h1
-rw-r--r--include/hw/riscv/sifive_u.h25
9 files changed, 235 insertions, 68 deletions
diff --git a/default-configs/riscv32-softmmu.mak b/default-configs/riscv32-softmmu.mak
index 20e670d99c..7937c69e22 100644
--- a/default-configs/riscv32-softmmu.mak
+++ b/default-configs/riscv32-softmmu.mak
@@ -3,3 +3,5 @@
CONFIG_SERIAL=y
CONFIG_VIRTIO_MMIO=y
include virtio.mak
+
+CONFIG_CADENCE=y
diff --git a/default-configs/riscv64-softmmu.mak b/default-configs/riscv64-softmmu.mak
index 20e670d99c..7937c69e22 100644
--- a/default-configs/riscv64-softmmu.mak
+++ b/default-configs/riscv64-softmmu.mak
@@ -3,3 +3,5 @@
CONFIG_SERIAL=y
CONFIG_VIRTIO_MMIO=y
include virtio.mak
+
+CONFIG_CADENCE=y
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index e4ecb7aa4b..8a8dbe1c00 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -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)
diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 874de2ebaf..a91aeb97ab 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -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)
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index c05dcbba95..3a6ffeb437 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -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)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 34d48993a2..aeada2498d 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -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);
}
diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
index 12ad6d2ebb..7b6d8aed96 100644
--- a/include/hw/riscv/sifive_e.h
+++ b/include/hw/riscv/sifive_e.h
@@ -19,13 +19,25 @@
#ifndef HW_SIFIVE_E_H
#define HW_SIFIVE_E_H
-typedef struct SiFiveEState {
+#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 soc;
+ RISCVHartArrayState cpus;
DeviceState *plic;
+} SiFiveESoCState;
+
+typedef struct SiFiveEState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ SiFiveESoCState soc;
} SiFiveEState;
enum {
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
index 11a5a98df1..2f2af7e686 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/riscv/sifive_plic.h
@@ -56,7 +56,6 @@ typedef struct SiFivePLICState {
uint32_t *claimed;
uint32_t *enable;
QemuMutex lock;
- qemu_irq *irqs;
/* config */
char *hart_config;
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 94a390566e..e8b4d9ffa3 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -19,13 +19,28 @@
#ifndef HW_SIFIVE_U_H
#define HW_SIFIVE_U_H
-typedef struct SiFiveUState {
+#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 soc;
+ RISCVHartArrayState cpus;
DeviceState *plic;
+ CadenceGEMState gem;
+} SiFiveUSoCState;
+
+typedef struct SiFiveUState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ 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 {