Message ID | 1591625864-31494-10-git-send-email-bmeng.cn@gmail.com |
---|---|
State | New |
Headers | show |
Series | hw/riscv: sifive_u: Add GPIO and Mode Select (MSEL[3:0]) support | expand |
On Mon, Jun 8, 2020 at 7:23 AM Bin Meng <bmeng.cn@gmail.com> wrote: > > From: Bin Meng <bin.meng@windriver.com> > > The HiFive Unleashed board wires GPIO pin#10 to the input of the > system reset signal. Let's set up the GPIO pin#10 and insert a > "gpio-restart" device tree node so that reboot is now functional > with QEMU 'sifive_u' machine. > > Signed-off-by: Bin Meng <bin.meng@windriver.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > > hw/riscv/sifive_u.c | 24 +++++++++++++++++++++++- > 1 file changed, 23 insertions(+), 1 deletion(-) > > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c > index 881949b..ef51874 100644 > --- a/hw/riscv/sifive_u.c > +++ b/hw/riscv/sifive_u.c > @@ -37,6 +37,7 @@ > #include "qapi/error.h" > #include "qapi/visitor.h" > #include "hw/boards.h" > +#include "hw/irq.h" > #include "hw/loader.h" > #include "hw/sysbus.h" > #include "hw/char/serial.h" > @@ -53,6 +54,7 @@ > #include "net/eth.h" > #include "sysemu/arch_init.h" > #include "sysemu/device_tree.h" > +#include "sysemu/runstate.h" > #include "sysemu/sysemu.h" > #include "exec/address-spaces.h" > > @@ -96,7 +98,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, phandle = 1; > + uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; > uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; > > fdt = s->fdt = create_device_tree(&s->fdt_size); > @@ -270,9 +272,11 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, > g_free(cells); > g_free(nodename); > > + gpio_phandle = phandle++; > nodename = g_strdup_printf("/soc/gpio@%lx", > (long)memmap[SIFIVE_U_GPIO].base); > qemu_fdt_add_subnode(fdt, nodename); > + qemu_fdt_setprop_cell(fdt, nodename, "phandle", gpio_phandle); > qemu_fdt_setprop_cells(fdt, nodename, "clocks", > prci_phandle, PRCI_CLK_TLCLK); > qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 2); > @@ -292,6 +296,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, > qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,gpio0"); > g_free(nodename); > > + nodename = g_strdup_printf("/gpio-restart"); > + qemu_fdt_add_subnode(fdt, nodename); > + qemu_fdt_setprop_cells(fdt, nodename, "gpios", gpio_phandle, 10, 1); > + qemu_fdt_setprop_string(fdt, nodename, "compatible", "gpio-restart"); > + g_free(nodename); > + > phy_phandle = phandle++; > nodename = g_strdup_printf("/soc/ethernet@%lx", > (long)memmap[SIFIVE_U_GEM].base); > @@ -352,6 +362,14 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, > g_free(nodename); > } > > +static void sifive_u_machine_reset(void *opaque, int n, int level) > +{ > + /* gpio pin active low triggers reset */ > + if (!level) { > + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); > + } > +} > + > static void sifive_u_machine_init(MachineState *machine) > { > const struct MemmapEntry *memmap = sifive_u_memmap; > @@ -383,6 +401,10 @@ static void sifive_u_machine_init(MachineState *machine) > memory_region_add_subregion(system_memory, memmap[SIFIVE_U_FLASH0].base, > flash0); > > + /* register gpio-restart */ > + qdev_connect_gpio_out(DEVICE(&(s->soc.gpio)), 10, > + qemu_allocate_irq(sifive_u_machine_reset, NULL, 0)); > + > /* create device tree */ > create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); > > -- > 2.7.4 > >
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 881949b..ef51874 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -37,6 +37,7 @@ #include "qapi/error.h" #include "qapi/visitor.h" #include "hw/boards.h" +#include "hw/irq.h" #include "hw/loader.h" #include "hw/sysbus.h" #include "hw/char/serial.h" @@ -53,6 +54,7 @@ #include "net/eth.h" #include "sysemu/arch_init.h" #include "sysemu/device_tree.h" +#include "sysemu/runstate.h" #include "sysemu/sysemu.h" #include "exec/address-spaces.h" @@ -96,7 +98,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, phandle = 1; + uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1; uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle; fdt = s->fdt = create_device_tree(&s->fdt_size); @@ -270,9 +272,11 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(cells); g_free(nodename); + gpio_phandle = phandle++; nodename = g_strdup_printf("/soc/gpio@%lx", (long)memmap[SIFIVE_U_GPIO].base); qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", gpio_phandle); qemu_fdt_setprop_cells(fdt, nodename, "clocks", prci_phandle, PRCI_CLK_TLCLK); qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 2); @@ -292,6 +296,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,gpio0"); g_free(nodename); + nodename = g_strdup_printf("/gpio-restart"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cells(fdt, nodename, "gpios", gpio_phandle, 10, 1); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "gpio-restart"); + g_free(nodename); + phy_phandle = phandle++; nodename = g_strdup_printf("/soc/ethernet@%lx", (long)memmap[SIFIVE_U_GEM].base); @@ -352,6 +362,14 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); } +static void sifive_u_machine_reset(void *opaque, int n, int level) +{ + /* gpio pin active low triggers reset */ + if (!level) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } +} + static void sifive_u_machine_init(MachineState *machine) { const struct MemmapEntry *memmap = sifive_u_memmap; @@ -383,6 +401,10 @@ static void sifive_u_machine_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[SIFIVE_U_FLASH0].base, flash0); + /* register gpio-restart */ + qdev_connect_gpio_out(DEVICE(&(s->soc.gpio)), 10, + qemu_allocate_irq(sifive_u_machine_reset, NULL, 0)); + /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);