All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] QEMU patches to generate device tree data
@ 2010-04-03  7:19 Grant Likely
  2010-04-03  7:20 ` [PATCH 1/2] qemu: devicetree: Add 8k instead of double dtb size when reserving extra memory Grant Likely
  2010-04-03  7:20 ` [PATCH 2/2] qemu: arm-dt: auto-populate the device tree with qdev data Grant Likely
  0 siblings, 2 replies; 3+ messages in thread
From: Grant Likely @ 2010-04-03  7:19 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw

Hi Jeremy,

Here are a couple of patches to your QEMU tree that add basic support
for creating device nodes at run time based on the data in the qemu
device model.  I'm still refining these, and the irq handling is a
bit of a hack, but I wanted to get these out to you so that you could
take a look and provide some initial feedback.

Cheers,
g.
---

Grant Likely (2):
      arm-dt: auto-populate the device tree with qdev data
      devicetree: Add 8k instead of double dtb size when reserving extra memory


 device_tree.c |    4 +-
 hw/arm_boot.c |    3 +
 hw/qdev.c     |  127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h     |    9 ++++
 hw/sysbus.c   |   84 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 225 insertions(+), 2 deletions(-)

-- 
Signature

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] qemu: devicetree: Add 8k instead of double dtb size when reserving extra memory
  2010-04-03  7:19 [PATCH 0/2] QEMU patches to generate device tree data Grant Likely
@ 2010-04-03  7:20 ` Grant Likely
  2010-04-03  7:20 ` [PATCH 2/2] qemu: arm-dt: auto-populate the device tree with qdev data Grant Likely
  1 sibling, 0 replies; 3+ messages in thread
From: Grant Likely @ 2010-04-03  7:20 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw

If a small 'seed' dtb file is loaded into qemu and then heavily modified
(say for runtime population of all the device nodes), then 2x the dtb
size turns out not to be very much.

This patch changes the device tree loading code to add a fixed 8k of
additional space to the dtb buffer.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 device_tree.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/device_tree.c b/device_tree.c
index 426a631..bad4810 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -41,8 +41,8 @@ void *load_device_tree(const char *filename_path, int *sizep)
         goto fail;
     }
 
-    /* Expand to 2x size to give enough room for manipulation.  */
-    dt_size *= 2;
+    /* Expand size to give enough room for manipulation.  */
+    dt_size += 8 * 1024;
     /* First allocate space in qemu for device tree */
     fdt = qemu_mallocz(dt_size);

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] qemu: arm-dt: auto-populate the device tree with qdev data
  2010-04-03  7:19 [PATCH 0/2] QEMU patches to generate device tree data Grant Likely
  2010-04-03  7:20 ` [PATCH 1/2] qemu: devicetree: Add 8k instead of double dtb size when reserving extra memory Grant Likely
@ 2010-04-03  7:20 ` Grant Likely
  1 sibling, 0 replies; 3+ messages in thread
From: Grant Likely @ 2010-04-03  7:20 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw

This patch adds hooks to the qemu device model to auto-generate device
tree nodes from the registered qemu devices.

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---

 hw/arm_boot.c |    3 +
 hw/qdev.c     |  127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h     |    9 ++++
 hw/sysbus.c   |   84 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 223 insertions(+), 0 deletions(-)

diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 740a446..33c7356 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -13,6 +13,7 @@
 #include "sysemu.h"
 #include "loader.h"
 #include "elf.h"
+#include "qdev.h"
 
 #ifdef CONFIG_FDT
 #include "device_tree.h"
@@ -211,6 +212,8 @@ static int load_dtb(target_phys_addr_t addr, struct arm_boot_info *binfo)
     }
     qemu_free(filename);
 
+    qdev_fdt_populate(fdt);
+
     rc = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
                                sizeof(mem_reg_property));
     if (rc < 0)
diff --git a/hw/qdev.c b/hw/qdev.c
index d19d531..44db7b0 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -748,3 +748,130 @@ void do_device_del(Monitor *mon, const QDict *qdict)
     }
     qdev_unplug(dev);
 }
