All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation
@ 2018-08-09 11:40 Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 1/4] Add MEN " Johannes Thumshirn
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2018-08-09 11:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Johannes Thumshirn

This series adds support for emulating FPGAs by Men Mikroelektronik
Nürnberg and expose the FPGA itself as a bus. The IP-Cores implemented
in the FPGA are represented as devices hanging off that bus. This is the
same aproach that is used in the Linux kernel as well for these devices.

The main intention for this series is to have a test-bed for Linux
Kernel patches targeting the bus and/or sub-devices of it for people
who do not have access the hardware.

Changes since v1:
* Updated License comments of the files (Peter Maydell)
* Added <public>/<private> annotations (Philippe Mathieu-Daudé)

Johannes Thumshirn (4):
  Add MEN Chameleon Bus emulation
  Add MEN Chameleon Bus via PCI carrier
  serial-mcb: Add serial via MEN chameleon bus
  wdt_z069: Add support for MEN 16z069 Watchdog

 default-configs/pci.mak   |   1 +
 hw/Makefile.objs          |   1 +
 hw/char/Makefile.objs     |   1 +
 hw/char/serial-mcb.c      | 100 +++++++++++++++
 hw/mcb/Makefile.objs      |   2 +
 hw/mcb/mcb-pci.c          | 305 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/mcb/mcb.c              | 180 +++++++++++++++++++++++++++
 hw/watchdog/Makefile.objs |   1 +
 hw/watchdog/wdt_z069.c    | 215 ++++++++++++++++++++++++++++++++
 include/hw/mcb/mcb.h      | 104 ++++++++++++++++
 10 files changed, 910 insertions(+)
 create mode 100644 hw/char/serial-mcb.c
 create mode 100644 hw/mcb/Makefile.objs
 create mode 100644 hw/mcb/mcb-pci.c
 create mode 100644 hw/mcb/mcb.c
 create mode 100644 hw/watchdog/wdt_z069.c
 create mode 100644 include/hw/mcb/mcb.h

-- 
2.16.4

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

