From 0f8d4462498afd2f071cb5c837750b703a48ba18 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 19 Jul 2019 06:40:43 -0700 Subject: riscv: sifive_u: Add support for loading initrd Add support for loading initrd with "-initrd " to the sifive_u machine. This lets us boot into Linux without disk drive. Signed-off-by: Guenter Roeck Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 9910fa6..32167d0 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -67,7 +67,7 @@ static const struct MemmapEntry { #define GEM_REVISION 0x10070109 -static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, +static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint64_t mem_size, const char *cmdline) { void *fdt; @@ -244,11 +244,14 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } g_free(nodename); + + return fdt; } static void riscv_sifive_u_init(MachineState *machine) { const struct MemmapEntry *memmap = sifive_u_memmap; + void *fdt; SiFiveUState *s = g_new0(SiFiveUState, 1); MemoryRegion *system_memory = get_system_memory(); @@ -269,13 +272,24 @@ static void riscv_sifive_u_init(MachineState *machine) main_mem); /* create device tree */ - create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); + fdt = create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); riscv_find_and_load_firmware(machine, BIOS_FILENAME, memmap[SIFIVE_U_DRAM].base); if (machine->kernel_filename) { - riscv_load_kernel(machine->kernel_filename); + uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename); + + if (machine->initrd_filename) { + hwaddr start; + hwaddr end = riscv_load_initrd(machine->initrd_filename, + machine->ram_size, kernel_entry, + &start); + qemu_fdt_setprop_cell(fdt, "/chosen", + "linux,initrd-start", start); + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + end); + } } /* reset vector */ -- cgit v1.1 From 44e6dcd30a10e5b5d70cbf1bc248b146eabcec03 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 19 Jul 2019 06:40:44 -0700 Subject: riscv: sivive_u: Add dummy serial clock and aliases entry for uart The riscv uart needs valid clocks. This requires a refereence to the clock node. Since the SOC clock is not emulated by qemu, add a reference to a fixed clock instead. The clock-frequency entry in the uart node does not seem to be necessary, so drop it. In addition to a reference to the clock, the driver also needs an aliases entry for the serial node. Add it as well. Without this patch, the serial driver fails to instantiate with the following error message. sifive-serial 10013000.uart: unable to find controller clock sifive-serial: probe of 10013000.uart failed with error -2 when trying to boot Linux. Signed-off-by: Guenter Roeck Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 32167d0..8313f26 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -76,6 +76,7 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, char *nodename; char ethclk_names[] = "pclk\0hclk\0tx_clk"; uint32_t plic_phandle, ethclk_phandle, phandle = 1; + uint32_t uartclk_phandle; fdt = s->fdt = create_device_tree(&s->fdt_size); if (!fdt) { @@ -226,6 +227,17 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0); g_free(nodename); + uartclk_phandle = phandle++; + nodename = g_strdup_printf("/soc/uartclk"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock"); + qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 3686400); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", uartclk_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", uartclk_phandle); + uartclk_phandle = qemu_fdt_get_phandle(fdt, nodename); + g_free(nodename); + nodename = g_strdup_printf("/soc/uart@%lx", (long)memmap[SIFIVE_U_UART0].base); qemu_fdt_add_subnode(fdt, nodename); @@ -233,8 +245,7 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_UART0].base, 0x0, memmap[SIFIVE_U_UART0].size); - qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", - SIFIVE_U_CLOCK_FREQ / 2); + qemu_fdt_setprop_cells(fdt, nodename, "clocks", uartclk_phandle); qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle); qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_UART0_IRQ); @@ -243,6 +254,10 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, if (cmdline) { qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } + + qemu_fdt_add_subnode(fdt, "/aliases"); + qemu_fdt_setprop_string(fdt, "/aliases", "serial0", nodename); + g_free(nodename); return fdt; -- cgit v1.1 From 04ece4f8205b19b31c4c6ebc481c9653c7fadd39 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 19 Jul 2019 06:40:45 -0700 Subject: riscv: sifive_u: Fix clock-names property for ethernet node The correct property name is clock-names, not clocks-names. Without this patch, the Ethernet driver fails to instantiate with the following error. macb 100900fc.ethernet: failed to get macb_clk (-2) macb: probe of 100900fc.ethernet failed with error -2 Signed-off-by: Guenter Roeck Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 8313f26..ae5a16e 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -215,7 +215,7 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ); qemu_fdt_setprop_cells(fdt, nodename, "clocks", ethclk_phandle, ethclk_phandle, ethclk_phandle); - qemu_fdt_setprop(fdt, nodename, "clocks-names", ethclk_names, + qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names, sizeof(ethclk_names)); qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 1); qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0); -- cgit v1.1 From f14d65e8992499a179ecdf1901137ce496a0a607 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 30 Jul 2019 16:35:21 -0700 Subject: riscv: plic: Remove unused interrupt functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alistair Francis Reviewed-by: Jonathan Behrens Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Chih-Min Chao Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_plic.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c index 64a1a10..98e4304 100644 --- a/hw/riscv/sifive_plic.c +++ b/hw/riscv/sifive_plic.c @@ -162,18 +162,6 @@ static void sifive_plic_update(SiFivePLICState *plic) } } -void sifive_plic_raise_irq(SiFivePLICState *plic, uint32_t irq) -{ - sifive_plic_set_pending(plic, irq, true); - sifive_plic_update(plic); -} - -void sifive_plic_lower_irq(SiFivePLICState *plic, uint32_t irq) -{ - sifive_plic_set_pending(plic, irq, false); - sifive_plic_update(plic); -} - static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid) { int i, j; -- cgit v1.1 From 751f8f41331951077f3fc17dd245c23b5a18b595 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 16 Aug 2019 06:09:35 -0700 Subject: riscv: Add a helper routine for finding firmware This adds a helper routine for finding firmware. It is currently used only for "-bios default" case. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/boot.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'hw') diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 4c63b5c..10f7991 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -69,13 +69,7 @@ void riscv_find_and_load_firmware(MachineState *machine, * so then in the future we can make "-bios default" the default option * if no -bios option is set without breaking anything. */ - firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - default_machine_firmware); - if (firmware_filename == NULL) { - error_report("Unable to load the default RISC-V firmware \"%s\"", - default_machine_firmware); - exit(1); - } + firmware_filename = riscv_find_firmware(default_machine_firmware); } else { firmware_filename = machine->firmware; } @@ -90,6 +84,20 @@ void riscv_find_and_load_firmware(MachineState *machine, } } +char *riscv_find_firmware(const char *firmware_filename) +{ + char *filename; + + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware_filename); + if (filename == NULL) { + error_report("Unable to load the RISC-V firmware \"%s\"", + firmware_filename); + exit(1); + } + + return filename; +} + target_ulong riscv_load_firmware(const char *firmware_filename, hwaddr firmware_load_addr) { -- cgit v1.1 From 49dd180e4f3e0af8ab8a54fec5058b6cd89e5942 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 16 Aug 2019 06:09:36 -0700 Subject: riscv: Resolve full path of the given bios image At present when "-bios image" is supplied, we just use the straight path without searching for the configured data directories. Like "-bios default", we add the same logic so that "-L" actually works. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/boot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 10f7991..2e92fb0 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -72,14 +72,14 @@ void riscv_find_and_load_firmware(MachineState *machine, firmware_filename = riscv_find_firmware(default_machine_firmware); } else { firmware_filename = machine->firmware; + if (strcmp(firmware_filename, "none")) { + firmware_filename = riscv_find_firmware(firmware_filename); + } } if (strcmp(firmware_filename, "none")) { /* If not "none" load the firmware */ riscv_load_firmware(firmware_filename, firmware_load_addr); - } - - if (!strcmp(machine->firmware, "default")) { g_free(firmware_filename); } } -- cgit v1.1 From 9a2551ed6f946e96cd54ea3f3499d785a1f27c3d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 5 Sep 2019 08:55:16 -0700 Subject: riscv: sifive_test: Add reset functionality This adds a reset opcode for sifive_test device to trigger a system reset for testing purpose. Signed-off-by: Bin Meng Reviewed-by: Palmer Dabbelt Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_test.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'hw') diff --git a/hw/riscv/sifive_test.c b/hw/riscv/sifive_test.c index afbb3aa..3557e16 100644 --- a/hw/riscv/sifive_test.c +++ b/hw/riscv/sifive_test.c @@ -22,6 +22,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "qemu/module.h" +#include "sysemu/runstate.h" #include "target/riscv/cpu.h" #include "hw/hw.h" #include "hw/riscv/sifive_test.h" @@ -42,6 +43,9 @@ static void sifive_test_write(void *opaque, hwaddr addr, exit(code); case FINISHER_PASS: exit(0); + case FINISHER_RESET: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; default: break; } -- cgit v1.1 From 1faa8f0138cf8d65b8fa59a3fd325e448a444bc4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:48 -0700 Subject: riscv: hw: Remove duplicated "hw/hw.h" inclusion Commit a27bd6c779ba ("Include hw/qdev-properties.h less") wrongly added "hw/hw.h" to sifive_prci.c and sifive_test.c. Another inclusion of "hw/hw.h" was later added via commit 650d103d3ea9 ("Include hw/hw.h exactly where needed"), that resulted in duplicated inclusion of "hw/hw.h". Fixes: a27bd6c779ba ("Include hw/qdev-properties.h less") Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_prci.c | 1 - hw/riscv/sifive_test.c | 1 - 2 files changed, 2 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c index 9837b61..562bc3d 100644 --- a/hw/riscv/sifive_prci.c +++ b/hw/riscv/sifive_prci.c @@ -19,7 +19,6 @@ */ #include "qemu/osdep.h" -#include "hw/hw.h" #include "hw/sysbus.h" #include "qemu/module.h" #include "target/riscv/cpu.h" diff --git a/hw/riscv/sifive_test.c b/hw/riscv/sifive_test.c index 3557e16..7117409 100644 --- a/hw/riscv/sifive_test.c +++ b/hw/riscv/sifive_test.c @@ -19,7 +19,6 @@ */ #include "qemu/osdep.h" -#include "hw/hw.h" #include "hw/sysbus.h" #include "qemu/module.h" #include "sysemu/runstate.h" -- cgit v1.1 From 24e398d06b42e3340be2c7ab54856802b82a1788 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:50 -0700 Subject: riscv: hw: Remove superfluous "linux, phandle" property "linux,phandle" property is optional. Remove all instances in the sifive_u, virt and spike machine device trees. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 4 ---- hw/riscv/spike.c | 1 - hw/riscv/virt.c | 3 --- 3 files changed, 8 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index ae5a16e..0d9ff76 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -126,7 +126,6 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); qemu_fdt_add_subnode(fdt, intc); qemu_fdt_setprop_cell(fdt, intc, "phandle", cpu_phandle); - qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", cpu_phandle); qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); @@ -185,7 +184,6 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "riscv,max-priority", 7); qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 0x35); qemu_fdt_setprop_cells(fdt, nodename, "phandle", plic_phandle); - qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(cells); g_free(nodename); @@ -198,7 +196,6 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", SIFIVE_U_GEM_CLOCK_FREQ); qemu_fdt_setprop_cell(fdt, nodename, "phandle", ethclk_phandle); - qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", ethclk_phandle); ethclk_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(nodename); @@ -234,7 +231,6 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 3686400); qemu_fdt_setprop_cell(fdt, nodename, "phandle", uartclk_phandle); - qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", uartclk_phandle); uartclk_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(nodename); diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 7c04bd5..d60415d 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -112,7 +112,6 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); qemu_fdt_add_subnode(fdt, intc); qemu_fdt_setprop_cell(fdt, intc, "phandle", 1); - qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", 1); qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 9bced28..7809170 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -170,11 +170,9 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); qemu_fdt_setprop_cell(fdt, nodename, "phandle", cpu_phandle); - qemu_fdt_setprop_cell(fdt, nodename, "linux,phandle", cpu_phandle); intc_phandle = phandle++; qemu_fdt_add_subnode(fdt, intc); qemu_fdt_setprop_cell(fdt, intc, "phandle", intc_phandle); - qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", intc_phandle); qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); @@ -250,7 +248,6 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "riscv,max-priority", 7); qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", VIRTIO_NDEV); qemu_fdt_setprop_cells(fdt, nodename, "phandle", plic_phandle); - qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(cells); g_free(nodename); -- cgit v1.1 From 04e7edd108308b03f8066f4385fd317aa620ea70 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:51 -0700 Subject: riscv: hw: Use qemu_fdt_setprop_cell() for property with only 1 cell Some of the properties only have 1 cell so we should use qemu_fdt_setprop_cell() instead of qemu_fdt_setprop_cells(). Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 18 +++++++++--------- hw/riscv/virt.c | 24 ++++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 0d9ff76..762223c 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -183,7 +183,7 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 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", 0x35); - qemu_fdt_setprop_cells(fdt, nodename, "phandle", plic_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(cells); g_free(nodename); @@ -208,20 +208,20 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 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_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ); qemu_fdt_setprop_cells(fdt, nodename, "clocks", ethclk_phandle, ethclk_phandle, ethclk_phandle); qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names, sizeof(ethclk_names)); - qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 1); - qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0); + qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1); + qemu_fdt_setprop_cell(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); + qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0); g_free(nodename); uartclk_phandle = phandle++; @@ -241,9 +241,9 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_UART0].base, 0x0, memmap[SIFIVE_U_UART0].size); - qemu_fdt_setprop_cells(fdt, nodename, "clocks", uartclk_phandle); - qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle); - qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_UART0_IRQ); + qemu_fdt_setprop_cell(fdt, nodename, "clocks", uartclk_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_UART0_IRQ); qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 7809170..6852178 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -233,8 +233,8 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, nodename = g_strdup_printf("/soc/interrupt-controller@%lx", (long)memmap[VIRT_PLIC].base); qemu_fdt_add_subnode(fdt, nodename); - qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", - FDT_PLIC_ADDR_CELLS); + qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", + FDT_PLIC_ADDR_CELLS); qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", FDT_PLIC_INT_CELLS); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0"); @@ -247,7 +247,7 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, 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", VIRTIO_NDEV); - qemu_fdt_setprop_cells(fdt, nodename, "phandle", plic_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(cells); g_free(nodename); @@ -260,19 +260,19 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size, 0x0, memmap[VIRT_VIRTIO].size); - qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle); - qemu_fdt_setprop_cells(fdt, nodename, "interrupts", VIRTIO_IRQ + i); + qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", VIRTIO_IRQ + i); g_free(nodename); } nodename = g_strdup_printf("/soc/pci@%lx", (long) memmap[VIRT_PCIE_ECAM].base); qemu_fdt_add_subnode(fdt, nodename); - qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", - FDT_PCI_ADDR_CELLS); - qemu_fdt_setprop_cells(fdt, nodename, "#interrupt-cells", - FDT_PCI_INT_CELLS); - qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0x2); + qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", + FDT_PCI_ADDR_CELLS); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", + FDT_PCI_INT_CELLS); + qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0x2); qemu_fdt_setprop_string(fdt, nodename, "compatible", "pci-host-ecam-generic"); qemu_fdt_setprop_string(fdt, nodename, "device_type", "pci"); @@ -309,8 +309,8 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, 0x0, memmap[VIRT_UART0].base, 0x0, memmap[VIRT_UART0].size); qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 3686400); - qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle); - qemu_fdt_setprop_cells(fdt, nodename, "interrupts", UART0_IRQ); + qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", UART0_IRQ); qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); -- cgit v1.1 From b179685b6a8c3738161d562985a5aa3ad0a65839 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:52 -0700 Subject: riscv: hw: Remove not needed PLIC properties in device tree This removes "reg-names" and "riscv,max-priority" properties of the PLIC node from device tree. Signed-off-by: Bin Meng Reviewed-by: Jonathan Behrens Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 2 -- hw/riscv/virt.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 762223c..e8acdd9 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -180,8 +180,6 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 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", 0x35); qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 6852178..090512b 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -244,8 +244,6 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[VIRT_PLIC].base, 0x0, memmap[VIRT_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", VIRTIO_NDEV); qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); plic_phandle = qemu_fdt_get_phandle(fdt, nodename); -- cgit v1.1 From 9f79638ec55411d5d120a15bd2181cc862e4fba1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:53 -0700 Subject: riscv: hw: Change create_fdt() to return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to return fdt at the end of create_fdt() because it's already saved in s->fdt. Signed-off-by: Bin Meng Reviewed-by: Chih-Min Chao Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 11 ++++------- hw/riscv/virt.c | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index e8acdd9..32d8cee 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -67,7 +67,7 @@ static const struct MemmapEntry { #define GEM_REVISION 0x10070109 -static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, +static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint64_t mem_size, const char *cmdline) { void *fdt; @@ -253,14 +253,11 @@ static void *create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, "/aliases", "serial0", nodename); g_free(nodename); - - return fdt; } static void riscv_sifive_u_init(MachineState *machine) { const struct MemmapEntry *memmap = sifive_u_memmap; - void *fdt; SiFiveUState *s = g_new0(SiFiveUState, 1); MemoryRegion *system_memory = get_system_memory(); @@ -281,7 +278,7 @@ static void riscv_sifive_u_init(MachineState *machine) main_mem); /* create device tree */ - fdt = create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); + create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); riscv_find_and_load_firmware(machine, BIOS_FILENAME, memmap[SIFIVE_U_DRAM].base); @@ -294,9 +291,9 @@ static void riscv_sifive_u_init(MachineState *machine) hwaddr end = riscv_load_initrd(machine->initrd_filename, machine->ram_size, kernel_entry, &start); - qemu_fdt_setprop_cell(fdt, "/chosen", + qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-start", start); - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", end); } } diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 090512b..d36f562 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -112,7 +112,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, 0x1800, 0, 0, 0x7); } -static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, +static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, uint64_t mem_size, const char *cmdline) { void *fdt; @@ -316,8 +316,6 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } g_free(nodename); - - return fdt; } @@ -373,7 +371,6 @@ static void riscv_virt_board_init(MachineState *machine) size_t plic_hart_config_len; int i; unsigned int smp_cpus = machine->smp.cpus; - void *fdt; /* Initialize SOC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc), @@ -392,7 +389,7 @@ static void riscv_virt_board_init(MachineState *machine) main_mem); /* create device tree */ - fdt = create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); + create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); /* boot rom */ memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom", @@ -411,9 +408,9 @@ static void riscv_virt_board_init(MachineState *machine) hwaddr end = riscv_load_initrd(machine->initrd_filename, machine->ram_size, kernel_entry, &start); - qemu_fdt_setprop_cell(fdt, "/chosen", + qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-start", start); - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", end); } } -- cgit v1.1 From a2360c854fb56f9506d81be8b86ba577c0dbefc3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:54 -0700 Subject: riscv: hw: Change to use qemu_log_mask(LOG_GUEST_ERROR, ...) instead Replace the call to hw_error() with qemu_log_mask(LOG_GUEST_ERROR,...) in various sifive models. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_prci.c | 8 +++++--- hw/riscv/sifive_test.c | 5 +++-- hw/riscv/sifive_uart.c | 9 +++++---- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c index 562bc3d..982fbb2 100644 --- a/hw/riscv/sifive_prci.c +++ b/hw/riscv/sifive_prci.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qemu/log.h" #include "qemu/module.h" #include "target/riscv/cpu.h" #include "hw/hw.h" @@ -38,7 +39,8 @@ static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size) case SIFIVE_PRCI_PLLOUTDIV: return s->plloutdiv; } - hw_error("%s: read: addr=0x%x\n", __func__, (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%x\n", + __func__, (int)addr); return 0; } @@ -66,8 +68,8 @@ static void sifive_prci_write(void *opaque, hwaddr addr, s->plloutdiv = (uint32_t) val64; break; default: - hw_error("%s: bad write: addr=0x%x v=0x%x\n", - __func__, (int)addr, (int)val64); + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n", + __func__, (int)addr, (int)val64); } } diff --git a/hw/riscv/sifive_test.c b/hw/riscv/sifive_test.c index 7117409..aa544e7 100644 --- a/hw/riscv/sifive_test.c +++ b/hw/riscv/sifive_test.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" +#include "qemu/log.h" #include "qemu/module.h" #include "sysemu/runstate.h" #include "target/riscv/cpu.h" @@ -49,8 +50,8 @@ static void sifive_test_write(void *opaque, hwaddr addr, break; } } - hw_error("%s: write: addr=0x%x val=0x%016" PRIx64 "\n", - __func__, (int)addr, val64); + qemu_log_mask(LOG_GUEST_ERROR, "%s: write: addr=0x%x val=0x%016" PRIx64 "\n", + __func__, (int)addr, val64); } static const MemoryRegionOps sifive_test_ops = { diff --git a/hw/riscv/sifive_uart.c b/hw/riscv/sifive_uart.c index 9de42b1..215990b 100644 --- a/hw/riscv/sifive_uart.c +++ b/hw/riscv/sifive_uart.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu/log.h" #include "hw/sysbus.h" #include "chardev/char.h" #include "chardev/char-fe.h" @@ -95,8 +96,8 @@ uart_read(void *opaque, hwaddr addr, unsigned int size) return s->div; } - hw_error("%s: bad read: addr=0x%x\n", - __func__, (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read: addr=0x%x\n", + __func__, (int)addr); return 0; } @@ -127,8 +128,8 @@ uart_write(void *opaque, hwaddr addr, s->div = val64; return; } - hw_error("%s: bad write: addr=0x%x v=0x%x\n", - __func__, (int)addr, (int)value); + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n", + __func__, (int)addr, (int)value); } static const MemoryRegionOps uart_ops = { -- cgit v1.1 From 131f0932cf0194355cbcac326c93c2830ebd5148 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:55 -0700 Subject: riscv: hw: Remove the unnecessary include of target/riscv/cpu.h The inclusion of "target/riscv/cpu.h" is unnecessary in various sifive model drivers. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_prci.c | 1 - hw/riscv/sifive_test.c | 1 - hw/riscv/sifive_uart.c | 1 - 3 files changed, 3 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c index 982fbb2..c413f0c 100644 --- a/hw/riscv/sifive_prci.c +++ b/hw/riscv/sifive_prci.c @@ -22,7 +22,6 @@ #include "hw/sysbus.h" #include "qemu/log.h" #include "qemu/module.h" -#include "target/riscv/cpu.h" #include "hw/hw.h" #include "hw/riscv/sifive_prci.h" diff --git a/hw/riscv/sifive_test.c b/hw/riscv/sifive_test.c index aa544e7..339195c 100644 --- a/hw/riscv/sifive_test.c +++ b/hw/riscv/sifive_test.c @@ -23,7 +23,6 @@ #include "qemu/log.h" #include "qemu/module.h" #include "sysemu/runstate.h" -#include "target/riscv/cpu.h" #include "hw/hw.h" #include "hw/riscv/sifive_test.h" diff --git a/hw/riscv/sifive_uart.c b/hw/riscv/sifive_uart.c index 215990b..a403ae9 100644 --- a/hw/riscv/sifive_uart.c +++ b/hw/riscv/sifive_uart.c @@ -22,7 +22,6 @@ #include "hw/sysbus.h" #include "chardev/char.h" #include "chardev/char-fe.h" -#include "target/riscv/cpu.h" #include "hw/hw.h" #include "hw/irq.h" #include "hw/riscv/sifive_uart.h" -- cgit v1.1 From 9baa9f7c9f651dfc7ee8a4abd46c4036f6841f64 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:57 -0700 Subject: riscv: sifive_u: Remove the unnecessary include of prci header sifive_u machine does not use PRCI as of today. Remove the prci header inclusion. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 1 - 1 file changed, 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 32d8cee..2947e06 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -38,7 +38,6 @@ #include "hw/riscv/sifive_plic.h" #include "hw/riscv/sifive_clint.h" #include "hw/riscv/sifive_uart.h" -#include "hw/riscv/sifive_prci.h" #include "hw/riscv/sifive_u.h" #include "hw/riscv/boot.h" #include "chardev/char.h" -- cgit v1.1 From 56449d20e937e807e4fc35fa3e5a38f7636e7046 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:58 -0700 Subject: riscv: sifive: Rename sifive_prci.{c, h} to sifive_e_prci.{c, h} Current SiFive PRCI model only works with sifive_e machine, as it only emulates registers or PRCI block in the FE310 SoC. Rename the file name to make it clear that it is for sifive_e. This also prefix "sifive_e"/"SIFIVE_E" for all macros, variables and functions. Signed-off-by: Bin Meng Reviewed-by: Chih-Min Chao Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/Makefile.objs | 2 +- hw/riscv/sifive_e.c | 4 +- hw/riscv/sifive_e_prci.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ hw/riscv/sifive_prci.c | 125 ----------------------------------------------- 4 files changed, 127 insertions(+), 128 deletions(-) create mode 100644 hw/riscv/sifive_e_prci.c delete mode 100644 hw/riscv/sifive_prci.c (limited to 'hw') diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs index eb9d4f9..c859697 100644 --- a/hw/riscv/Makefile.objs +++ b/hw/riscv/Makefile.objs @@ -2,9 +2,9 @@ obj-y += boot.o obj-$(CONFIG_SPIKE) += riscv_htif.o obj-$(CONFIG_HART) += riscv_hart.o obj-$(CONFIG_SIFIVE_E) += sifive_e.o +obj-$(CONFIG_SIFIVE_E) += sifive_e_prci.o obj-$(CONFIG_SIFIVE) += sifive_clint.o obj-$(CONFIG_SIFIVE) += sifive_gpio.o -obj-$(CONFIG_SIFIVE) += sifive_prci.o obj-$(CONFIG_SIFIVE) += sifive_plic.o obj-$(CONFIG_SIFIVE) += sifive_test.o obj-$(CONFIG_SIFIVE_U) += sifive_u.o diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 792d75a..1428a99 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -40,9 +40,9 @@ #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_plic.h" #include "hw/riscv/sifive_clint.h" -#include "hw/riscv/sifive_prci.h" #include "hw/riscv/sifive_uart.h" #include "hw/riscv/sifive_e.h" +#include "hw/riscv/sifive_e_prci.h" #include "hw/riscv/boot.h" #include "chardev/char.h" #include "sysemu/arch_init.h" @@ -174,7 +174,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); sifive_mmio_emulate(sys_mem, "riscv.sifive.e.aon", memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size); - sifive_prci_create(memmap[SIFIVE_E_PRCI].base); + sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base); /* GPIO */ diff --git a/hw/riscv/sifive_e_prci.c b/hw/riscv/sifive_e_prci.c new file mode 100644 index 0000000..b6d32db --- /dev/null +++ b/hw/riscv/sifive_e_prci.c @@ -0,0 +1,124 @@ +/* + * QEMU SiFive E PRCI (Power, Reset, Clock, Interrupt) + * + * Copyright (c) 2017 SiFive, Inc. + * + * Simple model of the PRCI to emulate register reads made by the SDK BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/hw.h" +#include "hw/riscv/sifive_e_prci.h" + +static uint64_t sifive_e_prci_read(void *opaque, hwaddr addr, unsigned int size) +{ + SiFiveEPRCIState *s = opaque; + switch (addr) { + case SIFIVE_E_PRCI_HFROSCCFG: + return s->hfrosccfg; + case SIFIVE_E_PRCI_HFXOSCCFG: + return s->hfxosccfg; + case SIFIVE_E_PRCI_PLLCFG: + return s->pllcfg; + case SIFIVE_E_PRCI_PLLOUTDIV: + return s->plloutdiv; + } + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%x\n", + __func__, (int)addr); + return 0; +} + +static void sifive_e_prci_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveEPRCIState *s = opaque; + switch (addr) { + case SIFIVE_E_PRCI_HFROSCCFG: + s->hfrosccfg = (uint32_t) val64; + /* OSC stays ready */ + s->hfrosccfg |= SIFIVE_E_PRCI_HFROSCCFG_RDY; + break; + case SIFIVE_E_PRCI_HFXOSCCFG: + s->hfxosccfg = (uint32_t) val64; + /* OSC stays ready */ + s->hfxosccfg |= SIFIVE_E_PRCI_HFXOSCCFG_RDY; + break; + case SIFIVE_E_PRCI_PLLCFG: + s->pllcfg = (uint32_t) val64; + /* PLL stays locked */ + s->pllcfg |= SIFIVE_E_PRCI_PLLCFG_LOCK; + break; + case SIFIVE_E_PRCI_PLLOUTDIV: + s->plloutdiv = (uint32_t) val64; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n", + __func__, (int)addr, (int)val64); + } +} + +static const MemoryRegionOps sifive_e_prci_ops = { + .read = sifive_e_prci_read, + .write = sifive_e_prci_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static void sifive_e_prci_init(Object *obj) +{ + SiFiveEPRCIState *s = SIFIVE_E_PRCI(obj); + + memory_region_init_io(&s->mmio, obj, &sifive_e_prci_ops, s, + TYPE_SIFIVE_E_PRCI, 0x8000); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + s->hfrosccfg = (SIFIVE_E_PRCI_HFROSCCFG_RDY | SIFIVE_E_PRCI_HFROSCCFG_EN); + s->hfxosccfg = (SIFIVE_E_PRCI_HFROSCCFG_RDY | SIFIVE_E_PRCI_HFROSCCFG_EN); + s->pllcfg = (SIFIVE_E_PRCI_PLLCFG_REFSEL | SIFIVE_E_PRCI_PLLCFG_BYPASS | + SIFIVE_E_PRCI_PLLCFG_LOCK); + s->plloutdiv = SIFIVE_E_PRCI_PLLOUTDIV_DIV1; +} + +static const TypeInfo sifive_e_prci_info = { + .name = TYPE_SIFIVE_E_PRCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveEPRCIState), + .instance_init = sifive_e_prci_init, +}; + +static void sifive_e_prci_register_types(void) +{ + type_register_static(&sifive_e_prci_info); +} + +type_init(sifive_e_prci_register_types) + + +/* + * Create PRCI device. + */ +DeviceState *sifive_e_prci_create(hwaddr addr) +{ + DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_E_PRCI); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + return dev; +} diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c deleted file mode 100644 index c413f0c..0000000 --- a/hw/riscv/sifive_prci.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt) - * - * Copyright (c) 2017 SiFive, Inc. - * - * Simple model of the PRCI to emulate register reads made by the SDK BSP - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or later, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" -#include "qemu/log.h" -#include "qemu/module.h" -#include "hw/hw.h" -#include "hw/riscv/sifive_prci.h" - -static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size) -{ - SiFivePRCIState *s = opaque; - switch (addr) { - case SIFIVE_PRCI_HFROSCCFG: - return s->hfrosccfg; - case SIFIVE_PRCI_HFXOSCCFG: - return s->hfxosccfg; - case SIFIVE_PRCI_PLLCFG: - return s->pllcfg; - case SIFIVE_PRCI_PLLOUTDIV: - return s->plloutdiv; - } - qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%x\n", - __func__, (int)addr); - return 0; -} - -static void sifive_prci_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned int size) -{ - SiFivePRCIState *s = opaque; - switch (addr) { - case SIFIVE_PRCI_HFROSCCFG: - s->hfrosccfg = (uint32_t) val64; - /* OSC stays ready */ - s->hfrosccfg |= SIFIVE_PRCI_HFROSCCFG_RDY; - break; - case SIFIVE_PRCI_HFXOSCCFG: - s->hfxosccfg = (uint32_t) val64; - /* OSC stays ready */ - s->hfxosccfg |= SIFIVE_PRCI_HFXOSCCFG_RDY; - break; - case SIFIVE_PRCI_PLLCFG: - s->pllcfg = (uint32_t) val64; - /* PLL stays locked */ - s->pllcfg |= SIFIVE_PRCI_PLLCFG_LOCK; - break; - case SIFIVE_PRCI_PLLOUTDIV: - s->plloutdiv = (uint32_t) val64; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n", - __func__, (int)addr, (int)val64); - } -} - -static const MemoryRegionOps sifive_prci_ops = { - .read = sifive_prci_read, - .write = sifive_prci_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4 - } -}; - -static void sifive_prci_init(Object *obj) -{ - SiFivePRCIState *s = SIFIVE_PRCI(obj); - - memory_region_init_io(&s->mmio, obj, &sifive_prci_ops, s, - TYPE_SIFIVE_PRCI, 0x8000); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); - - s->hfrosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN); - s->hfxosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN); - s->pllcfg = (SIFIVE_PRCI_PLLCFG_REFSEL | SIFIVE_PRCI_PLLCFG_BYPASS | - SIFIVE_PRCI_PLLCFG_LOCK); - s->plloutdiv = SIFIVE_PRCI_PLLOUTDIV_DIV1; - -} - -static const TypeInfo sifive_prci_info = { - .name = TYPE_SIFIVE_PRCI, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFivePRCIState), - .instance_init = sifive_prci_init, -}; - -static void sifive_prci_register_types(void) -{ - type_register_static(&sifive_prci_info); -} - -type_init(sifive_prci_register_types) - - -/* - * Create PRCI device. - */ -DeviceState *sifive_prci_create(hwaddr addr) -{ - DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PRCI); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); - return dev; -} -- cgit v1.1 From 1a5938a01fab0a04c322734f683e2348fc9d30b3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:19:59 -0700 Subject: riscv: sifive_e: prci: Fix a typo of hfxosccfg register programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For hfxosccfg register programming, SIFIVE_E_PRCI_HFXOSCCFG_RDY and SIFIVE_E_PRCI_HFXOSCCFG_EN should be used. Signed-off-by: Bin Meng Acked-by: Alistair Francis Reviewed-by: Chih-Min Chao Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_e_prci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_e_prci.c b/hw/riscv/sifive_e_prci.c index b6d32db..bfe9b13 100644 --- a/hw/riscv/sifive_e_prci.c +++ b/hw/riscv/sifive_e_prci.c @@ -91,7 +91,7 @@ static void sifive_e_prci_init(Object *obj) sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); s->hfrosccfg = (SIFIVE_E_PRCI_HFROSCCFG_RDY | SIFIVE_E_PRCI_HFROSCCFG_EN); - s->hfxosccfg = (SIFIVE_E_PRCI_HFROSCCFG_RDY | SIFIVE_E_PRCI_HFROSCCFG_EN); + s->hfxosccfg = (SIFIVE_E_PRCI_HFXOSCCFG_RDY | SIFIVE_E_PRCI_HFXOSCCFG_EN); s->pllcfg = (SIFIVE_E_PRCI_PLLCFG_REFSEL | SIFIVE_E_PRCI_PLLCFG_BYPASS | SIFIVE_E_PRCI_PLLCFG_LOCK); s->plloutdiv = SIFIVE_E_PRCI_PLLOUTDIV_DIV1; -- cgit v1.1 From d0730344fd8f27ce5e98efd43efe594ae3a00087 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:00 -0700 Subject: riscv: sifive_e: prci: Update the PRCI register block size Currently the PRCI register block size is set to 0x8000, but in fact 0x1000 is enough, which is also what the manual says. Signed-off-by: Bin Meng Reviewed-by: Chih-Min Chao Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_e_prci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_e_prci.c b/hw/riscv/sifive_e_prci.c index bfe9b13..a1c0d44 100644 --- a/hw/riscv/sifive_e_prci.c +++ b/hw/riscv/sifive_e_prci.c @@ -87,7 +87,7 @@ static void sifive_e_prci_init(Object *obj) SiFiveEPRCIState *s = SIFIVE_E_PRCI(obj); memory_region_init_io(&s->mmio, obj, &sifive_e_prci_ops, s, - TYPE_SIFIVE_E_PRCI, 0x8000); + TYPE_SIFIVE_E_PRCI, SIFIVE_E_PRCI_REG_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); s->hfrosccfg = (SIFIVE_E_PRCI_HFROSCCFG_RDY | SIFIVE_E_PRCI_HFROSCCFG_EN); -- cgit v1.1 From 68c9a9b3eb5897bf39e6aa0aa72e5761f3bc9725 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:01 -0700 Subject: riscv: sifive_e: Drop sifive_mmio_emulate() Use create_unimplemented_device() instead. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/Kconfig | 1 + hw/riscv/sifive_e.c | 23 ++++++++--------------- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'hw') diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 8674211..33e54b0 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -12,6 +12,7 @@ config SIFIVE_E bool select HART select SIFIVE + select UNIMP config SIFIVE_U bool diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 1428a99..0f9d641 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -36,6 +36,7 @@ #include "hw/loader.h" #include "hw/sysbus.h" #include "hw/char/serial.h" +#include "hw/misc/unimp.h" #include "target/riscv/cpu.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_plic.h" @@ -74,14 +75,6 @@ static const struct MemmapEntry { [SIFIVE_E_DTIM] = { 0x80000000, 0x4000 } }; -static void sifive_mmio_emulate(MemoryRegion *parent, const char *name, - uintptr_t offset, uintptr_t length) -{ - MemoryRegion *mock_mmio = g_new(MemoryRegion, 1); - memory_region_init_ram(mock_mmio, NULL, name, length, &error_fatal); - memory_region_add_subregion(parent, offset, mock_mmio); -} - static void riscv_sifive_e_init(MachineState *machine) { const struct MemmapEntry *memmap = sifive_e_memmap; @@ -172,7 +165,7 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) sifive_clint_create(memmap[SIFIVE_E_CLINT].base, memmap[SIFIVE_E_CLINT].size, ms->smp.cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.aon", + create_unimplemented_device("riscv.sifive.e.aon", memmap[SIFIVE_E_AON].base, memmap[SIFIVE_E_AON].size); sifive_e_prci_create(memmap[SIFIVE_E_PRCI].base); @@ -199,19 +192,19 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp) sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART0].base, serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ)); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi0", + create_unimplemented_device("riscv.sifive.e.qspi0", memmap[SIFIVE_E_QSPI0].base, memmap[SIFIVE_E_QSPI0].size); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm0", + create_unimplemented_device("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), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART1_IRQ)); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi1", + create_unimplemented_device("riscv.sifive.e.qspi1", memmap[SIFIVE_E_QSPI1].base, memmap[SIFIVE_E_QSPI1].size); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm1", + create_unimplemented_device("riscv.sifive.e.pwm1", memmap[SIFIVE_E_PWM1].base, memmap[SIFIVE_E_PWM1].size); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi2", + create_unimplemented_device("riscv.sifive.e.qspi2", memmap[SIFIVE_E_QSPI2].base, memmap[SIFIVE_E_QSPI2].size); - sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm2", + create_unimplemented_device("riscv.sifive.e.pwm2", memmap[SIFIVE_E_PWM2].base, memmap[SIFIVE_E_PWM2].size); /* Flash memory */ -- cgit v1.1 From 91c985851dd57df3b003e7bd91f1cf544b3a288d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:03 -0700 Subject: riscv: hart: Extract hart realize to a separate routine Currently riscv_harts_realize() creates all harts based on the same cpu type given in the hart array property. With current implementation it can only create homogeneous harts. Exact the hart realize to a separate routine in preparation for supporting multiple hart arrays. Note the file header says the RISC-V hart array holds the state of a heterogeneous array of RISC-V harts, which is not true. Update the comment to mention homogeneous array of RISC-V harts. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/riscv_hart.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'hw') diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index d0f3199..6620e41 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -3,7 +3,7 @@ * * Copyright (c) 2017 SiFive, Inc. * - * Holds the state of a heterogenous array of RISC-V harts + * Holds the state of a homogeneous array of RISC-V harts * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -39,26 +39,33 @@ static void riscv_harts_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } +static void riscv_hart_realize(RISCVHartArrayState *s, int idx, + char *cpu_type, Error **errp) +{ + Error *err = NULL; + + object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], + sizeof(RISCVCPU), cpu_type, + &error_abort, NULL); + s->harts[idx].env.mhartid = idx; + qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]); + object_property_set_bool(OBJECT(&s->harts[idx]), true, + "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } +} + static void riscv_harts_realize(DeviceState *dev, Error **errp) { RISCVHartArrayState *s = RISCV_HART_ARRAY(dev); - Error *err = NULL; int n; s->harts = g_new0(RISCVCPU, s->num_harts); for (n = 0; n < s->num_harts; n++) { - object_initialize_child(OBJECT(s), "harts[*]", &s->harts[n], - sizeof(RISCVCPU), s->cpu_type, - &error_abort, NULL); - s->harts[n].env.mhartid = n; - qemu_register_reset(riscv_harts_cpu_reset, &s->harts[n]); - object_property_set_bool(OBJECT(&s->harts[n]), true, - "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } + riscv_hart_realize(s, n, s->cpu_type, errp); } } -- cgit v1.1 From e8c56787cd78f5d26285120f85bf898f5d3693b9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:04 -0700 Subject: riscv: hart: Add a "hartid-base" property to RISC-V hart array At present each hart's hartid in a RISC-V hart array is assigned the same value of its index in the hart array. But for a system that has multiple hart arrays, this is not the case any more. Add a new "hartid-base" property so that hartid number can be assigned based on the property value. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/riscv_hart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index 6620e41..5b98227 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -29,6 +29,7 @@ static Property riscv_harts_props[] = { DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1), + DEFINE_PROP_UINT32("hartid-base", RISCVHartArrayState, hartid_base, 0), DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type), DEFINE_PROP_END_OF_LIST(), }; @@ -47,7 +48,7 @@ static void riscv_hart_realize(RISCVHartArrayState *s, int idx, object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], sizeof(RISCVCPU), cpu_type, &error_abort, NULL); - s->harts[idx].env.mhartid = idx; + s->harts[idx].env.mhartid = s->hartid_base + idx; qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]); object_property_set_bool(OBJECT(&s->harts[idx]), true, "realized", &err); -- cgit v1.1 From f3d47d580402d11b73108de807031124c135e370 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:05 -0700 Subject: riscv: sifive_u: Set the minimum number of cpus to 2 It is not useful if we only have one management CPU. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis [Palmer: Set default CPUs to 2] Reviewed-by: Palmer Dabbelt Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 2947e06..feee21e 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -10,7 +10,8 @@ * 1) CLINT (Core Level Interruptor) * 2) PLIC (Platform Level Interrupt Controller) * - * This board currently uses a hardcoded devicetree that indicates one hart. + * This board currently generates devicetree dynamically that indicates at least + * two harts. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -433,6 +434,8 @@ static void riscv_sifive_u_machine_init(MachineClass *mc) * management CPU. */ mc->max_cpus = 4; + mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; + mc->default_cpus = mc->min_cpus; } DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init) -- cgit v1.1 From ecdfe393b69985eb90ac4921287439dc47ed35b4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:06 -0700 Subject: riscv: sifive_u: Update hart configuration to reflect the real FU540 SoC The FU540-C000 includes a 64-bit E51 RISC-V core and four 64-bit U54 RISC-V cores. Currently the sifive_u machine only populates 4 U54 cores. Update the max cpu number to 5 to reflect the real hardware, by creating 2 CPU clusters as containers for RISC-V hart arrays to populate heterogeneous harts. The cpu nodes in the generated DTS have been updated as well. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 92 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 25 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index feee21e..7fc126b 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -11,7 +11,7 @@ * 2) PLIC (Platform Level Interrupt Controller) * * This board currently generates devicetree dynamically that indicates at least - * two harts. + * two harts and up to five harts. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -34,6 +34,7 @@ #include "hw/loader.h" #include "hw/sysbus.h" #include "hw/char/serial.h" +#include "hw/cpu/cluster.h" #include "target/riscv/cpu.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_plic.h" @@ -70,6 +71,7 @@ static const struct MemmapEntry { static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint64_t mem_size, const char *cmdline) { + MachineState *ms = MACHINE(qdev_get_machine()); void *fdt; int cpu; uint32_t *cells; @@ -110,15 +112,21 @@ 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.cpus.num_harts - 1; cpu >= 0; cpu--) { + for (cpu = ms->smp.cpus - 1; cpu >= 0; cpu--) { int cpu_phandle = phandle++; 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.cpus.harts[cpu]); + char *isa; qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", SIFIVE_U_CLOCK_FREQ); - qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); + /* cpu 0 is the management hart that does not have mmu */ + if (cpu != 0) { + qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); + isa = riscv_isa_string(&s->soc.u_cpus.harts[cpu - 1]); + } else { + isa = riscv_isa_string(&s->soc.e_cpus.harts[0]); + } qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); @@ -134,8 +142,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); } - cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4); - for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) { + cells = g_new0(uint32_t, ms->smp.cpus * 4); + for (cpu = 0; cpu < ms->smp.cpus; cpu++) { nodename = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); @@ -153,20 +161,26 @@ 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.cpus.num_harts * sizeof(uint32_t) * 4); + cells, ms->smp.cpus * sizeof(uint32_t) * 4); g_free(cells); g_free(nodename); plic_phandle = phandle++; - cells = g_new0(uint32_t, s->soc.cpus.num_harts * 4); - for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) { + cells = g_new0(uint32_t, ms->smp.cpus * 4 - 2); + for (cpu = 0; cpu < ms->smp.cpus; cpu++) { nodename = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); - cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); - cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); - cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); - cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); + /* cpu 0 is the management hart that does not have S-mode */ + if (cpu == 0) { + cells[0] = cpu_to_be32(intc_phandle); + cells[1] = cpu_to_be32(IRQ_M_EXT); + } else { + cells[cpu * 4 - 2] = cpu_to_be32(intc_phandle); + cells[cpu * 4 - 1] = cpu_to_be32(IRQ_M_EXT); + cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); + cells[cpu * 4 + 1] = cpu_to_be32(IRQ_S_EXT); + } g_free(nodename); } nodename = g_strdup_printf("/soc/interrupt-controller@%lx", @@ -176,7 +190,7 @@ 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.cpus.num_harts * sizeof(uint32_t) * 4); + cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t)); qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_PLIC].base, 0x0, memmap[SIFIVE_U_PLIC].size); @@ -339,12 +353,31 @@ static void riscv_sifive_u_soc_init(Object *obj) MachineState *ms = MACHINE(qdev_get_machine()); SiFiveUSoCState *s = RISCV_U_SOC(obj); - object_initialize_child(obj, "cpus", &s->cpus, sizeof(s->cpus), - TYPE_RISCV_HART_ARRAY, &error_abort, NULL); - object_property_set_str(OBJECT(&s->cpus), SIFIVE_U_CPU, "cpu-type", - &error_abort); - object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts", - &error_abort); + object_initialize_child(obj, "e-cluster", &s->e_cluster, + sizeof(s->e_cluster), TYPE_CPU_CLUSTER, + &error_abort, NULL); + qdev_prop_set_uint32(DEVICE(&s->e_cluster), "cluster-id", 0); + + object_initialize_child(OBJECT(&s->e_cluster), "e-cpus", + &s->e_cpus, sizeof(s->e_cpus), + TYPE_RISCV_HART_ARRAY, &error_abort, + NULL); + qdev_prop_set_uint32(DEVICE(&s->e_cpus), "num-harts", 1); + qdev_prop_set_uint32(DEVICE(&s->e_cpus), "hartid-base", 0); + qdev_prop_set_string(DEVICE(&s->e_cpus), "cpu-type", SIFIVE_E_CPU); + + object_initialize_child(obj, "u-cluster", &s->u_cluster, + sizeof(s->u_cluster), TYPE_CPU_CLUSTER, + &error_abort, NULL); + qdev_prop_set_uint32(DEVICE(&s->u_cluster), "cluster-id", 1); + + object_initialize_child(OBJECT(&s->u_cluster), "u-cpus", + &s->u_cpus, sizeof(s->u_cpus), + TYPE_RISCV_HART_ARRAY, &error_abort, + NULL); + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "num-harts", ms->smp.cpus - 1); + qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); + qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU); sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem), TYPE_CADENCE_GEM); @@ -364,7 +397,19 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) Error *err = NULL; NICInfo *nd = &nd_table[0]; - object_property_set_bool(OBJECT(&s->cpus), true, "realized", + object_property_set_bool(OBJECT(&s->e_cpus), true, "realized", + &error_abort); + object_property_set_bool(OBJECT(&s->u_cpus), true, "realized", + &error_abort); + /* + * The cluster must be realized after the RISC-V hart array container, + * as the container's CPU object is only created on realize, and the + * CPU must exist and have been parented into the cluster before the + * cluster is realized. + */ + object_property_set_bool(OBJECT(&s->e_cluster), true, "realized", + &error_abort); + object_property_set_bool(OBJECT(&s->u_cluster), true, "realized", &error_abort); /* boot rom */ @@ -430,10 +475,7 @@ static void riscv_sifive_u_machine_init(MachineClass *mc) { mc->desc = "RISC-V Board compatible with SiFive U SDK"; mc->init = riscv_sifive_u_init; - /* The real hardware has 5 CPUs, but one of them is a small embedded power - * management CPU. - */ - mc->max_cpus = 4; + mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT; mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; mc->default_cpus = mc->min_cpus; } -- cgit v1.1 From ef965ce23956a9e5cde5c9e91081484ec68a4139 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:07 -0700 Subject: riscv: sifive_u: Update PLIC hart topology configuration string With heterogeneous harts config, the PLIC hart topology configuration string are "M,MS,.." because of the monitor hart #0. Suggested-by: Fabien Chouteau Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 7fc126b..d80b203 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -424,10 +424,11 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) plic_hart_config = g_malloc0(plic_hart_config_len); for (i = 0; i < ms->smp.cpus; i++) { if (i != 0) { - strncat(plic_hart_config, ",", plic_hart_config_len); + strncat(plic_hart_config, "," SIFIVE_U_PLIC_HART_CONFIG, + plic_hart_config_len); + } else { + strncat(plic_hart_config, "M", plic_hart_config_len); } - strncat(plic_hart_config, SIFIVE_U_PLIC_HART_CONFIG, - plic_hart_config_len); plic_hart_config_len -= (strlen(SIFIVE_U_PLIC_HART_CONFIG) + 1); } -- cgit v1.1 From 0d95299468c8f19a306b93bb9b6940ea55945db5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:08 -0700 Subject: riscv: sifive: Implement PRCI model for FU540 This adds a simple PRCI model for FU540 (sifive_u). It has different register layout from the existing PRCI model for FE310 (sifive_e). Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/Makefile.objs | 1 + hw/riscv/sifive_u_prci.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 hw/riscv/sifive_u_prci.c (limited to 'hw') diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs index c859697..b95bbd5 100644 --- a/hw/riscv/Makefile.objs +++ b/hw/riscv/Makefile.objs @@ -8,6 +8,7 @@ obj-$(CONFIG_SIFIVE) += sifive_gpio.o obj-$(CONFIG_SIFIVE) += sifive_plic.o obj-$(CONFIG_SIFIVE) += sifive_test.o obj-$(CONFIG_SIFIVE_U) += sifive_u.o +obj-$(CONFIG_SIFIVE_U) += sifive_u_prci.o obj-$(CONFIG_SIFIVE) += sifive_uart.o obj-$(CONFIG_SPIKE) += spike.o obj-$(CONFIG_RISCV_VIRT) += virt.o diff --git a/hw/riscv/sifive_u_prci.c b/hw/riscv/sifive_u_prci.c new file mode 100644 index 0000000..4fa590c --- /dev/null +++ b/hw/riscv/sifive_u_prci.c @@ -0,0 +1,169 @@ +/* + * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt) + * + * Copyright (c) 2019 Bin Meng + * + * Simple model of the PRCI to emulate register reads made by the SDK BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/riscv/sifive_u_prci.h" + +static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size) +{ + SiFiveUPRCIState *s = opaque; + + switch (addr) { + case SIFIVE_U_PRCI_HFXOSCCFG: + return s->hfxosccfg; + case SIFIVE_U_PRCI_COREPLLCFG0: + return s->corepllcfg0; + case SIFIVE_U_PRCI_DDRPLLCFG0: + return s->ddrpllcfg0; + case SIFIVE_U_PRCI_DDRPLLCFG1: + return s->ddrpllcfg1; + case SIFIVE_U_PRCI_GEMGXLPLLCFG0: + return s->gemgxlpllcfg0; + case SIFIVE_U_PRCI_GEMGXLPLLCFG1: + return s->gemgxlpllcfg1; + case SIFIVE_U_PRCI_CORECLKSEL: + return s->coreclksel; + case SIFIVE_U_PRCI_DEVICESRESET: + return s->devicesreset; + case SIFIVE_U_PRCI_CLKMUXSTATUS: + return s->clkmuxstatus; + } + + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", + __func__, addr); + + return 0; +} + +static void sifive_u_prci_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveUPRCIState *s = opaque; + uint32_t val32 = (uint32_t)val64; + + switch (addr) { + case SIFIVE_U_PRCI_HFXOSCCFG: + s->hfxosccfg = val32; + /* OSC stays ready */ + s->hfxosccfg |= SIFIVE_U_PRCI_HFXOSCCFG_RDY; + break; + case SIFIVE_U_PRCI_COREPLLCFG0: + s->corepllcfg0 = val32; + /* internal feedback */ + s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; + /* PLL stays locked */ + s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; + break; + case SIFIVE_U_PRCI_DDRPLLCFG0: + s->ddrpllcfg0 = val32; + /* internal feedback */ + s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; + /* PLL stays locked */ + s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; + break; + case SIFIVE_U_PRCI_DDRPLLCFG1: + s->ddrpllcfg1 = val32; + break; + case SIFIVE_U_PRCI_GEMGXLPLLCFG0: + s->gemgxlpllcfg0 = val32; + /* internal feedback */ + s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; + /* PLL stays locked */ + s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; + break; + case SIFIVE_U_PRCI_GEMGXLPLLCFG1: + s->gemgxlpllcfg1 = val32; + break; + case SIFIVE_U_PRCI_CORECLKSEL: + s->coreclksel = val32; + break; + case SIFIVE_U_PRCI_DEVICESRESET: + s->devicesreset = val32; + break; + case SIFIVE_U_PRCI_CLKMUXSTATUS: + s->clkmuxstatus = val32; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx + " v=0x%x\n", __func__, addr, val32); + } +} + +static const MemoryRegionOps sifive_u_prci_ops = { + .read = sifive_u_prci_read, + .write = sifive_u_prci_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static void sifive_u_prci_realize(DeviceState *dev, Error **errp) +{ + SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_prci_ops, s, + TYPE_SIFIVE_U_PRCI, SIFIVE_U_PRCI_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); +} + +static void sifive_u_prci_reset(DeviceState *dev) +{ + SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev); + + /* Initialize register to power-on-reset values */ + s->hfxosccfg = SIFIVE_U_PRCI_HFXOSCCFG_RDY | SIFIVE_U_PRCI_HFXOSCCFG_EN; + s->corepllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | + SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | + SIFIVE_U_PRCI_PLLCFG0_LOCK; + s->ddrpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | + SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | + SIFIVE_U_PRCI_PLLCFG0_LOCK; + s->gemgxlpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | + SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | + SIFIVE_U_PRCI_PLLCFG0_LOCK; + s->coreclksel = SIFIVE_U_PRCI_CORECLKSEL_HFCLK; +} + +static void sifive_u_prci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = sifive_u_prci_realize; + dc->reset = sifive_u_prci_reset; +} + +static const TypeInfo sifive_u_prci_info = { + .name = TYPE_SIFIVE_U_PRCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveUPRCIState), + .class_init = sifive_u_prci_class_init, +}; + +static void sifive_u_prci_register_types(void) +{ + type_register_static(&sifive_u_prci_info); +} + +type_init(sifive_u_prci_register_types) -- cgit v1.1 From e1724d09a6dc090063cad9d88d9994b9f55f5716 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:09 -0700 Subject: riscv: sifive_u: Generate hfclk and rtcclk nodes To keep in sync with Linux kernel device tree, generate hfclk and rtcclk nodes in the device tree, to be referenced by PRCI node. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index d80b203..7eefe97 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -79,6 +79,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, char ethclk_names[] = "pclk\0hclk\0tx_clk"; uint32_t plic_phandle, ethclk_phandle, phandle = 1; uint32_t uartclk_phandle; + uint32_t hfclk_phandle, rtcclk_phandle; fdt = s->fdt = create_device_tree(&s->fdt_size); if (!fdt) { @@ -97,6 +98,28 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); + hfclk_phandle = phandle++; + nodename = g_strdup_printf("/hfclk"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", hfclk_phandle); + qemu_fdt_setprop_string(fdt, nodename, "clock-output-names", "hfclk"); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + SIFIVE_U_HFCLK_FREQ); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock"); + qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); + g_free(nodename); + + rtcclk_phandle = phandle++; + nodename = g_strdup_printf("/rtcclk"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", rtcclk_phandle); + qemu_fdt_setprop_string(fdt, nodename, "clock-output-names", "rtcclk"); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + SIFIVE_U_RTCCLK_FREQ); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock"); + qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); + g_free(nodename); + nodename = g_strdup_printf("/memory@%lx", (long)memmap[SIFIVE_U_DRAM].base); qemu_fdt_add_subnode(fdt, nodename); -- cgit v1.1 From af14c840418bee1b22e5b1bc403dcc8c69492517 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:10 -0700 Subject: riscv: sifive_u: Add PRCI block to the SoC Add PRCI mmio base address and size mappings to sifive_u machine, and generate the corresponding device tree node. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 7eefe97..f6b868f4 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -9,6 +9,7 @@ * 0) UART * 1) CLINT (Core Level Interruptor) * 2) PLIC (Platform Level Interrupt Controller) + * 3) PRCI (Power, Reset, Clock, Interrupt) * * This board currently generates devicetree dynamically that indicates at least * two harts and up to five harts. @@ -60,6 +61,7 @@ static const struct MemmapEntry { [SIFIVE_U_MROM] = { 0x1000, 0x11000 }, [SIFIVE_U_CLINT] = { 0x2000000, 0x10000 }, [SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 }, + [SIFIVE_U_PRCI] = { 0x10000000, 0x1000 }, [SIFIVE_U_UART0] = { 0x10013000, 0x1000 }, [SIFIVE_U_UART1] = { 0x10023000, 0x1000 }, [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, @@ -77,7 +79,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint32_t *cells; char *nodename; char ethclk_names[] = "pclk\0hclk\0tx_clk"; - uint32_t plic_phandle, ethclk_phandle, phandle = 1; + uint32_t plic_phandle, prci_phandle, ethclk_phandle, phandle = 1; uint32_t uartclk_phandle; uint32_t hfclk_phandle, rtcclk_phandle; @@ -188,6 +190,21 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(cells); g_free(nodename); + prci_phandle = phandle++; + nodename = g_strdup_printf("/soc/clock-controller@%lx", + (long)memmap[SIFIVE_U_PRCI].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", prci_phandle); + qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x1); + qemu_fdt_setprop_cells(fdt, nodename, "clocks", + hfclk_phandle, rtcclk_phandle); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + 0x0, memmap[SIFIVE_U_PRCI].base, + 0x0, memmap[SIFIVE_U_PRCI].size); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "sifive,fu540-c000-prci"); + g_free(nodename); + plic_phandle = phandle++; cells = g_new0(uint32_t, ms->smp.cpus * 4 - 2); for (cpu = 0; cpu < ms->smp.cpus; cpu++) { @@ -402,6 +419,8 @@ static void riscv_sifive_u_soc_init(Object *obj) qdev_prop_set_uint32(DEVICE(&s->u_cpus), "hartid-base", 1); qdev_prop_set_string(DEVICE(&s->u_cpus), "cpu-type", SIFIVE_U_CPU); + sysbus_init_child_obj(obj, "prci", &s->prci, sizeof(s->prci), + TYPE_SIFIVE_U_PRCI); sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem), TYPE_CADENCE_GEM); } @@ -475,6 +494,9 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) memmap[SIFIVE_U_CLINT].size, ms->smp.cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); + object_property_set_bool(OBJECT(&s->prci), true, "realized", &err); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base); + for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) { plic_gpios[i] = qdev_get_gpio_in(DEVICE(s->plic), i); } -- cgit v1.1 From 806c64b7b0e782b7f1414478486c67df718a0f00 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:11 -0700 Subject: riscv: sifive_u: Reference PRCI clocks in UART and ethernet nodes Now that we have added a PRCI node, update existing UART and ethernet nodes to reference PRCI as their clock sources, to keep in sync with the Linux kernel device tree. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index f6b868f4..9e698a1 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -78,7 +78,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, int cpu; uint32_t *cells; char *nodename; - char ethclk_names[] = "pclk\0hclk\0tx_clk"; + char ethclk_names[] = "pclk\0hclk"; uint32_t plic_phandle, prci_phandle, ethclk_phandle, phandle = 1; uint32_t uartclk_phandle; uint32_t hfclk_phandle, rtcclk_phandle; @@ -263,7 +263,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ); qemu_fdt_setprop_cells(fdt, nodename, "clocks", - ethclk_phandle, ethclk_phandle, ethclk_phandle); + prci_phandle, PRCI_CLK_GEMGXLPLL, prci_phandle, PRCI_CLK_GEMGXLPLL); qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names, sizeof(ethclk_names)); qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1); @@ -293,7 +293,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_UART0].base, 0x0, memmap[SIFIVE_U_UART0].size); - qemu_fdt_setprop_cell(fdt, nodename, "clocks", uartclk_phandle); + qemu_fdt_setprop_cells(fdt, nodename, "clocks", + prci_phandle, PRCI_CLK_TLCLK); qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_UART0_IRQ); -- cgit v1.1 From 4b55bc2b5f7ff065da5d2b813ee5153c598d3764 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:12 -0700 Subject: riscv: sifive_u: Update UART base addresses and IRQs This updates the UART base address and IRQs to match the hardware. Signed-off-by: Bin Meng Reviewed-by: Jonathan Behrens Acked-by: Alistair Francis Reviewed-by: Chih-Min Chao Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 9e698a1..b66eaef 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -62,8 +62,8 @@ static const struct MemmapEntry { [SIFIVE_U_CLINT] = { 0x2000000, 0x10000 }, [SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 }, [SIFIVE_U_PRCI] = { 0x10000000, 0x1000 }, - [SIFIVE_U_UART0] = { 0x10013000, 0x1000 }, - [SIFIVE_U_UART1] = { 0x10023000, 0x1000 }, + [SIFIVE_U_UART0] = { 0x10010000, 0x1000 }, + [SIFIVE_U_UART1] = { 0x10011000, 0x1000 }, [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, [SIFIVE_U_GEM] = { 0x100900FC, 0x2000 }, }; -- cgit v1.1 From 5f7134d3b34955d1e99780b27ea0844ff7f778e2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:13 -0700 Subject: riscv: sifive_u: Change UART node name in device tree OpenSBI for fu540 does DT fix up (see fu540_modify_dt()) by updating chosen "stdout-path" to point to "/soc/serial@...", and U-Boot will use this information to locate the serial node and probe its driver. However currently we generate the UART node name as "/soc/uart@...", causing U-Boot fail to find the serial node in DT. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index b66eaef..24f8c19 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -286,7 +286,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uartclk_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(nodename); - nodename = g_strdup_printf("/soc/uart@%lx", + nodename = g_strdup_printf("/soc/serial@%lx", (long)memmap[SIFIVE_U_UART0].base); qemu_fdt_add_subnode(fdt, nodename); qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0"); -- cgit v1.1 From 9fb45c62ae88726eb472656ae90683098473041a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:15 -0700 Subject: riscv: sifive: Implement a model for SiFive FU540 OTP This implements a simple model for SiFive FU540 OTP (One-Time Programmable) Memory interface, primarily for reading out the stored serial number from the first 1 KiB of the 16 KiB OTP memory reserved by SiFive for internal use. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/Makefile.objs | 1 + hw/riscv/sifive_u_otp.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 hw/riscv/sifive_u_otp.c (limited to 'hw') diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs index b95bbd5..fc3c6dd 100644 --- a/hw/riscv/Makefile.objs +++ b/hw/riscv/Makefile.objs @@ -8,6 +8,7 @@ obj-$(CONFIG_SIFIVE) += sifive_gpio.o obj-$(CONFIG_SIFIVE) += sifive_plic.o obj-$(CONFIG_SIFIVE) += sifive_test.o obj-$(CONFIG_SIFIVE_U) += sifive_u.o +obj-$(CONFIG_SIFIVE_U) += sifive_u_otp.o obj-$(CONFIG_SIFIVE_U) += sifive_u_prci.o obj-$(CONFIG_SIFIVE) += sifive_uart.o obj-$(CONFIG_SPIKE) += spike.o diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c new file mode 100644 index 0000000..ea0eee5 --- /dev/null +++ b/hw/riscv/sifive_u_otp.c @@ -0,0 +1,191 @@ +/* + * QEMU SiFive U OTP (One-Time Programmable) Memory interface + * + * Copyright (c) 2019 Bin Meng + * + * Simple model of the OTP to emulate register reads made by the SDK BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/riscv/sifive_u_otp.h" + +static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size) +{ + SiFiveUOTPState *s = opaque; + + switch (addr) { + case SIFIVE_U_OTP_PA: + return s->pa; + case SIFIVE_U_OTP_PAIO: + return s->paio; + case SIFIVE_U_OTP_PAS: + return s->pas; + case SIFIVE_U_OTP_PCE: + return s->pce; + case SIFIVE_U_OTP_PCLK: + return s->pclk; + case SIFIVE_U_OTP_PDIN: + return s->pdin; + case SIFIVE_U_OTP_PDOUT: + if ((s->pce & SIFIVE_U_OTP_PCE_EN) && + (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) && + (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) { + return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK]; + } else { + return 0xff; + } + case SIFIVE_U_OTP_PDSTB: + return s->pdstb; + case SIFIVE_U_OTP_PPROG: + return s->pprog; + case SIFIVE_U_OTP_PTC: + return s->ptc; + case SIFIVE_U_OTP_PTM: + return s->ptm; + case SIFIVE_U_OTP_PTM_REP: + return s->ptm_rep; + case SIFIVE_U_OTP_PTR: + return s->ptr; + case SIFIVE_U_OTP_PTRIM: + return s->ptrim; + case SIFIVE_U_OTP_PWE: + return s->pwe; + } + + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", + __func__, addr); + return 0; +} + +static void sifive_u_otp_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveUOTPState *s = opaque; + uint32_t val32 = (uint32_t)val64; + + switch (addr) { + case SIFIVE_U_OTP_PA: + s->pa = val32 & SIFIVE_U_OTP_PA_MASK; + break; + case SIFIVE_U_OTP_PAIO: + s->paio = val32; + break; + case SIFIVE_U_OTP_PAS: + s->pas = val32; + break; + case SIFIVE_U_OTP_PCE: + s->pce = val32; + break; + case SIFIVE_U_OTP_PCLK: + s->pclk = val32; + break; + case SIFIVE_U_OTP_PDIN: + s->pdin = val32; + break; + case SIFIVE_U_OTP_PDOUT: + /* read-only */ + break; + case SIFIVE_U_OTP_PDSTB: + s->pdstb = val32; + break; + case SIFIVE_U_OTP_PPROG: + s->pprog = val32; + break; + case SIFIVE_U_OTP_PTC: + s->ptc = val32; + break; + case SIFIVE_U_OTP_PTM: + s->ptm = val32; + break; + case SIFIVE_U_OTP_PTM_REP: + s->ptm_rep = val32; + break; + case SIFIVE_U_OTP_PTR: + s->ptr = val32; + break; + case SIFIVE_U_OTP_PTRIM: + s->ptrim = val32; + break; + case SIFIVE_U_OTP_PWE: + s->pwe = val32; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx + " v=0x%x\n", __func__, addr, val32); + } +} + +static const MemoryRegionOps sifive_u_otp_ops = { + .read = sifive_u_otp_read, + .write = sifive_u_otp_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static Property sifive_u_otp_properties[] = { + DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_u_otp_realize(DeviceState *dev, Error **errp) +{ + SiFiveUOTPState *s = SIFIVE_U_OTP(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s, + TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); +} + +static void sifive_u_otp_reset(DeviceState *dev) +{ + SiFiveUOTPState *s = SIFIVE_U_OTP(dev); + + /* Initialize all fuses' initial value to 0xFFs */ + memset(s->fuse, 0xff, sizeof(s->fuse)); + + /* Make a valid content of serial number */ + s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial; + s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial); +} + +static void sifive_u_otp_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = sifive_u_otp_properties; + dc->realize = sifive_u_otp_realize; + dc->reset = sifive_u_otp_reset; +} + +static const TypeInfo sifive_u_otp_info = { + .name = TYPE_SIFIVE_U_OTP, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveUOTPState), + .class_init = sifive_u_otp_class_init, +}; + +static void sifive_u_otp_register_types(void) +{ + type_register_static(&sifive_u_otp_info); +} + +type_init(sifive_u_otp_register_types) -- cgit v1.1 From 5461c4fefed627eac9e1cadfb5754fc985d6df89 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:16 -0700 Subject: riscv: sifive_u: Instantiate OTP memory with a serial number This adds an OTP memory with a given serial number to the sifive_u machine. With such support, the upstream U-Boot for sifive_fu540 boots out of the box on the sifive_u machine. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 24f8c19..f5f0c3c 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -10,6 +10,7 @@ * 1) CLINT (Core Level Interruptor) * 2) PLIC (Platform Level Interrupt Controller) * 3) PRCI (Power, Reset, Clock, Interrupt) + * 4) OTP (One-Time Programmable) memory with stored serial number * * This board currently generates devicetree dynamically that indicates at least * two harts and up to five harts. @@ -64,10 +65,12 @@ static const struct MemmapEntry { [SIFIVE_U_PRCI] = { 0x10000000, 0x1000 }, [SIFIVE_U_UART0] = { 0x10010000, 0x1000 }, [SIFIVE_U_UART1] = { 0x10011000, 0x1000 }, + [SIFIVE_U_OTP] = { 0x10070000, 0x1000 }, [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, [SIFIVE_U_GEM] = { 0x100900FC, 0x2000 }, }; +#define OTP_SERIAL 1 #define GEM_REVISION 0x10070109 static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, @@ -422,6 +425,9 @@ static void riscv_sifive_u_soc_init(Object *obj) sysbus_init_child_obj(obj, "prci", &s->prci, sizeof(s->prci), TYPE_SIFIVE_U_PRCI); + sysbus_init_child_obj(obj, "otp", &s->otp, sizeof(s->otp), + TYPE_SIFIVE_U_OTP); + qdev_prop_set_uint32(DEVICE(&s->otp), "serial", OTP_SERIAL); sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem), TYPE_CADENCE_GEM); } @@ -498,6 +504,9 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) object_property_set_bool(OBJECT(&s->prci), true, "realized", &err); sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base); + object_property_set_bool(OBJECT(&s->otp), true, "realized", &err); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_OTP].base); + for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) { plic_gpios[i] = qdev_get_gpio_in(DEVICE(s->plic), i); } -- cgit v1.1 From 7b6bb66f02bc81a6bb5d90a4fe08ab9c6841a936 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:17 -0700 Subject: riscv: sifive_u: Fix broken GEM support At present the GEM support in sifive_u machine is seriously broken. The GEM block register base was set to a weird number (0x100900FC), which for no way could work with the cadence_gem model in QEMU. Not like other GEM variants, the FU540-specific GEM has a management block to control 10/100/1000Mbps link speed changes, that is mapped to 0x100a0000. We can simply map it into MMIO space without special handling using create_unimplemented_device(). Update the GEM node compatible string to use the official name used by the upstream Linux kernel, and add the management block reg base & size to the property encoding. Tested with upstream U-Boot and Linux kernel MACB drivers. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/Kconfig | 1 + hw/riscv/sifive_u.c | 24 ++++++++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'hw') diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 33e54b0..fb19b2d 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -19,6 +19,7 @@ config SIFIVE_U select CADENCE select HART select SIFIVE + select UNIMP config SPIKE bool diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index f5f0c3c..7c07452 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -3,6 +3,7 @@ * * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu * Copyright (c) 2017 SiFive, Inc. + * Copyright (c) 2019 Bin Meng * * Provides a board compatible with the SiFive Freedom U SDK: * @@ -11,6 +12,7 @@ * 2) PLIC (Platform Level Interrupt Controller) * 3) PRCI (Power, Reset, Clock, Interrupt) * 4) OTP (One-Time Programmable) memory with stored serial number + * 5) GEM (Gigabit Ethernet Controller) and management block * * This board currently generates devicetree dynamically that indicates at least * two harts and up to five harts. @@ -37,6 +39,7 @@ #include "hw/sysbus.h" #include "hw/char/serial.h" #include "hw/cpu/cluster.h" +#include "hw/misc/unimp.h" #include "target/riscv/cpu.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_plic.h" @@ -45,6 +48,7 @@ #include "hw/riscv/sifive_u.h" #include "hw/riscv/boot.h" #include "chardev/char.h" +#include "net/eth.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" @@ -67,7 +71,8 @@ static const struct MemmapEntry { [SIFIVE_U_UART1] = { 0x10011000, 0x1000 }, [SIFIVE_U_OTP] = { 0x10070000, 0x1000 }, [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, - [SIFIVE_U_GEM] = { 0x100900FC, 0x2000 }, + [SIFIVE_U_GEM] = { 0x10090000, 0x2000 }, + [SIFIVE_U_GEM_MGMT] = { 0x100a0000, 0x1000 }, }; #define OTP_SERIAL 1 @@ -84,7 +89,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, char ethclk_names[] = "pclk\0hclk"; uint32_t plic_phandle, prci_phandle, ethclk_phandle, phandle = 1; uint32_t uartclk_phandle; - uint32_t hfclk_phandle, rtcclk_phandle; + uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; fdt = s->fdt = create_device_tree(&s->fdt_size); if (!fdt) { @@ -254,21 +259,28 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, ethclk_phandle = qemu_fdt_get_phandle(fdt, nodename); g_free(nodename); + phy_phandle = phandle++; 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_string(fdt, nodename, "compatible", + "sifive,fu540-c000-gem"); qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0, memmap[SIFIVE_U_GEM].base, - 0x0, memmap[SIFIVE_U_GEM].size); + 0x0, memmap[SIFIVE_U_GEM].size, + 0x0, memmap[SIFIVE_U_GEM_MGMT].base, + 0x0, memmap[SIFIVE_U_GEM_MGMT].size); qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control"); qemu_fdt_setprop_string(fdt, nodename, "phy-mode", "gmii"); + qemu_fdt_setprop_cell(fdt, nodename, "phy-handle", phy_phandle); qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle); qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ); qemu_fdt_setprop_cells(fdt, nodename, "clocks", prci_phandle, PRCI_CLK_GEMGXLPLL, prci_phandle, PRCI_CLK_GEMGXLPLL); qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names, sizeof(ethclk_names)); + qemu_fdt_setprop(fdt, nodename, "local-mac-address", + s->soc.gem.conf.macaddr.a, ETH_ALEN); qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1); qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0); g_free(nodename); @@ -276,6 +288,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 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_cell(fdt, nodename, "phandle", phy_phandle); qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0); g_free(nodename); @@ -525,6 +538,9 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp) 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]); + + create_unimplemented_device("riscv.sifive.u.gem-mgmt", + memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size); } static void riscv_sifive_u_machine_init(MachineClass *mc) -- cgit v1.1 From 81e94379f75c40b77d577c6bff2d7e23c9904ccf Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:18 -0700 Subject: riscv: sifive_u: Remove handcrafted clock nodes for UART and ethernet In the past we did not have a model for PRCI, hence two handcrafted clock nodes ("/soc/ethclk" and "/soc/uartclk") were created for the purpose of supplying hard-coded clock frequencies. But now since we have added the PRCI support in QEMU, we don't need them any more. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 7c07452..444c699 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -87,8 +87,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, uint32_t *cells; char *nodename; char ethclk_names[] = "pclk\0hclk"; - uint32_t plic_phandle, prci_phandle, ethclk_phandle, phandle = 1; - uint32_t uartclk_phandle; + uint32_t plic_phandle, prci_phandle, phandle = 1; uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; fdt = s->fdt = create_device_tree(&s->fdt_size); @@ -248,17 +247,6 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(cells); g_free(nodename); - ethclk_phandle = phandle++; - nodename = g_strdup_printf("/soc/ethclk"); - qemu_fdt_add_subnode(fdt, nodename); - qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock"); - qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); - qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", - SIFIVE_U_GEM_CLOCK_FREQ); - qemu_fdt_setprop_cell(fdt, nodename, "phandle", ethclk_phandle); - ethclk_phandle = qemu_fdt_get_phandle(fdt, nodename); - g_free(nodename); - phy_phandle = phandle++; nodename = g_strdup_printf("/soc/ethernet@%lx", (long)memmap[SIFIVE_U_GEM].base); @@ -292,16 +280,6 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0); g_free(nodename); - uartclk_phandle = phandle++; - nodename = g_strdup_printf("/soc/uartclk"); - qemu_fdt_add_subnode(fdt, nodename); - qemu_fdt_setprop_string(fdt, nodename, "compatible", "fixed-clock"); - qemu_fdt_setprop_cell(fdt, nodename, "#clock-cells", 0x0); - qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 3686400); - qemu_fdt_setprop_cell(fdt, nodename, "phandle", uartclk_phandle); - uartclk_phandle = qemu_fdt_get_phandle(fdt, nodename); - g_free(nodename); - nodename = g_strdup_printf("/soc/serial@%lx", (long)memmap[SIFIVE_U_UART0].base); qemu_fdt_add_subnode(fdt, nodename); -- cgit v1.1 From d372e7486f48f00a7a1e2db56d2795976845f5fc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Fri, 6 Sep 2019 09:20:19 -0700 Subject: riscv: sifive_u: Update model and compatible strings in device tree This updates model and compatible strings to use the same strings as used in the Linux kernel device tree (hifive-unleashed-a00.dts). Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Palmer Dabbelt --- hw/riscv/sifive_u.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'hw') diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 444c699..9f8e84b 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -96,8 +96,9 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, exit(1); } - qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu"); - qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev"); + qemu_fdt_setprop_string(fdt, "/", "model", "SiFive HiFive Unleashed A00"); + qemu_fdt_setprop_string(fdt, "/", "compatible", + "sifive,hifive-unleashed-a00"); qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2); qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); -- cgit v1.1