+
+#ifdef CONFIG_FDT
+#include <libfdt.h>
+/* Iterate over entire device list looking for the interrupt parent */
+static int __qbus_fdt_irq_to_number(qemu_irq irq, BusState *bus,
+                                    uint32_t *phandle);
+static int __qbus_fdt_irq_to_number_dev(qemu_irq irq, DeviceState *dev,
+                                        uint32_t *phandle)
+{
+    BusState *child;
+    int rc, i;
+
+    for (i = 0; i < dev->num_gpio_in; i++) {
+        if (irq == qdev_get_gpio_in(dev, i)) {
+            if (phandle)
+                *phandle = (uint64_t)dev;
+            return i;
+        }
+    }
+
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        rc = __qbus_fdt_irq_to_number(irq, child, phandle);
+        if (rc >= 0)
+            return rc;
+    }
+
+    return -1;
+}
+
+static int __qbus_fdt_irq_to_number(qemu_irq irq, BusState *bus,
+                                    uint32_t *phandle)
+{
+    struct DeviceState *dev;
+    int rc;
+
+    QLIST_FOREACH(dev, &bus->children, sibling) {
+        rc = __qbus_fdt_irq_to_number_dev(irq, dev, phandle);
+        if (rc >= 0)
+            return rc;
+    }
+
+    return -1;
+}
+
+int qbus_fdt_irq_to_number(qemu_irq irq, uint32_t *phandle)
+{
+    return __qbus_fdt_irq_to_number(irq, main_system_bus, phandle);
+}
+
+
+
+static int qbus_fdt_add_bus(void *fdt, BusState *bus, int dev_offset);
+static int qdev_fdt_add_device(void *fdt, DeviceState *dev, int bus_offset)
+{
+    BusState *child;
+    int dev_offset, rc;
+    char name[sizeof(dev->info->name) + 9];
+    static int unique = 0;
+
+    sprintf(name, "%s@%x", dev->info->name, unique++);
+    dev_offset = fdt_add_subnode(fdt, bus_offset, name);
+    if (dev_offset < 0) {
+        qemu_error("Couldn't add FDT node for device %s\n", dev->info->name);
+        return dev_offset;
+    }
+
+    rc = fdt_setprop_cell(fdt, dev_offset, "phandle", (uint64_t)dev);
+    if (rc < 0) {
+        qemu_error("Could not add phandle property to device %s\n",
+                   dev->info->name);
+        return rc;
+    }
+
+    if (dev->parent_bus->info->fdt_populate_node) {
+        int rc = dev->parent_bus->info->fdt_populate_node(fdt, dev, dev_offset);
+        if (rc < 0)
+            return rc;
+    }
+
+    QLIST_FOREACH(child, &dev->child_bus, sibling) {
+        int rc = qbus_fdt_add_bus(fdt, child, dev_offset);
+        if (rc < 0)
+            return rc;
+    }
+
+    return dev_offset;
+}
+
+static int qbus_fdt_add_bus(void *fdt, BusState *bus, int dev_offset)
+{
+    struct DeviceState *dev;
+    int bus_offset;
+
+    bus_offset = fdt_add_subnode(fdt, dev_offset, bus->name);
+    if (bus_offset < 0) {
+        qemu_error("Couldn't add FDT node for bus %s\n", bus->name);
+        return bus_offset;
+    }
+
+    if (bus->info->fdt_populate_bus) {
+        int rc = bus->info->fdt_populate_bus(fdt, bus, bus_offset);
+        if (rc < 0)
+            return rc;
+    }
+
+    QLIST_FOREACH(dev, &bus->children, sibling) {
+        int rc = qdev_fdt_add_device(fdt, dev, bus_offset);
+        if (rc < 0)
+            return rc;
+    }
+
+    return bus_offset;
+}
+
+int qdev_fdt_populate(void *fdt)
+{
+    int offset = fdt_path_offset(fdt, "/");
+    if (offset < 0)
+        return offset;
+
+    if (main_system_bus)
+        qbus_fdt_add_bus(fdt, main_system_bus, offset);
+
+    return offset;
+}
+#endif /* CONFIG_FDT */
+
diff --git a/hw/qdev.h b/hw/qdev.h
index 41642ee..9947bda 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -43,10 +43,14 @@ struct DeviceState {
 };
 
 typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent);
+typedef int (*fdt_populate_busfn)(void *fdt, BusState *bus, int offset);
+typedef int (*fdt_populate_devicefn)(void *fdt, DeviceState *dev, int offset);
 struct BusInfo {
     const char *name;
     size_t size;
     bus_dev_printfn print_dev;
+    fdt_populate_devicefn fdt_populate_node;
+    fdt_populate_busfn fdt_populate_bus;
     Property *props;
 };
 
