diff mbox series

[1/2] aspeed: Add syscon-poweroff to guest device tree

Message ID 20181211031044.27628-2-joel@jms.id.au
State New
Headers show
Series arm: aspeed: Allow the guest to exit | expand

Commit Message

Joel Stanley Dec. 11, 2018, 3:10 a.m. UTC
This adds a node to the guest's device tree that allows it to cause Qemu
to exit when the guest shuts down.

Signed-off-by: Joel Stanley <joel@jms.id.au>

---
 hw/arm/aspeed.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

-- 
2.19.1

Comments

Cédric Le Goater Dec. 11, 2018, 7:32 a.m. UTC | #1
On 12/11/18 4:10 AM, Joel Stanley wrote:
> This adds a node to the guest's device tree that allows it to cause Qemu

> to exit when the guest shuts down.


Do you think we could find a way to add the same node under U-Boot for 
tests using flash images ? or could we just add the node in DT ? Would
that be a problem on real system ?      


Nevertheless, this is fine.

Reviewed-by: Cédric Le Goater <clg@kaod.org>


Thanks,

C.


> Signed-off-by: Joel Stanley <joel@jms.id.au>

> ---

>  hw/arm/aspeed.c | 33 +++++++++++++++++++++++++++++++++

>  1 file changed, 33 insertions(+)

> 

> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c

> index 515898548284..00060d44ad51 100644

> --- a/hw/arm/aspeed.c

> +++ b/hw/arm/aspeed.c

> @@ -21,8 +21,10 @@

>  #include "hw/i2c/smbus.h"

>  #include "qemu/log.h"

>  #include "sysemu/block-backend.h"

> +#include "sysemu/device_tree.h"

>  #include "hw/loader.h"

>  #include "qemu/error-report.h"

> +#include <libfdt.h>

>  

>  static struct arm_boot_info aspeed_board_binfo = {

>      .board_id = -1, /* device-tree-only board */

> @@ -126,6 +128,36 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,

>      g_free(storage);

>  }

>  

> +static void fdt_add_shutdown_node(void *fdt)

> +{

> +    const char *nodename = "/syscon-poweroff";

> +    uint32_t phandle;

> +    int offset;

> +

> +    /* Find the scu phandle */

> +    offset = fdt_path_offset(fdt, "/ahb/apb/syscon@1e6e2000");

> +    if (offset < 0) {

> +        error_report("%s couldn't find syscon, guest shutdown unavailable: %s",

> +                     __func__, fdt_strerror(offset));

> +        return;

> +    }

> +    phandle = fdt_get_phandle(fdt, offset);

> +

> +    /* Add syscon-poweroff node and use 0x1A0, an un-used SCU register */

> +    qemu_fdt_add_subnode(fdt, nodename);

> +    qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-poweroff");

> +    qemu_fdt_setprop_cells(fdt, nodename, "regmap", phandle);

> +    qemu_fdt_setprop_cells(fdt, nodename, "offset", 0x1A0);

> +    qemu_fdt_setprop_cells(fdt, nodename, "value", 1);

> +}

> +

> +static void aspeed_board_modify_dtb(const struct arm_boot_info *binfo,

> +                                    void *fdt)

> +{

> +    fdt_add_shutdown_node(fdt);

> +}

> +

> +

>  static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,

>                                        Error **errp)

>  {

> @@ -228,6 +260,7 @@ static void aspeed_board_init(MachineState *machine,

>      aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;

>      aspeed_board_binfo.ram_size = ram_size;

>      aspeed_board_binfo.loader_start = sc->info->sdram_base;

> +    aspeed_board_binfo.modify_dtb = aspeed_board_modify_dtb;

>  

>      if (cfg->i2c_init) {

>          cfg->i2c_init(bmc);

>
diff mbox series

Patch

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 515898548284..00060d44ad51 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -21,8 +21,10 @@ 
 #include "hw/i2c/smbus.h"
 #include "qemu/log.h"
 #include "sysemu/block-backend.h"
+#include "sysemu/device_tree.h"
 #include "hw/loader.h"
 #include "qemu/error-report.h"
+#include <libfdt.h>
 
 static struct arm_boot_info aspeed_board_binfo = {
     .board_id = -1, /* device-tree-only board */
@@ -126,6 +128,36 @@  static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
     g_free(storage);
 }
 
+static void fdt_add_shutdown_node(void *fdt)
+{
+    const char *nodename = "/syscon-poweroff";
+    uint32_t phandle;
+    int offset;
+
+    /* Find the scu phandle */
+    offset = fdt_path_offset(fdt, "/ahb/apb/syscon@1e6e2000");
+    if (offset < 0) {
+        error_report("%s couldn't find syscon, guest shutdown unavailable: %s",
+                     __func__, fdt_strerror(offset));
+        return;
+    }
+    phandle = fdt_get_phandle(fdt, offset);
+
+    /* Add syscon-poweroff node and use 0x1A0, an un-used SCU register */
+    qemu_fdt_add_subnode(fdt, nodename);
+    qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-poweroff");
+    qemu_fdt_setprop_cells(fdt, nodename, "regmap", phandle);
+    qemu_fdt_setprop_cells(fdt, nodename, "offset", 0x1A0);
+    qemu_fdt_setprop_cells(fdt, nodename, "value", 1);
+}
+
+static void aspeed_board_modify_dtb(const struct arm_boot_info *binfo,
+                                    void *fdt)
+{
+    fdt_add_shutdown_node(fdt);
+}
+
+
 static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
                                       Error **errp)
 {
@@ -228,6 +260,7 @@  static void aspeed_board_init(MachineState *machine,
     aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
     aspeed_board_binfo.ram_size = ram_size;
     aspeed_board_binfo.loader_start = sc->info->sdram_base;
+    aspeed_board_binfo.modify_dtb = aspeed_board_modify_dtb;
 
     if (cfg->i2c_init) {
         cfg->i2c_init(bmc);