* [Qemu-devel] [PATCH v2 1/4] Add MEN Chameleon Bus emulation
  2018-08-09 11:40 [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
@ 2018-08-09 11:40 ` Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 2/4] Add MEN Chameleon Bus via PCI carrier Johannes Thumshirn
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2018-08-09 11:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Johannes Thumshirn

The MEN Chameleon Bus (MCB) is an on-chip bus system exposing IP Cores of an
FPGA to a outside bus system like PCIe.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
---
 default-configs/pci.mak |   1 +
 hw/Makefile.objs        |   1 +
 hw/mcb/Makefile.objs    |   1 +
 hw/mcb/mcb.c            | 180 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/mcb/mcb.h    | 104 ++++++++++++++++++++++++++++
 5 files changed, 287 insertions(+)
 create mode 100644 hw/mcb/Makefile.objs
 create mode 100644 hw/mcb/mcb.c
 create mode 100644 include/hw/mcb/mcb.h

diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index de53d20ac62c..341498615d6e 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -46,3 +46,4 @@ CONFIG_VGA=y
 CONFIG_VGA_PCI=y
 CONFIG_IVSHMEM_DEVICE=$(CONFIG_IVSHMEM)
 CONFIG_ROCKER=y
+CONFIG_MCB=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index a19c1417ed3e..96ab195a24b9 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -17,6 +17,7 @@ devices-dirs-$(CONFIG_IPACK) += ipack/
 devices-dirs-$(CONFIG_IPMI) += ipmi/
 devices-dirs-$(CONFIG_SOFTMMU) += isa/
 devices-dirs-$(CONFIG_SOFTMMU) += misc/
+devices-dirs-$(CONFIG_MCB) += mcb/
 devices-dirs-$(CONFIG_SOFTMMU) += net/
 devices-dirs-$(CONFIG_SOFTMMU) += rdma/
 devices-dirs-$(CONFIG_SOFTMMU) += nvram/
diff --git a/hw/mcb/Makefile.objs b/hw/mcb/Makefile.objs
new file mode 100644
index 000000000000..32427c987c44
--- /dev/null
+++ b/hw/mcb/Makefile.objs
@@ -0,0 +1 @@
+common-obj-$(CONFIG_MCB) += mcb.o
diff --git a/hw/mcb/mcb.c b/hw/mcb/mcb.c
new file mode 100644
index 000000000000..a9ec3d13dc86
--- /dev/null
+++ b/hw/mcb/mcb.c
@@ -0,0 +1,180 @@
+/*
+ * QEMU MEN Chameleon Bus emulation
+ *
+ * Copyright (C) 2016 - 2018 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/mcb/mcb.h"
+
+ChameleonDeviceDescriptor *mcb_new_chameleon_descriptor(MCBus *bus, uint8_t id,
+                                                        uint8_t rev,
+                                                        uint8_t var,
+                                                        uint32_t size)
+{
+    BusChild *kid;
+    ChameleonDeviceDescriptor *gdd;
+    uint32_t reg1 = 0;
+    uint32_t offset = 0x200;
+    uint32_t end = 0;
+
+    gdd =  g_new0(ChameleonDeviceDescriptor, 1);
+    if (!gdd) {
+        return NULL;
+    }
+
+    reg1 |= GDD_DEV(id);
+    reg1 |= GDD_DTY(CHAMELEON_DTYPE_GENERAL);
+    reg1 |= GDD_REV(rev);
+    reg1 |= GDD_VAR(var);
+    gdd->reg1 = cpu_to_le32(reg1);
+
+    QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) {
+        DeviceState *qdev = kid->child;
+        MCBDevice *mdev = MCB_DEVICE(qdev);
+
+        if (mdev->gdd) {
+            offset = mdev->gdd->offset;
+            end = offset + mdev->gdd->size;
+        }
+    }
+
+    gdd->offset = offset + end;
+    gdd->size = size;
+
+    return gdd;
+}
+
+static void mcb_irq_handler(void *opaque, int irq_num, int level)
+{
+    MCBDevice *dev = opaque;
+    MCBus *bus = MCB_BUS(qdev_get_parent_bus(DEVICE(dev)));
+
+    if (bus->set_irq) {
+        bus->set_irq(dev, irq_num, level);
+    }
+}
+
+qemu_irq mcb_allocate_irq(MCBDevice *dev)
+{
+    int irq = 0;
+    return qemu_allocate_irq(mcb_irq_handler, dev, irq);
+}
+
+MCBDevice *mcb_device_find(MCBus *bus, hwaddr addr)
+{
+    BusChild *kid;
+    uint32_t start;
+    uint32_t end;
+
+    QTAILQ_FOREACH(kid, &BUS(bus)->children, sibling) {
+        DeviceState *qdev = kid->child;
+        MCBDevice *mdev = MCB_DEVICE(qdev);
+
+        start = mdev->gdd->offset;
+        end = start + mdev->gdd->size;
+
+        if (addr >= start && addr <= end) {
+            return mdev;
+        }
+    }
+    return NULL;
+}
+
+void mcb_bus_new_inplace(MCBus *bus, size_t bus_size,
+                         DeviceState *parent,
+                         const char *name, uint8_t slots,
+                         qemu_irq_handler handler)
+{
+    qbus_create_inplace(bus, bus_size, TYPE_MCB_BUS, parent, name);
+    bus->n_slots = slots;
+    bus->set_irq = handler;
+}
+
+static void mcb_device_realize(DeviceState *dev, Error **errp)
+{
+    MCBDevice *mdev = MCB_DEVICE(dev);
+    MCBus *bus = MCB_BUS(qdev_get_parent_bus(dev));
+    MCBDeviceClass *k = MCB_DEVICE_GET_CLASS(dev);
+
+    if (mdev->slot < 0) {
+        mdev->slot = bus->free_slot;
+    }
+
+    if (mdev->slot >= bus->n_slots) {
+        error_setg(errp, "Only %" PRIu8 " slots available.", bus->n_slots);
+        return;
+    }
+    bus->free_slot = mdev->slot + 1;
+
+    mdev->irq = qemu_allocate_irqs(bus->set_irq, mdev, 1);
+
+    k->realize(dev, errp);
+}
+
+static void mcb_device_unrealize(DeviceState *dev, Error **errp)
+{
+    MCBDevice *mdev = MCB_DEVICE(dev);
+    MCBDeviceClass *k = MCB_DEVICE_GET_CLASS(dev);
+    Error *err = NULL;
+
+    if (k->unrealize) {
+        k->unrealize(dev, &err);
+        error_propagate(errp, err);
+        return;
+    }
+
+    qemu_free_irqs(mdev->irq, 1);
+}
+
+static Property mcb_device_props[] = {
+    DEFINE_PROP_INT32("slot", MCBDevice, slot, -1),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void mcb_device_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *k = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_INPUT, k->categories);
+    k->bus_type = TYPE_MCB_BUS;
+    k->realize = mcb_device_realize;
+    k->unrealize = mcb_device_unrealize;
+    k->props = mcb_device_props;
+}
+
+const VMStateDescription vmstate_mcb_device = {
+    .name = "mcb_device",
+    .version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(slot, MCBDevice),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const TypeInfo mcb_device_info = {
+    .name = TYPE_MCB_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(MCBDevice),
+    .class_size = sizeof(MCBDeviceClass),
+    .class_init = mcb_device_class_init,
+    .abstract = true,
+};
+
+static const TypeInfo mcb_bus_info = {
+    .name = TYPE_MCB_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(MCBus),
+};
+
+static void mcb_register_types(void)
+{
+    type_register_static(&mcb_device_info);
+    type_register_static(&mcb_bus_info);
+}
+
+type_init(mcb_register_types);
diff --git a/include/hw/mcb/mcb.h b/include/hw/mcb/mcb.h
new file mode 100644
index 000000000000..e546d2319182
--- /dev/null
+++ b/include/hw/mcb/mcb.h
@@ -0,0 +1,104 @@
+/*
+ * QEMU MEN Chameleon Bus emulation
+ *
+ * Copyright (C) 2016 - 2018 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_MCB_H
+#define QEMU_MCB_H
+
+#include "hw/qdev.h"
+
+#define CHAMELEON_DTYPE_GENERAL  0x0
+#define CHAMELEON_DTYPE_END 0xf
+
+typedef struct {
+    uint32_t reg1;
+    uint32_t reg2;
+    uint32_t offset;
+    uint32_t size;
+} ChameleonDeviceDescriptor;
+
+#define GDD_DEV(x) (((x) & 0x3ff) << 18)
+#define GDD_DTY(x) (((x) & 0xf) << 28)
+#define GDD_REV(x) (((x) & 0x3f) << 5)
+#define GDD_VAR(x) (((x) & 0x3f) << 11)
+
+/* GDD Register 1 fields */
+#define GDD_IRQ(x) ((x) & 0x1f)
+
+/* GDD Register 2 fields */
+#define GDD_BAR(x) ((x) & 0x7)
+#define GDD_INS(x) (((x) >> 3) & 0x3f)
+#define GDD_GRP(x) (((x) >> 9) & 0x3f)
+
+typedef struct MCBus MCBus;
+
+#define TYPE_MCB_BUS "MEN Chameleon Bus"
+#define MCB_BUS(obj) OBJECT_CHECK(MCBus, (obj), TYPE_MCB_BUS)
+
+struct MCBus {
+    /*< private >*/
+    BusState parent_obj;
+
+    uint8_t n_slots;
+    uint8_t free_slot;
+    qemu_irq_handler set_irq;
+    MemoryRegion mmio_region;
+};
+
+typedef struct MCBDevice MCBDevice;
+typedef struct MCBDeviceClass MCBDeviceClass;
+
+#define TYPE_MCB_DEVICE "mcb-device"
+#define MCB_DEVICE(obj) \
+    OBJECT_CHECK(MCBDevice, (obj), TYPE_MCB_DEVICE)
+#define MCB_DEVICE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(MCBDeviceClass, (klass), TYPE_MCB_DEVICE)
+#define MCB_DEVICE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(MCBDeviceClass, (obj), TYPE_MCB_DEVICE)
+
+struct MCBDeviceClass {
+    /*< private >*/
+    DeviceClass parent_class;
+    /*< public >*/
+
+
+    DeviceRealize realize;
+    DeviceUnrealize unrealize;
+};
+
+struct MCBDevice {
+    /*< private >*/
+    DeviceState parent_obj;
+    /*< public >*/
+
+    qemu_irq *irq;
+    ChameleonDeviceDescriptor *gdd;
+    int slot;
+
+    uint8_t rev;
+    uint8_t var;
+};
+
+extern const VMStateDescription vmstate_mcb_device;
+
+ChameleonDeviceDescriptor *mcb_new_chameleon_descriptor(MCBus *bus, uint8_t id,
+                                                        uint8_t rev,
+                                                        uint8_t var,
+                                                        uint32_t size);
+
+#define VMSTATE_MCB_DEVICE(_field, _state)      \
+    VMSTATE_STRUCT(_field, _state, 1, vmstate_mcb_device, MCBDevice)
+
+MCBDevice *mcb_device_find(MCBus *bus, hwaddr addr);
+void mcb_bus_new_inplace(MCBus *bus, size_t bus_size,
+                         DeviceState *parent,
+                         const char *name, uint8_t slots,
+                         qemu_irq_handler handler);
+
+qemu_irq mcb_allocate_irq(MCBDevice *dev);
+#endif
-- 
2.16.4

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

* [Qemu-devel] [PATCH v2 2/4] Add MEN Chameleon Bus via PCI carrier
  2018-08-09 11:40 [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 1/4] Add MEN " Johannes Thumshirn
@ 2018-08-09 11:40 ` Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 3/4] serial-mcb: Add serial via MEN chameleon bus Johannes Thumshirn
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2018-08-09 11:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Johannes Thumshirn

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
---
 hw/mcb/Makefile.objs |   1 +
 hw/mcb/mcb-pci.c     | 305 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 306 insertions(+)
 create mode 100644 hw/mcb/mcb-pci.c

