* [PATCH v4 0/4] Add emulation of MEN Chameleon Hardware
@ 2023-04-18 17:35 Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 1/4] Add MEN Chameleon Bus emulation Johannes Thumshirn
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2023-04-18 17:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Javier Rodriguez, Jorge Sanjuan García,
Peter Maydell, Dmitry Fomichev, Johannes Thumshirn
Add emulation of MEN Chameleon Hardware to Qemu.
This emulation is specifically designed to test the upstream Linux kernel
drivers when one has no access to the hardware.
The emulation consists of the bus itself, a PCI hardware target creating the
bus, MEN Micro Electronic's 8250 based UART via MCB and a watchdog timer.
Changes since v2:
- Converted DPRINTF() to tracing infrastructure again (Alistair)
Changes since v2:
- Adjusted license to GPL 2 or later (Peter)
Changes since v1:
- Converted DPRINTF() to tracing infrastructure (Alistair)
- Fixed style issues (Alistair)
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
MAINTAINERS | 6 +
hw/Kconfig | 1 +
hw/char/Kconfig | 6 +
hw/char/meson.build | 1 +
hw/char/serial-mcb.c | 115 +++++++++++++++
hw/mcb/Kconfig | 8 ++
hw/mcb/mcb-pci.c | 298 +++++++++++++++++++++++++++++++++++++++
hw/mcb/mcb.c | 180 +++++++++++++++++++++++
hw/mcb/meson.build | 2 +
hw/mcb/trace-events | 4 +
hw/mcb/trace.h | 1 +
hw/meson.build | 1 +
hw/watchdog/Kconfig | 5 +
hw/watchdog/meson.build | 1 +
hw/watchdog/trace-events | 6 +
hw/watchdog/wdt_z069.c | 207 +++++++++++++++++++++++++++
include/hw/mcb/mcb.h | 106 ++++++++++++++
meson.build | 1 +
18 files changed, 949 insertions(+)
create mode 100644 hw/char/serial-mcb.c
create mode 100644 hw/mcb/Kconfig
create mode 100644 hw/mcb/mcb-pci.c
create mode 100644 hw/mcb/mcb.c
create mode 100644 hw/mcb/meson.build
create mode 100644 hw/mcb/trace-events
create mode 100644 hw/mcb/trace.h
create mode 100644 hw/watchdog/wdt_z069.c
create mode 100644 include/hw/mcb/mcb.h
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/4] Add MEN Chameleon Bus emulation
2023-04-18 17:35 [PATCH v4 0/4] Add emulation of MEN Chameleon Hardware Johannes Thumshirn
@ 2023-04-18 17:35 ` Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 2/4] Add MEN Chameleon Bus via PCI carrier Johannes Thumshirn
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2023-04-18 17:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Javier Rodriguez, Jorge Sanjuan García,
Peter Maydell, Dmitry Fomichev, Johannes Thumshirn,
Alistair Francis
The MEN Chameleon Bus (MCB) is an on-chip bus system exposing IP Cores of an
FPGA to a outside bus system like PCIe.
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Johannes Thumshirn <jth@kernel.org>
---
MAINTAINERS | 6 ++
hw/Kconfig | 1 +
hw/mcb/Kconfig | 2 +
hw/mcb/mcb.c | 180 +++++++++++++++++++++++++++++++++++++++++++
hw/mcb/meson.build | 1 +
hw/meson.build | 1 +
include/hw/mcb/mcb.h | 106 +++++++++++++++++++++++++
7 files changed, 297 insertions(+)
create mode 100644 hw/mcb/Kconfig
create mode 100644 hw/mcb/mcb.c
create mode 100644 hw/mcb/meson.build
create mode 100644 include/hw/mcb/mcb.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 2c2068ea5c..1fa5909a97 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1962,6 +1962,12 @@ R: Paolo Bonzini <pbonzini@redhat.com>
S: Odd Fixes
F: hw/char/
+MEN Chameleon Bus
+M: Johannes Thumshirn <jth@kernel.org>
+S: Maintained
+F: hw/mcb/
+F: include/hw/mcb/
+
Network devices
M: Jason Wang <jasowang@redhat.com>
S: Odd Fixes
diff --git a/hw/Kconfig b/hw/Kconfig
index ba62ff6417..f5ef84b10b 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -18,6 +18,7 @@ source intc/Kconfig
source ipack/Kconfig
source ipmi/Kconfig
source isa/Kconfig
+source mcb/Kconfig
source mem/Kconfig
source misc/Kconfig
source net/Kconfig
diff --git a/hw/mcb/Kconfig b/hw/mcb/Kconfig
new file mode 100644
index 0000000000..36a7a583a8
--- /dev/null
+++ b/hw/mcb/Kconfig
@@ -0,0 +1,2 @@
+config MCB
+ bool
diff --git a/hw/mcb/mcb.c b/hw/mcb/mcb.c
new file mode 100644
index 0000000000..1c4f693a73
--- /dev/null
+++ b/hw/mcb/mcb.c
@@ -0,0 +1,180 @@
+/*
+ * QEMU MEN Chameleon Bus emulation
+ *
+ * Copyright (C) 2023 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/mcb/mcb.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.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 end = 0x200;
+
+ 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) {
+ end += mdev->gdd->size;
+ }
+ }
+
+ gdd->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_init(MCBus *bus, size_t bus_size,
+ DeviceState *parent,
+ uint8_t n_slots,
+ qemu_irq_handler handler)
+{
+ qbus_init(bus, bus_size, TYPE_MCB_BUS, parent, NULL);
+ bus->n_slots = n_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)
+{
+ MCBDevice *mdev = MCB_DEVICE(dev);
+ MCBDeviceClass *k = MCB_DEVICE_GET_CLASS(dev);
+
+ if (k->unrealize) {
+ k->unrealize(dev);
+ 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;
+ device_class_set_props(k, 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/hw/mcb/meson.build b/hw/mcb/meson.build
new file mode 100644
index 0000000000..a385edc07c
--- /dev/null
+++ b/hw/mcb/meson.build
@@ -0,0 +1 @@
+softmmu_ss.add(when: 'CONFIG_MCB', if_true: files('mcb.c'))
diff --git a/hw/meson.build b/hw/meson.build
index c7ac7d3d75..3d1462ad8b 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -18,6 +18,7 @@ subdir('intc')
subdir('ipack')
subdir('ipmi')
subdir('isa')
+subdir('mcb')
subdir('mem')
subdir('misc')
subdir('net')
diff --git a/include/hw/mcb/mcb.h b/include/hw/mcb/mcb.h
new file mode 100644
index 0000000000..03d7e12ad2
--- /dev/null
+++ b/include/hw/mcb/mcb.h
@@ -0,0 +1,106 @@
+/*
+ * QEMU MEN Chameleon Bus emulation
+ *
+ * Copyright (C) 2023 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_MCB_H
+#define QEMU_MCB_H
+
+#include "hw/qdev-core.h"
+#include "qom/object.h"
+#include "exec/memory.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"
+OBJECT_DECLARE_SIMPLE_TYPE(MCBus, 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_init(MCBus *bus, size_t bus_size,
+ DeviceState *parent,
+ uint8_t n_slots,
+ qemu_irq_handler handler);
+
+qemu_irq mcb_allocate_irq(MCBDevice *dev);
+#endif
--
2.39.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/4] Add MEN Chameleon Bus via PCI carrier
2023-04-18 17:35 [PATCH v4 0/4] Add emulation of MEN Chameleon Hardware Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 1/4] Add MEN Chameleon Bus emulation Johannes Thumshirn
@ 2023-04-18 17:35 ` Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 3/4] serial-mcb: Add serial via MEN chameleon bus Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 4/4] wdt_z069: Add support for MEN 16z069 Watchdog Johannes Thumshirn
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2023-04-18 17:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Javier Rodriguez, Jorge Sanjuan García,
Peter Maydell, Dmitry Fomichev, Johannes Thumshirn,
Alistair Francis
Add PCI based MEN Chameleon Bus carrier emulation.
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Johannes Thumshirn <jth@kernel.org>
---
hw/mcb/Kconfig | 6 +
hw/mcb/mcb-pci.c | 298 ++++++++++++++++++++++++++++++++++++++++++++
hw/mcb/meson.build | 1 +
hw/mcb/trace-events | 4 +
hw/mcb/trace.h | 1 +
meson.build | 1 +
6 files changed, 311 insertions(+)
create mode 100644 hw/mcb/mcb-pci.c
create mode 100644 hw/mcb/trace-events
create mode 100644 hw/mcb/trace.h
diff --git a/hw/mcb/Kconfig b/hw/mcb/Kconfig
index 36a7a583a8..7deb96c2fe 100644
--- a/hw/mcb/Kconfig
+++ b/hw/mcb/Kconfig
@@ -1,2 +1,8 @@
config MCB
bool
+
+config MCB_PCI
+ bool
+ default y if PCI_DEVICES
+ depends on PCI
+ select MCB
diff --git a/hw/mcb/mcb-pci.c b/hw/mcb/mcb-pci.c
new file mode 100644
index 0000000000..905b9adb3b
--- /dev/null
+++ b/hw/mcb/mcb-pci.c
@@ -0,0 +1,298 @@
+/*
+ * QEMU MEN Chameleon Bus emulation
+ *
+ * Copyright (C) 2023 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This code is licensed under the GPL version 2 or later. 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"
+#include "hw/pci/pci_device.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+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 >> 2) {
+ 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;
+
+ trace_mpci_chamtbl_read(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 */
+ return ~0U;
+ }
+ }
+ qdev = kid->child;
+ mdev = MCB_DEVICE(qdev);
+ offset -= slot * 16;
+
+ return le32_to_cpu(read_gdd(mdev, offset / 4));
+ }
+
+ return 0;
+}
+
+static void mpci_chamtbl_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+
+ if (addr < CHAMELEON_TABLE_SIZE) {
+ trace_mpci_chamtbl_write(addr, 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);
+
+ trace_mpci_set_irq(intno, level);
+ if (level) {
+ pci_set_irq(pcidev, !dev->int_set);
+ pci_set_irq(pcidev, dev->int_set);
+ } else {
+ uint16_t level_status = dev->status;
+
+ if (level_status && !dev->int_set) {
+ pci_irq_assert(pcidev);
+ dev->int_set = 1;
+ } else if (!level_status && dev->int_set) {
+ pci_irq_deassert(pcidev);
+ 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_init(bus, sizeof(MCBus), DEVICE(pci_dev), 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;
+ device_class_set_props(dc, 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);
diff --git a/hw/mcb/meson.build b/hw/mcb/meson.build
index a385edc07c..4e1a0f0cdb 100644
--- a/hw/mcb/meson.build
+++ b/hw/mcb/meson.build
@@ -1 +1,2 @@
softmmu_ss.add(when: 'CONFIG_MCB', if_true: files('mcb.c'))
+softmmu_ss.add(when: 'CONFIG_MCB_PCI', if_true: files('mcb-pci.c'))
diff --git a/hw/mcb/trace-events b/hw/mcb/trace-events
new file mode 100644
index 0000000000..e4f71315ab
--- /dev/null
+++ b/hw/mcb/trace-events
@@ -0,0 +1,4 @@
+# mcb-pci.c
+mpci_chamtbl_read(unsigned long addr, unsigned int size) "read from address 0x%lx size %d"
+mpci_chamtbl_write(unsigned long addr, uint64_t val) "invalid write to 0x%lx: 0x%" PRIx64
+mpci_set_irq(int intno, int level) "set IRQ #%d (level=%d)"
diff --git a/hw/mcb/trace.h b/hw/mcb/trace.h
new file mode 100644
index 0000000000..35653b3381
--- /dev/null
+++ b/hw/mcb/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_mcb.h"
diff --git a/meson.build b/meson.build
index c44d05a13f..26fe8e4115 100644
--- a/meson.build
+++ b/meson.build
@@ -2990,6 +2990,7 @@ if have_system
'hw/input',
'hw/intc',
'hw/isa',
+ 'hw/mcb',
'hw/mem',
'hw/mips',
'hw/misc',
--
2.39.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 3/4] serial-mcb: Add serial via MEN chameleon bus
2023-04-18 17:35 [PATCH v4 0/4] Add emulation of MEN Chameleon Hardware Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 1/4] Add MEN Chameleon Bus emulation Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 2/4] Add MEN Chameleon Bus via PCI carrier Johannes Thumshirn
@ 2023-04-18 17:35 ` Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 4/4] wdt_z069: Add support for MEN 16z069 Watchdog Johannes Thumshirn
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2023-04-18 17:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Javier Rodriguez, Jorge Sanjuan García,
Peter Maydell, Dmitry Fomichev, Johannes Thumshirn,
Alistair Francis
Add MEN z125 UART over MEN Chameleon Bus emulation.
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Johannes Thumshirn <jth@kernel.org>
---
hw/char/Kconfig | 6 +++
hw/char/meson.build | 1 +
hw/char/serial-mcb.c | 115 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 122 insertions(+)
create mode 100644 hw/char/serial-mcb.c
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6b6cf2fc1d..9e8ebf1d3d 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -71,3 +71,9 @@ config GOLDFISH_TTY
config SHAKTI_UART
bool
+
+config SERIAL_MCB
+ bool
+ default y if MCB
+ depends on MCB
+ select SERIAL
diff --git a/hw/char/meson.build b/hw/char/meson.build
index e02c60dd54..d5893a142d 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -20,6 +20,7 @@ softmmu_ss.add(when: 'CONFIG_SHAKTI_UART', if_true: files('shakti_uart.c'))
softmmu_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c'))
softmmu_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen_console.c'))
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c'))
+softmmu_ss.add(when: 'CONFIG_SERIAL_MCB', if_true: files('serial-mcb.c'))
softmmu_ss.add(when: 'CONFIG_AVR_USART', if_true: files('avr_usart.c'))
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_uart.c'))
diff --git a/hw/char/serial-mcb.c b/hw/char/serial-mcb.c
new file mode 100644
index 0000000000..09f8fec11e
--- /dev/null
+++ b/hw/char/serial-mcb.c
@@ -0,0 +1,115 @@
+/*
+ * QEMU MEN 16z125 UART over MCB emulation
+ *
+ * Copyright (C) 2023 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/char/serial.h"
+#include "hw/mcb/mcb.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "migration/vmstate.h"
+
+struct MCBSerialState {
+ MCBDevice dev;
+ SerialState state;
+};
+
+#define TYPE_MCB_SERIAL "mcb-serial"
+OBJECT_DECLARE_SIMPLE_TYPE(MCBSerialState, MCB_SERIAL)
+
+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;
+
+ mdev->gdd = mcb_new_chameleon_descriptor(bus, 125, mdev->rev,
+ mdev->var, 0x10);
+ if (!mdev->gdd) {
+ return;
+ }
+
+ s->baudbase = 115200;
+ if (!qdev_realize(DEVICE(s), NULL, errp)) {
+ 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)
+{
+ MCBDevice *mdev = MCB_DEVICE(dev);
+ MCBSerialState *mss = DO_UPCAST(MCBSerialState, dev, mdev);
+ SerialState *s = &mss->state;
+
+ qdev_unrealize(DEVICE(s));
+ qemu_free_irq(s->irq);
+ 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_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;
+ device_class_set_props(dc, serial_mcb_properties);
+}
+
+static void serial_mcb_init(Object *o)
+{
+ MCBSerialState *mss = MCB_SERIAL(o);
+
+ object_initialize_child(o, "serial", &mss->state, TYPE_SERIAL);
+
+ qdev_alias_all_properties(DEVICE(&mss->state), o);
+}
+
+static const TypeInfo serial_mcb_info = {
+ .name = "mcb-serial",
+ .parent = TYPE_MCB_DEVICE,
+ .instance_size = sizeof(MCBSerialState),
+ .instance_init = serial_mcb_init,
+ .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.39.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 4/4] wdt_z069: Add support for MEN 16z069 Watchdog
2023-04-18 17:35 [PATCH v4 0/4] Add emulation of MEN Chameleon Hardware Johannes Thumshirn
` (2 preceding siblings ...)
2023-04-18 17:35 ` [PATCH v4 3/4] serial-mcb: Add serial via MEN chameleon bus Johannes Thumshirn
@ 2023-04-18 17:35 ` Johannes Thumshirn
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Thumshirn @ 2023-04-18 17:35 UTC (permalink / raw)
To: qemu-devel
Cc: Alistair Francis, Javier Rodriguez, Jorge Sanjuan García,
Peter Maydell, Dmitry Fomichev, Johannes Thumshirn
Add 16z069 Watchdog over MEN Chameleon BUS emulation.
Signed-off-by: Johannes Thumshirn <jth@kernel.org>
---
hw/watchdog/Kconfig | 5 +
hw/watchdog/meson.build | 1 +
hw/watchdog/trace-events | 6 ++
hw/watchdog/wdt_z069.c | 207 +++++++++++++++++++++++++++++++++++++++
4 files changed, 219 insertions(+)
create mode 100644 hw/watchdog/wdt_z069.c
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
index 66e1d029e3..a3f1196f66 100644
--- a/hw/watchdog/Kconfig
+++ b/hw/watchdog/Kconfig
@@ -20,3 +20,8 @@ config WDT_IMX2
config WDT_SBSA
bool
+
+config WDT_Z069
+ bool
+ default y if MCB
+ depends on MCB
diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build
index 8974b5cf4c..7bc353774e 100644
--- a/hw/watchdog/meson.build
+++ b/hw/watchdog/meson.build
@@ -6,4 +6,5 @@ softmmu_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: files('wdt_diag288.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c'))
softmmu_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c'))
softmmu_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c'))
+softmmu_ss.add(when: 'CONFIG_WDT_Z069', if_true: files('wdt_z069.c'))
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_watchdog.c'))
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
index 54371ae075..854fa3f0c8 100644
--- a/hw/watchdog/trace-events
+++ b/hw/watchdog/trace-events
@@ -17,6 +17,12 @@ spapr_watchdog_query(uint64_t caps) "caps=0x%" PRIx64
spapr_watchdog_query_lpm(uint64_t caps) "caps=0x%" PRIx64
spapr_watchdog_expired(uint64_t num, unsigned action) "num=%" PRIu64 " action=%u"
+# wdt_z069.c
+men_z069_wdt_enable(unsigned int timeout) "next timeout will fire in +%dms"
+men_z069_wdt_write_wtr(uint16_t tout, uint16_t t, unsigned int timeout) "new timeout: %u (0x%x) %u"
+men_z069_wdt_write_wvr(uint16_t wvr, unsigned int timeout) "watchdog triggered (wvr=0x%x), next timeout will fire in +%dms"
+men_z069_wdt_read(unsigned long addr, int size, uint64_t ret) "addr=0x%lx, size=%d, ret=0x%" PRIx64
+
# watchdog.c
watchdog_perform_action(unsigned int action) "action=%u"
watchdog_set_action(unsigned int action) "action=%u"
diff --git a/hw/watchdog/wdt_z069.c b/hw/watchdog/wdt_z069.c
new file mode 100644
index 0000000000..eb58a44697
--- /dev/null
+++ b/hw/watchdog/wdt_z069.c
@@ -0,0 +1,207 @@
+/*
+ * QEMU MEN 16z069 Watchdog over MCB emulation
+ *
+ * Copyright (C) 2023 Johannes Thumshirn <jth@kernel.org>
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "sysemu/watchdog.h"
+#include "hw/mcb/mcb.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "trace.h"
+
+#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)
+{
+ trace_men_z069_wdt_enable(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;
+ }
+
+ trace_men_z069_wdt_read(addr, size, ret);
+ 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;
+
+ 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;
+ trace_men_z069_wdt_write_wtr(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;
+ trace_men_z069_wdt_write_wvr(s->wvr, 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 = 2,
+ .max_access_size = 2
+ },
+ .impl = {
+ .min_access_size = 2,
+ .max_access_size = 2
+ },
+};
+
+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)
+{
+ 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;
+ device_class_set_props(dc, 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.39.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-04-18 17:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-18 17:35 [PATCH v4 0/4] Add emulation of MEN Chameleon Hardware Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 1/4] Add MEN Chameleon Bus emulation Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 2/4] Add MEN Chameleon Bus via PCI carrier Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 3/4] serial-mcb: Add serial via MEN chameleon bus Johannes Thumshirn
2023-04-18 17:35 ` [PATCH v4 4/4] wdt_z069: Add support for MEN 16z069 Watchdog Johannes Thumshirn
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).