37
37
#include "qapi/error.h"
38
38
#include "qapi/visitor.h"
39
39
#include "hw/boards.h"
40
+ #include "hw/irq.h"
40
41
#include "hw/loader.h"
41
42
#include "hw/sysbus.h"
42
43
#include "hw/char/serial.h"
53
54
#include "net/eth.h"
54
55
#include "sysemu/arch_init.h"
55
56
#include "sysemu/device_tree.h"
57
+ #include "sysemu/runstate.h"
56
58
#include "sysemu/sysemu.h"
57
59
#include "exec/address-spaces.h"
58
60
@@ -96,7 +98,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
96
98
uint32_t * cells ;
97
99
char * nodename ;
98
100
char ethclk_names [] = "pclk\0hclk" ;
99
- uint32_t plic_phandle , prci_phandle , phandle = 1 ;
101
+ uint32_t plic_phandle , prci_phandle , gpio_phandle , phandle = 1 ;
100
102
uint32_t hfclk_phandle , rtcclk_phandle , phy_phandle ;
101
103
102
104
fdt = s -> fdt = create_device_tree (& s -> fdt_size );
@@ -270,9 +272,11 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
270
272
g_free (cells );
271
273
g_free (nodename );
272
274
275
+ gpio_phandle = phandle ++ ;
273
276
nodename = g_strdup_printf ("/soc/gpio@%lx" ,
274
277
(long )memmap [SIFIVE_U_GPIO ].base );
275
278
qemu_fdt_add_subnode (fdt , nodename );
279
+ qemu_fdt_setprop_cell (fdt , nodename , "phandle" , gpio_phandle );
276
280
qemu_fdt_setprop_cells (fdt , nodename , "clocks" ,
277
281
prci_phandle , PRCI_CLK_TLCLK );
278
282
qemu_fdt_setprop_cell (fdt , nodename , "#interrupt-cells" , 2 );
@@ -292,6 +296,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
292
296
qemu_fdt_setprop_string (fdt , nodename , "compatible" , "sifive,gpio0" );
293
297
g_free (nodename );
294
298
299
+ nodename = g_strdup_printf ("/gpio-restart" );
300
+ qemu_fdt_add_subnode (fdt , nodename );
301
+ qemu_fdt_setprop_cells (fdt , nodename , "gpios" , gpio_phandle , 10 , 1 );
302
+ qemu_fdt_setprop_string (fdt , nodename , "compatible" , "gpio-restart" );
303
+ g_free (nodename );
304
+
295
305
phy_phandle = phandle ++ ;
296
306
nodename = g_strdup_printf ("/soc/ethernet@%lx" ,
297
307
(long )memmap [SIFIVE_U_GEM ].base );
@@ -352,6 +362,14 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
352
362
g_free (nodename );
353
363
}
354
364
365
+ static void sifive_u_machine_reset (void * opaque , int n , int level )
366
+ {
367
+ /* gpio pin active low triggers reset */
368
+ if (!level ) {
369
+ qemu_system_reset_request (SHUTDOWN_CAUSE_GUEST_RESET );
370
+ }
371
+ }
372
+
355
373
static void sifive_u_machine_init (MachineState * machine )
356
374
{
357
375
const struct MemmapEntry * memmap = sifive_u_memmap ;
@@ -380,6 +398,10 @@ static void sifive_u_machine_init(MachineState *machine)
380
398
memory_region_add_subregion (system_memory , memmap [SIFIVE_U_FLASH0 ].base ,
381
399
flash0 );
382
400
401
+ /* register gpio-restart */
402
+ qdev_connect_gpio_out (DEVICE (& (s -> soc .gpio )), 10 ,
403
+ qemu_allocate_irq (sifive_u_machine_reset , NULL , 0 ));
404
+
383
405
/* create device tree */
384
406
create_fdt (s , memmap , machine -> ram_size , machine -> kernel_cmdline );
385
407
0 commit comments