@@ -272,4 +276,9 @@ void qdev_prop_set_compat(DeviceState *dev);
 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
 extern struct BusInfo system_bus_info;
 
+#ifdef CONFIG_FDT
+int qbus_fdt_irq_to_number(qemu_irq irq, uint32_t *phandle);
+int qdev_fdt_populate(void *fdt);
+#endif
+
 #endif
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 1f7f138..666f93f 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -22,11 +22,17 @@
 #include "monitor.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+static int sysbus_fdt_populate_node(void *fdt, DeviceState *dev, int offset);
+static int sysbus_fdt_populate_bus(void *fdt, BusState *bus, int offset);
 
 struct BusInfo system_bus_info = {
     .name       = "System",
     .size       = sizeof(BusState),
     .print_dev  = sysbus_dev_print,
+#ifdef CONFIG_FDT
+    .fdt_populate_node = sysbus_fdt_populate_node,
+    .fdt_populate_bus = sysbus_fdt_populate_bus,
+#endif /* CONFIG_FDT */
 };
 
 void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
@@ -170,3 +176,81 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
                        indent, "", s->mmio[i].addr, s->mmio[i].size);
     }
 }
+
+#ifdef CONFIG_FDT
+#include <libfdt.h>
+static int sysbus_fdt_populate_bus(void *fdt, BusState *bus, int offset)
+{
+    int rc;
+
+    rc = fdt_setprop_string(fdt, offset, "compatible", "simple-bus");
+    if (rc < 0)
+        return rc;
+
+    rc = fdt_setprop_cell(fdt, offset, "#address-cells", 1);
+    if (rc < 0)
+        return rc;
+    rc = fdt_setprop_cell(fdt, offset, "#size-cells", 1);
+    if (rc < 0)
+        return rc;
+    rc = fdt_setprop(fdt, offset, "ranges", NULL, 0);
+    if (rc < 0)
+        return rc;
+    return 0;
+}
+
+static int sysbus_fdt_populate_node(void *fdt, DeviceState *dev, int offset)
+{
+    SysBusDevice *s = sysbus_from_qdev(dev);
+    uint32_t reg_data[s->num_mmio * 2]; /* one cell each address and size */
+    uint32_t irq_data[s->num_irq];
+    uint32_t *pos;
+    uint32_t phandle;
+    int i, rc;
+
+    /* Create 'reg' property */
+    pos = reg_data;
+    for (i = 0; i < s->num_mmio; i++) {
+        /* By convention, the name is appended with '@<first reg addr>' */
+        if (i == 0) {
+            char n[sizeof(dev->info->name) + 10];
+            sprintf(n, "%s@%x", dev->info->name, (uint32_t)s->mmio[i].addr);
+            rc = fdt_set_name(fdt, offset, n);
+            if (rc < 0)
+                return rc;
+        }
+        *pos++ = cpu_to_be32(s->mmio[i].addr);
+        *pos++ = cpu_to_be32(s->mmio[i].size);
+    }
+    rc = fdt_setprop(fdt, offset, "reg", reg_data, sizeof(reg_data));
+    if (rc < 0)
+        return rc;
+
+    /* Is this an interrupt controller? */
+    if (dev->num_gpio_in) {
+        rc = fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0);
+        if (rc < 0)
+            return rc;
+        rc = fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1);
+        if (rc < 0)
+            return rc;
+    }
+
+    /* Create 'interrupts' property */
+    phandle = 0;
+    pos = irq_data;
+    for (i = 0; i < s->num_irq; i++) {
+        *pos++ = cpu_to_be32(qbus_fdt_irq_to_number(*s->irqp[i], &phandle));
+    }
+    if (phandle) {
+        rc = fdt_setprop_cell(fdt, offset, "interrupt-parent", phandle);
+        if (rc < 0)
+            return rc;
+        rc = fdt_setprop(fdt, offset, "interrupts", irq_data, sizeof(irq_data));
+        if (rc < 0)
+            return rc;
+    }
+
+    return 0;
+}
+#endif /* CONFIG_FDT */

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-04-03  7:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-03  7:19 [PATCH 0/2] QEMU patches to generate device tree data Grant Likely
2010-04-03  7:20 ` [PATCH 1/2] qemu: devicetree: Add 8k instead of double dtb size when reserving extra memory Grant Likely
2010-04-03  7:20 ` [PATCH 2/2] qemu: arm-dt: auto-populate the device tree with qdev data Grant Likely

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.