diff mbox

[v3,3/6] PPC: e500: use dyn_sysbus_binding helper routines

Message ID 1410249273-6063-4-git-send-email-eric.auger@linaro.org
State New
Headers show

Commit Message

Auger Eric Sept. 9, 2014, 7:54 a.m. UTC
From: Alexander Graf <agraf@suse.de>

Now platform_bus_init_notify and functions it calls were moved
to dyn_sysbus_binding.c, remove those functions from e500.

PPCE500Params includes a DynSysbusParams struct which contains
the settings related to platform device instantiation.

Signed-off-by: Eric Auger <eric.auger@linaro.org>

---

v2 -> v3:

- Modify e500.c to use platform_bus_init_notify now implemented in
dyn_sysbus_binding
- new DynSysbusParams that contains dynamic sysbus settings
- PPCE500Params includes a DynSysbusParams struct
---
 hw/ppc/e500.c     | 183 ++++--------------------------------------------------
 hw/ppc/e500.h     |   7 +--
 hw/ppc/e500plat.c |  13 ++--
 3 files changed, 22 insertions(+), 181 deletions(-)
diff mbox

Patch

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index fe9497a..0741412 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -38,6 +38,7 @@ 
 #include "hw/pci-host/ppce500.h"
 #include "qemu/error-report.h"
 #include "hw/net/fsl_etsec/etsec.h"
+#include "hw/misc/dyn_sysbus_binding.h"
 
 #define EPAPR_MAGIC                (0x45504150)
 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