diff --git a/hw/mcb/Makefile.objs b/hw/mcb/Makefile.objs
index 32427c987c44..125f4a84700a 100644
--- a/hw/mcb/Makefile.objs
+++ b/hw/mcb/Makefile.objs
@@ -1 +1,2 @@
 common-obj-$(CONFIG_MCB) += mcb.o
+common-obj-$(CONFIG_MCB) += mcb-pci.o
diff --git a/hw/mcb/mcb-pci.c b/hw/mcb/mcb-pci.c
new file mode 100644
index 000000000000..a1a47980766f
--- /dev/null
+++ b/hw/mcb/mcb-pci.c
@@ -0,0 +1,305 @@
+/*
+ * QEMU MEN Chameleon Bus emulation
+ *
+ * Copyright (C) 2016 - 2018 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/mcb/mcb.h"
+#include "hw/pci/pci.h"
+
+/* #define DEBUG_MPCI 1 */
+
+#ifdef DEBUG_MPCI
+#define DPRINTF(fmt, ...)                                               \
+    do { fprintf(stderr, "mcb-pci: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+typedef struct {
+    uint8_t revision;
+    char model;
+    uint8_t minor;
+    uint8_t bus_type;
+    uint16_t magic;
+    uint16_t reserved;
+    /* This one has no '\0' at the end!!! */
+    char filename[12];
+} ChameleonFPGAHeader;
+#define CHAMELEON_BUS_TYPE_WISHBONE 0
+#define CHAMELEONV2_MAGIC 0xabce
+
+typedef struct {
+    PCIDevice dev;
+    MCBus bus;
+    MemoryRegion ctbl;
+    uint16_t status;
+    uint8_t int_set;
+    ChameleonFPGAHeader *header;
+
+    uint8_t minor;
+    uint8_t rev;
+    uint8_t model;
+} MPCIState;
+
+#define TYPE_MCB_PCI "mcb-pci"
+
+#define MPCI(obj)                                       \
+    OBJECT_CHECK(MPCIState, (obj), TYPE_MCB_PCI)
+
+#define CHAMELEON_TABLE_SIZE 0x200
+#define N_MODULES 32
+
+#define PCI_VENDOR_ID_MEN 0x1a88
+#define PCI_DEVICE_ID_MEN_MCBPCI 0x4d45
+
+static uint32_t read_header(MPCIState *s, hwaddr addr)
+{
+    uint32_t ret = 0;
+    ChameleonFPGAHeader *header = s->header;
+
+    switch (addr / 4) {
+    case 0:
+        ret |= header->revision;
+        ret |= header->model << 8;
+        ret |= header->minor << 16;
+        ret |= header->bus_type << 24;
+        break;
+    case 1:
+        ret |= header->magic;
+        ret |= header->reserved << 16;
+        break;
+    case 2:
+        memcpy(&ret, header->filename, sizeof(uint32_t));
+        break;
+    case 3:
+        memcpy(&ret, header->filename + sizeof(uint32_t),
+               sizeof(uint32_t));
+        break;
+    case 4:
+        memcpy(&ret, header->filename + 2 * sizeof(uint32_t),
+               sizeof(uint32_t));
+    }
+
+    return ret;
+}
+
+static uint32_t read_gdd(MCBDevice *mdev, int reg)
+{
+    ChameleonDeviceDescriptor *gdd;
+    uint32_t ret = 0;
+
+    gdd = mdev->gdd;
+
+    switch (reg) {
+    case 0:
+        ret = gdd->reg1;
+        break;
+    case 1:
+        ret = gdd->reg2;
+        break;
+    case 2:
+        ret = gdd->offset;
+        break;
+    case 3:
+        ret = gdd->size;
+        break;
+    }
+
+    return ret;
+}
+
+static uint64_t mpci_chamtbl_read(void *opaque, hwaddr addr, unsigned size)
+{
+    MPCIState *s = opaque;
+    MCBus *bus = &s->bus;
+    MCBDevice *mdev;
+    uint32_t ret = 0;
+
+    DPRINTF("Read from address 0x%lx size %d\n", addr, size);
+
+    if (addr < sizeof(ChameleonFPGAHeader)) {
+        return le32_to_cpu(read_header(s, addr));
+    } else if (addr >= sizeof(ChameleonFPGAHeader) &&
+               addr < CHAMELEON_TABLE_SIZE) {
+        /* Handle read on chameleon table */
+        BusChild *kid;
+        DeviceState *qdev;
+        int slot;
+        int offset;
+        int i;
+
+        offset = addr - sizeof(ChameleonFPGAHeader);
+        slot = offset / sizeof(ChameleonDeviceDescriptor);
+
+        kid = QTAILQ_FIRST(&BUS(bus)->children);
+        for (i = 0; i < slot; i++) {
+            kid = QTAILQ_NEXT(kid, sibling);
+            if (!kid) { /* Last element */
+                DPRINTF("Last element: 0x%08x\n", ~0U);
+                return ~0U;
+            }
+        }
+        qdev = kid->child;
+        mdev = MCB_DEVICE(qdev);
+        offset -= slot * 16;
+
+        ret = read_gdd(mdev, offset / 4);
+        return le32_to_cpu(ret);
+    }
+
+    return ret;
+}
+
+static void mpci_chamtbl_write(void *opaque, hwaddr addr, uint64_t val,
+                               unsigned size)
+{
+
+    if (addr < CHAMELEON_TABLE_SIZE)
+        DPRINTF("Invalid write to 0x%x: 0x%x\n", (unsigned) addr,
+                (unsigned) val);
+
+    return;
+}
+
+static const MemoryRegionOps mpci_chamtbl_ops = {
+    .read = mpci_chamtbl_read,
+    .write = mpci_chamtbl_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    },
+};
+
+static void mcb_pci_set_irq(void *opaque, int intno, int level)
+{
+    MCBDevice *mdev = opaque;
+    MCBus *bus = MCB_BUS(qdev_get_parent_bus(DEVICE(mdev)));
+    PCIDevice *pcidev = PCI_DEVICE(BUS(bus)->parent);
+    MPCIState *dev = MPCI(pcidev);
+
+    if (level) {
+        pci_set_irq(&dev->dev, !dev->int_set);
+        pci_set_irq(&dev->dev,  dev->int_set);
+    } else {
+        uint16_t level_status = dev->status;
+
+        if (level_status && !dev->int_set) {
+            pci_irq_assert(&dev->dev);
+            dev->int_set = 1;
+        } else if (!level_status && dev->int_set) {
+            pci_irq_deassert(&dev->dev);
+            dev->int_set = 0;
+        }
+    }
+}
+
+static void mcb_pci_write_config(PCIDevice *pci_dev, uint32_t address,
+                                 uint32_t val, int len)
+{
+    pci_default_write_config(pci_dev, address, val, len);
+}
+
+static void mcb_pci_realize(PCIDevice *pci_dev, Error **errp)
+{
+    MPCIState *s = MPCI(pci_dev);
+    uint8_t *pci_conf = s->dev.config;
+    ChameleonFPGAHeader *header;
+    MCBus *bus = &s->bus;
+
+    header = g_new0(ChameleonFPGAHeader, 1);
+
+    s->header = header;
+
+    header->revision = s->rev;
+    header->model = (char) s->model;
+    header->minor = s->minor;
+    header->bus_type = CHAMELEON_BUS_TYPE_WISHBONE;
+    header->magic = CHAMELEONV2_MAGIC;
+    memcpy(&header->filename, "QEMU MCB PCI", 12);
+
+    pci_dev->config_write = mcb_pci_write_config;
+    pci_set_byte(pci_conf + PCI_INTERRUPT_PIN, 0x01); /* Interrupt pin A */
+    pci_conf[PCI_COMMAND] = PCI_COMMAND_MEMORY;
+
+    mcb_bus_new_inplace(&s->bus, sizeof(s->bus), DEVICE(pci_dev), NULL,
+                        N_MODULES, mcb_pci_set_irq);
+
+    memory_region_init(&bus->mmio_region, OBJECT(s), "mcb-pci.mmio",
+                       2048 * 1024);
+    memory_region_init_io(&s->ctbl, OBJECT(s), &mpci_chamtbl_ops,
+                          s, "mpci_chamtbl_ops", CHAMELEON_TABLE_SIZE);
+    memory_region_add_subregion(&bus->mmio_region, 0, &s->ctbl);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     &bus->mmio_region);
+
+}
+
+static void mcb_pci_unrealize(PCIDevice *pci_dev)
+{
+    MPCIState *s = MPCI(pci_dev);
+
+    g_free(s->header);
+    s->header = NULL;
+}
+
+static const VMStateDescription vmstate_mcb_pci = {
+    .name = "mcb-pci",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, MPCIState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property mcb_pci_props[] = {
+    DEFINE_PROP_UINT8("revision", MPCIState, rev, 1),
+    DEFINE_PROP_UINT8("minor", MPCIState, minor, 0),
+    DEFINE_PROP_UINT8("model", MPCIState, model, 0x41),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void mcb_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->realize = mcb_pci_realize;
+    k->exit = mcb_pci_unrealize;
+    k->vendor_id = PCI_VENDOR_ID_MEN;
+    k->device_id = PCI_DEVICE_ID_MEN_MCBPCI;
+    k->class_id = PCI_CLASS_BRIDGE_OTHER;
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->desc = "MEN Chameleon Bus over PCI";
+    dc->vmsd = &vmstate_mcb_pci;
+    dc->props = mcb_pci_props;
+}
+
+static const TypeInfo mcb_pci_info = {
+    .name = TYPE_MCB_PCI,
+    .parent = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(MPCIState),
+    .class_init = mcb_pci_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { INTERFACE_PCIE_DEVICE },
+        { }
+    },
+};
+
+static void mcb_pci_register_types(void)
+{
+    type_register(&mcb_pci_info);
+}
+type_init(mcb_pci_register_types);
-- 
2.16.4

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

