qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: "qemu-ppc@nongnu.org list:PowerPC" <qemu-ppc@nongnu.org>
Cc: Peter Maydell <peter.maydell@linaro.org>,
	qemu-devel Developers <qemu-devel@nongnu.org>
Subject: [Qemu-devel] [PATCH 2/9] PlatBus: Add abstract Platform Device
Date: Mon, 22 Jul 2013 19:50:04 +0200	[thread overview]
Message-ID: <1374515411-43818-3-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1374515411-43818-1-git-send-email-agraf@suse.de>

This patch adds an abstract platform device class. Real platform devices
should use this as their parent class.

It manages IO memory regions and IRQ ranges for the actual device.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/platbus/device.c         | 162 ++++++++++++++++++++++++++++++++++++++++++++
 include/hw/platbus/device.h | 102 ++++++++++++++++++++++++++++
 2 files changed, 264 insertions(+)
 create mode 100644 hw/platbus/device.c
 create mode 100644 include/hw/platbus/device.h

diff --git a/hw/platbus/device.c b/hw/platbus/device.c
new file mode 100644
index 0000000..74ba11b
--- /dev/null
+++ b/hw/platbus/device.c
@@ -0,0 +1,162 @@
+/*
+ * Platform Device that can connect to a Platform Bus
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Authors: Alexander Graf,   <agraf@suse.de>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ *
+ *
+ * This is an abstract platform device, so you really only want to use it
+ * as parent class for platform devices.
+ *
+ * It ensures that all boilerplate is properly abstracted away from children
+ * and consistent across devices.
+ *
+ * When instantiating a platform device you can optionally always specify 2 qdev
+ * properties which otherwise get populated automatically:
+ *
+ *  regions: Offsets in the platbus hole the device's memory regions get mapped
+ *           to.
+ *  irqs: IRQ pins in the linear platbus IRQ range the device's IRQs get mapped
+ *           to.
+ */
+
+#include "qemu-common.h"
+#include "hw/platbus/platbus.h"
+#include "hw/platbus/device.h"
+
+static int realize_regions(PlatBusDeviceState *s, PlatBusState *bus,
+                           Error **errp)
+{
+    uint64_t *addrs = g_new(uint64_t, s->num_regions);
+    int r, i;
+
+    /* get our memory regions */
+    for (i = 0; i < s->num_regions; i++) {
+        if (s->num_plat_region_addrs > i) {
+            /* user defined region */
+            addrs[i] = s->plat_region_addrs[i];
+        } else {
+            /* dynamically allocated region */
+            addrs[i] = PLATBUS_DYNAMIC;
+        }
+
+        r = platbus_map_region(bus, &addrs[i], s->regions[i]);
+        if (r) {
+            error_setg(errp, "PlatBus Device: Could not map region at %" PRIx64,
+                       addrs[i]);
+            return -1;
+        }
+    }
+
+    /* update our region list, so that we can see it with info qtree */
+    s->plat_region_addrs = addrs;
+    s->num_plat_region_addrs = s->num_regions;
+
+    return 0;
+}
+
+static int realize_irqs(PlatBusDeviceState *s, PlatBusState *bus, Error **errp)
+{
+    uint32_t *irqs = g_new(uint32_t, s->num_irqs);
+    int r, i;
+
+    /* get our IRQs */
+    for (i = 0; i < s->num_irqs; i++) {
+        if (s->num_plat_irqs > i) {
+            /* user defined IRQ */
+            irqs[i] = s->plat_irqs[i];
+        } else {
+            /* dynamically allocated IRQ */
+            irqs[i] = PLATBUS_DYNAMIC;
+        }
+
+        r = platbus_map_irq(bus, &irqs[i], s->irqs[i]);
+        if (r) {
+            error_setg(errp, "PlatBus Device: Could not map IRQ %d", irqs[i]);
+            return -1;
+        }
+    }
+
+    /* update our IRQ list, so that we can see it with info qtree */
+    s->plat_irqs = irqs;
+    s->num_plat_irqs = s->num_irqs;
+
+    return 0;
+}
+
+static void platbus_device_realize(DeviceState *dev, Error **errp)
+{
+    PlatBusDeviceState *s = PLATBUS_DEVICE(dev);
+    PlatBusState *bus = PLAT_BUS(qdev_get_parent_bus(dev));
+
+    /* Register memory regions and IRQs */
+    if (realize_regions(s, bus, errp) || realize_irqs(s, bus, errp)) {
+        return;
+    }
+
+    /* Tell the bus that we're here */
+    QTAILQ_INSERT_TAIL(&bus->devices, s, next);
+}
+
+static Property platbus_device_properties[] = {
+    /* memory regions for a device */
+    DEFINE_PROP_ARRAY("regions", PlatBusDeviceState, num_plat_region_addrs,
+                      plat_region_addrs, qdev_prop_uint64, uint64_t),
+    /* interrupts for a device */
+    DEFINE_PROP_ARRAY("irqs", PlatBusDeviceState, num_plat_irqs,
+                      plat_irqs, qdev_prop_uint32, uint32_t),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void platbus_device_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = platbus_device_realize;
+    dc->bus_type = TYPE_PLAT_BUS;
+    dc->props = platbus_device_properties;
+}
+
+static const TypeInfo platbus_device_type_info = {
+    .name = TYPE_PLATBUS_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(PlatBusDeviceState),
+    .abstract = true,
+    .class_init = platbus_device_class_init,
+};
+
+
+static void device_register_types(void)
+{
+    type_register_static(&platbus_device_type_info);
+}
+
+type_init(device_register_types)
+
+/******** public methods *********/
+
+void platbus_device_set_irqs_array(PlatBusDeviceState *dev, int n,
+                                   qemu_irq **irqs)
+{
+    qemu_irq **irqs_v = g_new(qemu_irq *, n);
+    memcpy(irqs_v, irqs, sizeof(qemu_irq *) * n);
+
+    dev->irqs = irqs_v;
+    dev->num_irqs = n;
+}
+
+void platbus_device_set_regions_array(PlatBusDeviceState *dev, int n,
+                                      MemoryRegion **regions)
+{
+    MemoryRegion **regions_v = g_new(MemoryRegion *, n);
+    memcpy(regions_v, regions, sizeof(MemoryRegion *) * n);
+
+    dev->regions = regions_v;
+    dev->num_regions = n;
+}
diff --git a/include/hw/platbus/device.h b/include/hw/platbus/device.h
new file mode 100644
index 0000000..f8cbc56
--- /dev/null
+++ b/include/hw/platbus/device.h
@@ -0,0 +1,102 @@
+/*
+ * Generic platform bus with dynamic IRQ and IO placement
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Authors: Alexander Graf,   <agraf@suse.de>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ */
+
+#ifndef QEMU_HW_PLATBUS_DEVICE_H
+#define QEMU_HW_PLATBUS_DEVICE_H
+
+#include "qemu-common.h"
+#include "hw/qdev.h"
+
+#define TYPE_PLATBUS_DEVICE "platbus-device"
+#define PLATBUS_DEVICE(obj) OBJECT_CHECK(PlatBusDeviceState, (obj), TYPE_PLATBUS_DEVICE)
+
+typedef struct PlatBusDeviceState {
+    /*< private >*/
+
+    DeviceState parent_obj;
+    QTAILQ_ENTRY(PlatBusDeviceState) next;
+
+    /* these get set by children through platbus_device_set_xxx() */
+    uint32_t num_regions;
+    MemoryRegion **regions;
+    uint32_t num_irqs;
+    qemu_irq **irqs;
+
+    /*< public >*/
+
+    /* these get set by the user though qdev parameters */
+    uint32_t num_plat_region_addrs;
+    uint64_t *plat_region_addrs;
+    uint32_t num_plat_irqs;
+    uint32_t *plat_irqs;
+} PlatBusDeviceState;
+
+
+/******** public methods *********/
+
+
+/**
+ * platbus_device_set_regions:
+ * @dev: Parent PlatBusDevice object
+ * @...: Pointers to properly initialized MemoryRegions
+ *
+ * Call this as PlatBusDevice child to tell your parent the location of your
+ * already initialized memory region objects.
+ */
+#define platbus_device_set_regions(dev, ...)                                   \
+    do {                                                                       \
+        MemoryRegion *regions[] = { __VA_ARGS__ };                             \
+        platbus_device_set_regions_array(dev, ARRAY_SIZE(regions), regions);   \
+    } while (0)
+
+/**
+ * platbus_device_set_regions_array:
+ * @dev: Parent PlatBusDevice object
+ * @n: Number of regions
+ * @regions: Pointers to properly initialized MemoryRegions
+ *
+ * Call this as PlatBusDevice child to tell your parent the location of your
+ * already initialized memory region objects.
+ */
+void platbus_device_set_regions_array(PlatBusDeviceState *dev, int n,
+                                      MemoryRegion **regions);
+
+/**
+ * platbus_device_set_irqs:
+ * @dev: Parent PlatBusDevice object
+ * @...: Pointers to qemu_irq fields
+ *
+ * Call this as PlatBusDevice child to tell your parent the location of your
+ * qemu_irq fields. These fields will get populated once the bus is fully
+ * initialized.
+ */
+#define platbus_device_set_irqs(dev, ...)                                      \
+    do {                                                                       \
+        qemu_irq *irqs[] = { __VA_ARGS__ };                                    \
+        platbus_device_set_irqs_array(dev, ARRAY_SIZE(irqs), irqs);            \
+    } while (0)
+
+/**
+ * platbus_device_set_irqs_array:
+ * @dev: Parent PlatBusDevice object
+ * @n: Number of irqs
+ * @regions: Pointers to qemu_irq fields
+ *
+ * Call this as PlatBusDevice child to tell your parent the location of your
+ * qemu_irq fields. These fields will get populated once the bus is fully
+ * initialized.
+ */
+void platbus_device_set_irqs_array(PlatBusDeviceState *dev, int n,
+                                   qemu_irq **irqs);
+
+#endif /* !QEMU_HW_PLATBUS_DEVICE_H */
-- 
1.8.1.4

  parent reply	other threads:[~2013-07-22 17:50 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-22 17:50 [Qemu-devel] [PATCH 0/9] Add platform bus Alexander Graf
2013-07-22 17:50 ` [Qemu-devel] [PATCH 1/9] PlatBus: Add Platform Bus Alexander Graf
2013-07-22 17:50 ` Alexander Graf [this message]
2013-07-22 17:50 ` [Qemu-devel] [PATCH 3/9] PlatBus: Add Sysbus/Platform bridge device Alexander Graf
2013-07-22 17:50 ` [Qemu-devel] [PATCH 4/9] PlatBus: Hook up into Makefile system Alexander Graf
2013-07-22 17:50 ` [Qemu-devel] [PATCH 5/9] PPC: Add platform bus to the default compile set Alexander Graf
2013-07-22 17:50 ` [Qemu-devel] [PATCH 6/9] PlatBus: Add serial-platbus device Alexander Graf
2013-07-22 18:26   ` Peter Maydell
2013-07-22 18:56     ` Alexander Graf
2013-07-24 20:16       ` Scott Wood
2013-07-24 20:25         ` Peter Maydell
2013-07-22 17:50 ` [Qemu-devel] [PATCH 7/9] PPC: Add PlatBus Serial to default configs Alexander Graf
2013-07-22 17:50 ` [Qemu-devel] [PATCH 8/9] PPC: E500: Spawn PlatBus bridge for ppce500 machine Alexander Graf
2013-07-22 17:50 ` [Qemu-devel] [PATCH 9/9] PPC: E500: Add PlatBus device tree walker Alexander Graf
2013-07-22 18:21 ` [Qemu-devel] [PATCH 0/9] Add platform bus Peter Maydell
2013-07-22 18:55   ` Alexander Graf
2013-07-23 12:19   ` Paolo Bonzini
2013-07-23 12:22     ` Peter Maydell
2013-07-23 12:34       ` Paolo Bonzini
2013-07-23 12:40         ` Peter Maydell
2013-07-23 13:06           ` Paolo Bonzini
2013-07-23 14:26           ` Anthony Liguori
2013-07-23 14:28             ` Peter Maydell
2013-07-23 12:29     ` François Revol
2013-07-22 19:38 ` Anthony Liguori
2013-07-22 19:44   ` Alexander Graf
2013-07-22 19:52     ` Anthony Liguori
2013-07-22 21:50       ` Peter Maydell
2013-07-22 22:05         ` Anthony Liguori
2013-07-22 22:34           ` Peter Maydell
2013-07-22 23:03             ` Andreas Färber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1374515411-43818-3-git-send-email-agraf@suse.de \
    --to=agraf@suse.de \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).