@@ -196,13 +197,14 @@  static int sysbus_device_create_devtree(Object *obj, void *opaque)
 static void platform_bus_create_devtree(PPCE500Params *params, void *fdt,
                                         const char *mpic)
 {
-    gchar *node = g_strdup_printf("/platform@%"PRIx64, params->platform_bus_base);
+    gchar *node = g_strdup_printf("/platform@%"PRIx64,
+                                  params->dyn_sysbus_params.platform_bus_base);
     const char platcomp[] = "qemu,platform\0simple-bus";
     PlatformDevtreeData data;
     Object *container;
-    uint64_t addr = params->platform_bus_base;
-    uint64_t size = params->platform_bus_size;
-    int irq_start = params->platform_bus_first_irq;
+    uint64_t addr = params->dyn_sysbus_params.platform_bus_base;
+    uint64_t size = params->dyn_sysbus_params.platform_bus_size;
+    int irq_start = params->dyn_sysbus_params.platform_bus_first_irq;
 
     /* Create a /platform node that we can put all devices into */
 
@@ -489,7 +491,7 @@  static int ppce500_load_device_tree(MachineState *machine,
     qemu_fdt_setprop_cell(fdt, pci, "#address-cells", 3);
     qemu_fdt_setprop_string(fdt, "/aliases", "pci0", pci);
 
-    if (params->has_platform_bus) {
+    if (params->dyn_sysbus_params.has_platform_bus) {
         platform_bus_create_devtree(params, fdt, mpic);
     }
 
@@ -732,169 +734,6 @@  static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
     return mpic;
 }
 
-typedef struct PlatformBusNotifier {
-    Notifier notifier;
-    MemoryRegion *address_space_mem;
-    qemu_irq *mpic;
-    PPCE500Params params;
-} PlatformBusNotifier;
-
-typedef struct PlatformBusInitData {
-    unsigned long *used_irqs;
-    unsigned long *used_mem;
-    MemoryRegion *mem;
-    qemu_irq *irqs;
-    int device_count;
-    PPCE500Params *params;
-} PlatformBusInitData;
-
-static int platform_bus_map_irq(PPCE500Params *params, SysBusDevice *sbdev,
-                                int n, unsigned long *used_irqs,
-                                qemu_irq *platform_irqs)
-{
-    int max_irqs = params->platform_bus_num_irqs;
-    char *prop = g_strdup_printf("irq[%d]", n);
-    int irqn = object_property_get_int(OBJECT(sbdev), prop, NULL);
-
-    if (irqn == SYSBUS_DYNAMIC) {
-        /* Find the first available IRQ */
-        irqn = find_first_zero_bit(used_irqs, max_irqs);
-    }
-
-    if ((irqn >= max_irqs) || test_and_set_bit(irqn, used_irqs)) {
-        hw_error("e500: IRQ %d is already allocated or no free IRQ left", irqn);
-    }
-
-    sysbus_connect_irq(sbdev, n, platform_irqs[irqn]);
-    object_property_set_int(OBJECT(sbdev), irqn, prop, NULL);
-
-    g_free(prop);
-    return 0;
-}
-
-static int platform_bus_map_mmio(PPCE500Params *params, SysBusDevice *sbdev,
-                                 int n, unsigned long *used_mem,
-                                 MemoryRegion *pmem)
-{
-    MemoryRegion *device_mem = sbdev->mmio[n].memory;
-    uint64_t size = memory_region_size(device_mem);
-    uint64_t page_size = (1 << E500_PLATFORM_BUS_PAGE_SHIFT);
-    uint64_t page_mask = page_size - 1;
-    uint64_t size_pages = (size + page_mask) >> E500_PLATFORM_BUS_PAGE_SHIFT;
-    uint64_t max_size = params->platform_bus_size;
-    uint64_t max_pages = max_size >> E500_PLATFORM_BUS_PAGE_SHIFT;
-    char *prop = g_strdup_printf("mmio[%d]", n);
-    hwaddr addr = object_property_get_int(OBJECT(sbdev), prop, NULL);
-    int page;
-    int i;
-
-    page = addr >> E500_PLATFORM_BUS_PAGE_SHIFT;
-    if (addr == SYSBUS_DYNAMIC) {
-        uint64_t size_pages_align;
-
-        /* Align the region to at least its own size granularity */
-        if (is_power_of_2(size_pages)) {
-            size_pages_align = size_pages;
-        } else {
-            size_pages_align = pow2floor(size_pages) << 1;
-        }
-
-        /* Find the first available region that fits */
-        page = bitmap_find_next_zero_area(used_mem, max_pages, 0, size_pages,
-                                          size_pages_align);
-
-        addr = (uint64_t)page << E500_PLATFORM_BUS_PAGE_SHIFT;
-    }
-
-    if (page >= max_pages || test_bit(page, used_mem) ||
-        (find_next_bit(used_mem, max_pages, page) < size_pages)) {
-        hw_error("e500: Memory [%"PRIx64":%"PRIx64" is already allocated or "
-                 "no slot left", addr, size);
-    }
-
-    for (i = page; i < (page + size_pages); i++) {
-        set_bit(i, used_mem);
-    }
-
-    memory_region_add_subregion(pmem, addr, device_mem);
-    sbdev->mmio[n].addr = addr;
-    object_property_set_int(OBJECT(sbdev), addr, prop, NULL);
-
-    g_free(prop);
-    return 0;
-}
-
-static int sysbus_device_check(Object *obj, void *opaque)
-{
-    PlatformBusInitData *init = opaque;
-    Object *dev;
-    SysBusDevice *sbdev;
-    int i;
-
-    dev = object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE);
-    sbdev = (SysBusDevice *)dev;
-
-    if (!sbdev) {
-        /* Container, traverse it for children */
-        return object_child_foreach(obj, sysbus_device_check, opaque);
-    }
-
-    /* Connect sysbus device to virtual platform bus */
-    for (i = 0; i < sbdev->num_irq; i++) {
-        if (!sbdev->irqp[i]) {
-            /* This IRQ is an incoming IRQ, we can't wire those here */
-            continue;
-        }
-        platform_bus_map_irq(init->params, sbdev, i, init->used_irqs, init->irqs);
-    }
-
-    for (i = 0; i < sbdev->num_mmio; i++) {
-        platform_bus_map_mmio(init->params, sbdev, i, init->used_mem, init->mem);
-    }
-
-    return 0;
-}
-
-static void platform_bus_init(PPCE500Params *params,
-                              MemoryRegion *address_space_mem,
-                              qemu_irq *mpic)
-{
-    uint64_t max_size = params->platform_bus_size;
-    uint64_t max_pages = max_size >> E500_PLATFORM_BUS_PAGE_SHIFT;
-    DECLARE_BITMAP(used_irqs, params->platform_bus_num_irqs);
-    DECLARE_BITMAP(used_mem, max_pages);
-    MemoryRegion *platform_region = g_new(MemoryRegion, 1);
-    Object *container;
-    PlatformBusInitData init = {
-        .used_irqs = used_irqs,
-        .used_mem = used_mem,
-        .mem = platform_region,
-        .irqs = &mpic[params->platform_bus_first_irq],
-        .params = params,
-    };
-
-    memory_region_init(platform_region, NULL, "platform devices",
-                       params->platform_bus_size);
-
-    bitmap_clear(used_irqs, 0, params->platform_bus_num_irqs);
-    bitmap_clear(used_mem, 0, max_pages);
-
-    /* Loop through all sysbus devices that were spawened outside the machine */
-    container = container_get(qdev_get_machine(), "/peripheral");
-    sysbus_device_check(container, &init);
-    container = container_get(qdev_get_machine(), "/peripheral-anon");
-    sysbus_device_check(container, &init);
-
-    memory_region_add_subregion(address_space_mem, params->platform_bus_base,
-                                platform_region);
-}
-
-static void platform_bus_init_notify(Notifier *notifier, void *data)
-{
-    PlatformBusNotifier *pn = (PlatformBusNotifier *)notifier;
-    platform_bus_init(&pn->params, pn->address_space_mem, pn->mpic);
-}
-
 void ppce500_init(MachineState *machine, PPCE500Params *params)
 {
     MemoryRegion *address_space_mem = get_system_memory();
@@ -1047,13 +886,15 @@  void ppce500_init(MachineState *machine, PPCE500Params *params)
     }
 
     /* Platform Devices */
-    if (params->has_platform_bus) {
-        PlatformBusNotifier *notifier = g_new(PlatformBusNotifier, 1);
+    if (params->dyn_sysbus_params.has_platform_bus) {
+        DynSysbusNotifier *notifier = g_new(DynSysbusNotifier, 1);
+        params->dyn_sysbus_params.page_shift =
+            E500_PLATFORM_BUS_PAGE_SHIFT;
 
         notifier->notifier.notify = platform_bus_init_notify;
         notifier->address_space_mem = address_space_mem;
         notifier->mpic = mpic;
-        notifier->params = *params;
+        notifier->params = params->dyn_sysbus_params;
         qemu_add_machine_init_done_notifier(&notifier->notifier);
     }
 
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index f1b2766..c191f9d 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -2,6 +2,7 @@ 
 #define PPCE500_H
 
 #include "hw/boards.h"
+#include "hw/misc/dyn_sysbus_binding.h"
 
 typedef struct PPCE500Params {
     int pci_first_slot;
@@ -11,11 +12,7 @@  typedef struct PPCE500Params {
     void (*fixup_devtree)(struct PPCE500Params *params, void *fdt);
 
     int mpic_version;
-    bool has_platform_bus;
-    hwaddr platform_bus_base;
-    hwaddr platform_bus_size;
-    int platform_bus_first_irq;
-    int platform_bus_num_irqs;
+    DynSysbusParams dyn_sysbus_params;
 } PPCE500Params;
 
 void ppce500_init(MachineState *machine, PPCE500Params *params);
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index befe1d1..4150a2c 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -35,11 +35,14 @@  static void e500plat_init(MachineState *machine)
         .pci_nr_slots = PCI_SLOT_MAX - 1,
         .fixup_devtree = e500plat_fixup_devtree,
         .mpic_version = OPENPIC_MODEL_FSL_MPIC_42,
-        .has_platform_bus = true,
-        .platform_bus_base = 0xf00000000ULL,
-        .platform_bus_size = (128ULL * 1024 * 1024),
-        .platform_bus_first_irq = 5,
-        .platform_bus_num_irqs = 10,
+        .dyn_sysbus_params = {
+            .has_platform_bus = true,
+            .platform_bus_base = 0xf00000000ULL,
+            .platform_bus_size = (128ULL * 1024 * 1024),
+            .platform_bus_first_irq = 5,
+            .platform_bus_num_irqs = 10,
+            .page_shift = 12 /* default */
+        }
     };
 
     /* Older KVM versions don't support EPR which breaks guests when we announce