* [Qemu-devel] [PATCH v2 3/4] serial-mcb: Add serial via MEN chameleon bus
  2018-08-09 11:40 [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 1/4] Add MEN " Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 2/4] Add MEN Chameleon Bus via PCI carrier Johannes Thumshirn
@ 2018-08-09 11:40 ` Johannes Thumshirn
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 4/4] wdt_z069: Add support for MEN 16z069 Watchdog Johannes Thumshirn
  2018-08-22 12:47 ` [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2018-08-09 11:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Johannes Thumshirn

Add MEN z125 UART over MEN Chameleon Bus emulation.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
---
 hw/char/Makefile.objs |   1 +
 hw/char/serial-mcb.c  | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 hw/char/serial-mcb.c

diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index b57053129107..063f1720974d 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -6,6 +6,7 @@ common-obj-$(CONFIG_PL011) += pl011.o
 common-obj-$(CONFIG_SERIAL) += serial.o
 common-obj-$(CONFIG_SERIAL_ISA) += serial-isa.o
 common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o
+common-obj-$(CONFIG_MCB) += serial-mcb.o
 common-obj-$(CONFIG_VIRTIO_SERIAL) += virtio-console.o
 common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o
 common-obj-$(CONFIG_XEN) += xen_console.o
diff --git a/hw/char/serial-mcb.c b/hw/char/serial-mcb.c
new file mode 100644
index 000000000000..5e1ef27815c6
--- /dev/null
+++ b/hw/char/serial-mcb.c
@@ -0,0 +1,100 @@
+/*
+ * QEMU MEN 16z125 UART over MCB emulation
+ *
+ * Copyright (C) 2016 - 2018 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/char/serial.h"
+#include "hw/mcb/mcb.h"
+
+typedef struct {
+    /*< private >*/
+    MCBDevice dev;
+    /*< public >*/
+
+    SerialState state;
+} MCBSerialState;
+
+static void serial_mcb_realize(DeviceState *dev, Error **errp)
+{
+    MCBDevice *mdev = MCB_DEVICE(dev);
+    MCBSerialState *mss = DO_UPCAST(MCBSerialState, dev, mdev);
+    MCBus *bus = MCB_BUS(qdev_get_parent_bus(DEVICE(dev)));
+    SerialState *s = &mss->state;
+    Error *err = 0;
+
+    mdev->gdd = mcb_new_chameleon_descriptor(bus, 125, mdev->rev,
+                                             mdev->var, 0x10);
+    if (!mdev->gdd) {
+        return;
+    }
+
+    s->baudbase = 115200;
+    serial_realize_core(s, &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    s->irq = mcb_allocate_irq(&mss->dev);
+    memory_region_init_io(&s->io, OBJECT(mss), &serial_io_ops, s, "serial", 8);
+    memory_region_add_subregion(&bus->mmio_region, mdev->gdd->offset, &s->io);
+}
+
+static void serial_mcb_unrealize(DeviceState *dev, Error **errp)
+{
+    MCBDevice *mdev = MCB_DEVICE(dev);
+
+    g_free(&mdev->gdd);
+}
+
+static const VMStateDescription vmstate_mcb_serial = {
+    .name = "mcb-serial",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_MCB_DEVICE(dev, MCBSerialState),
+        VMSTATE_STRUCT(state, MCBSerialState, 0, vmstate_serial, SerialState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property serial_mcb_properties[] = {
+    DEFINE_PROP_CHR("chardev", MCBSerialState, state.chr),
+    DEFINE_PROP_UINT8("rev", MCBSerialState, dev.rev, 0),
+    DEFINE_PROP_UINT8("var", MCBSerialState, dev.var, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void serial_mcb_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    MCBDeviceClass *mc = MCB_DEVICE_CLASS(klass);
+
+    mc->realize = serial_mcb_realize;
+    mc->unrealize = serial_mcb_unrealize;
+
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+    dc->desc = "MEN 16z125 UART over MCB";
+    dc->vmsd = &vmstate_mcb_serial;
+    dc->props = serial_mcb_properties;
+}
+
+static const TypeInfo serial_mcb_info = {
+    .name = "mcb-serial",
+    .parent = TYPE_MCB_DEVICE,
+    .instance_size = sizeof(MCBSerialState),
+    .class_init = serial_mcb_class_initfn,
+};
+
+static void serial_mcb_register_types(void)
+{
+    type_register_static(&serial_mcb_info);
+}
+
+type_init(serial_mcb_register_types);
-- 
2.16.4

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

* [Qemu-devel] [PATCH v2 4/4] wdt_z069: Add support for MEN 16z069 Watchdog
  2018-08-09 11:40 [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
                   ` (2 preceding siblings ...)
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 3/4] serial-mcb: Add serial via MEN chameleon bus Johannes Thumshirn
@ 2018-08-09 11:40 ` Johannes Thumshirn
  2018-08-22 12:47 ` [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2018-08-09 11:40 UTC (permalink / raw)
  To: qemu-devel; +Cc: Johannes Thumshirn

Add 16z069 Watchdog over MEN Chameleon BUS emulation.

Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de>
---
 hw/watchdog/Makefile.objs |   1 +
 hw/watchdog/wdt_z069.c    | 215 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 216 insertions(+)
 create mode 100644 hw/watchdog/wdt_z069.c

diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
index 9589bed63a3d..ada010f1eb69 100644
--- a/hw/watchdog/Makefile.objs
+++ b/hw/watchdog/Makefile.objs
@@ -3,3 +3,4 @@ common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
 common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
 common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
 common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
+common-obj-$(CONFIG_MCB) += wdt_z069.o
diff --git a/hw/watchdog/wdt_z069.c b/hw/watchdog/wdt_z069.c
new file mode 100644
index 000000000000..9cd900bfdc17
--- /dev/null
+++ b/hw/watchdog/wdt_z069.c
@@ -0,0 +1,215 @@
+/*
+ * QEMU MEN 16z069 Watchdog over MCB emulation
+ *
+ * Copyright (C) 2018 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "sysemu/watchdog.h"
+#include "hw/mcb/mcb.h"
+
+/* #define Z069_DEBUG 1 */
+
+#ifdef Z069_DEBUG
+#define z069_debug(fmt, ...)                                        \
+    fprintf(stderr, "wdt_z069: %s: "fmt, __func__, ##__VA_ARGS__)
+#else
+#define z069_debug(fmt, ...)
+#endif
+
+#define MEN_Z069_WTR 0x10
+#define MEN_Z069_WTR_WDEN BIT(15)
+#define MEN_Z069_WTR_WDET_MASK  0x7fff
+#define MEN_Z069_WVR 0x14
+
+#define CLK_500(x) ((x) * 2) /* 500Hz in ms */
+
+typedef struct {
+    /*< private >*/
+    MCBDevice dev;
+
+    /*< public >*/
+    QEMUTimer *timer;
+
+    bool enabled;
+    unsigned int timeout;
+
+    MemoryRegion mmio;
+
+    /* Registers */
+    uint16_t wtr;
+    uint16_t wvr;
+} MENZ069State;
+
+static void men_z069_wdt_enable(MENZ069State *s)
+{
+    z069_debug("next timeout will fire in +%dms\n", s->timeout);
+    timer_mod(s->timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + s->timeout);
+}
+
+static void men_z069_wdt_disable(MENZ069State *s)
+{
+    timer_del(s->timer);
+}
+
+static uint64_t men_z069_wdt_read(void *opaque, hwaddr addr, unsigned size)
+{
+    MENZ069State *s = opaque;
+    uint64_t ret;
+
+    switch (addr) {
+    case MEN_Z069_WTR:
+        ret = s->wtr;
+        break;
+    case MEN_Z069_WVR:
+        ret = s->wvr;
+        break;
+    default:
+        ret = 0UL;
+        break;
+    }
+
+    z069_debug("returning: 0x%"PRIx64" @ 0x%lx\n", ret, addr);
+    return ret;
+}
+
+static void men_z069_wdt_write(void *opaque, hwaddr addr, uint64_t v,
+                               unsigned size)
+{
+    MENZ069State *s = opaque;
+    bool old_ena = s->enabled;
+    uint16_t val = v & 0xffff;
+    uint16_t tout;
+
+    z069_debug("got: 0x%"PRIx64" @ 0x%lx\n", v, addr);
+
+    switch (addr) {
+    case MEN_Z069_WTR:
+        s->wtr = val;
+        tout = val & MEN_Z069_WTR_WDET_MASK;
+        s->timeout = CLK_500(tout);
+        s->enabled = val & MEN_Z069_WTR_WDEN;
+        z069_debug("new timeout: %u (0x%x) %u\n", tout, tout, s->timeout);
+
+        if (old_ena && !s->enabled) {
+            men_z069_wdt_disable(s);
+        } else if (!old_ena && s->enabled) {
+            men_z069_wdt_enable(s);
+        }
+
+        break;
+    case MEN_Z069_WVR:
+        /* The watchdog trigger value toggles between 0x5555 and 0xaaaa */
+        if (val == (s->wvr ^ 0xffff)) {
+            s->wvr = val;
+            z069_debug("watchdog triggered, next timeout will fire in +%dms\n",
+                       s->timeout);
+            timer_mod(s->timer,
+                      qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + s->timeout);
+        }
+        break;
+    default:
+        break;
+    }
+    return;
+}
+
+static const MemoryRegionOps men_z069_io_ops = {
+    .read = men_z069_wdt_read,
+    .write = men_z069_wdt_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    },
+};
+
+static void men_z069_timer_expired(void *opaque)
+{
+    MENZ069State *s = opaque;
+
+    watchdog_perform_action();
+    timer_del(s->timer);
+}
+
+static void men_z069_wdt_realize(DeviceState *dev, Error **errp)
+{
+    MCBDevice *mdev = MCB_DEVICE(dev);
+    MENZ069State *s = DO_UPCAST(MENZ069State, dev, mdev);
+    MCBus *bus = MCB_BUS(qdev_get_parent_bus(DEVICE(dev)));
+
+    mdev->gdd = mcb_new_chameleon_descriptor(bus, 69, mdev->rev,
+                                             mdev->var, 0x18);
+    if (!mdev->gdd) {
+        return;
+    }
+
+    s->wvr = 0x5555;
+    s->wtr = 0x7fff;
+    s->timeout = CLK_500(s->wtr & MEN_Z069_WTR_WDET_MASK);
+    s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
+                            men_z069_timer_expired, s);
+
+    memory_region_init_io(&s->mmio, OBJECT(s),
+                          &men_z069_io_ops, s, "z069.wdt", 0x16);
+    memory_region_add_subregion(&bus->mmio_region, mdev->gdd->offset,
+                                &s->mmio);
+}
+
+static void men_z069_wdt_unrealize(DeviceState *dev, Error **errp)
+{
+    MCBDevice *mdev = MCB_DEVICE(dev);
+
+    g_free(&mdev->gdd);
+}
+
+static const VMStateDescription vmstate_z069_wdt = {
+    .name = "z069-wdt",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_MCB_DEVICE(dev, MENZ069State),
+        VMSTATE_TIMER_PTR(timer, MENZ069State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property men_z069_wdt_properties[] = {
+    DEFINE_PROP_UINT8("rev", MENZ069State, dev.rev, 0),
+    DEFINE_PROP_UINT8("var", MENZ069State, dev.var, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void men_z069_wdt_class_intifn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    MCBDeviceClass *mc = MCB_DEVICE_CLASS(klass);
+
+    mc->realize = men_z069_wdt_realize;
+    mc->unrealize = men_z069_wdt_unrealize;
+
+    dc->desc = "MEN 16z069 Watchdog Timer";
+    dc->vmsd = &vmstate_z069_wdt;
+    dc->props = men_z069_wdt_properties;
+}
+
+static const TypeInfo men_z069_wdt_info = {
+    .name = "z069-wdt",
+    .parent = TYPE_MCB_DEVICE,
+    .instance_size = sizeof(MENZ069State),
+    .class_init = men_z069_wdt_class_intifn,
+};
+
+static void men_z069_wdt_register_types(void)
+{
+    type_register_static(&men_z069_wdt_info);
+}
+
+type_init(men_z069_wdt_register_types);
-- 
2.16.4

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

* Re: [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation
  2018-08-09 11:40 [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
                   ` (3 preceding siblings ...)
  2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 4/4] wdt_z069: Add support for MEN 16z069 Watchdog Johannes Thumshirn
@ 2018-08-22 12:47 ` Johannes Thumshirn
  4 siblings, 0 replies; 6+ messages in thread
From: Johannes Thumshirn @ 2018-08-22 12:47 UTC (permalink / raw)
  To: qemu-devel

On Thu, Aug 09, 2018 at 01:40:13PM +0200, Johannes Thumshirn wrote:
> This series adds support for emulating FPGAs by Men Mikroelektronik
> Nürnberg and expose the FPGA itself as a bus. The IP-Cores implemented
> in the FPGA are represented as devices hanging off that bus. This is the
> same aproach that is used in the Linux kernel as well for these devices.
> 
> The main intention for this series is to have a test-bed for Linux
> Kernel patches targeting the bus and/or sub-devices of it for people
> who do not have access the hardware.
> 
> Changes since v1:
> * Updated License comments of the files (Peter Maydell)
> * Added <public>/<private> annotations (Philippe Mathieu-Daudé)

Ping?
-- 
Johannes Thumshirn                                          Storage
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

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

end of thread, other threads:[~2018-08-22 13:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-09 11:40 [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn
2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 1/4] Add MEN " Johannes Thumshirn
2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 2/4] Add MEN Chameleon Bus via PCI carrier Johannes Thumshirn
2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 3/4] serial-mcb: Add serial via MEN chameleon bus Johannes Thumshirn
2018-08-09 11:40 ` [Qemu-devel] [PATCH v2 4/4] wdt_z069: Add support for MEN 16z069 Watchdog Johannes Thumshirn
2018-08-22 12:47 ` [Qemu-devel] [PATCH v2 0/4] Add support for Men Chameleon Bus emulation Johannes Thumshirn

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.