* [PATCH v5 00/10] Introduce model for IBM's FSI
@ 2023-10-11 15:13 Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
` (10 more replies)
0 siblings, 11 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
Hello,
Please review the patch-set version 5.
I have incorporated review comments from Cedric.
Ninad Palsule (10):
hw/fsi: Introduce IBM's Local bus
hw/fsi: Introduce IBM's scratchpad
hw/fsi: Introduce IBM's cfam,fsi-slave
hw/fsi: Introduce IBM's FSI
hw/fsi: IBM's On-chip Peripheral Bus
hw/fsi: Aspeed APB2OPB interface
hw/arm: Hook up FSI module in AST2600
hw/fsi: Added qtest
hw/fsi: Added FSI documentation
hw/fsi: Update MAINTAINER list
MAINTAINERS | 8 +
docs/specs/fsi.rst | 141 ++++++++++++
meson.build | 1 +
hw/fsi/trace.h | 1 +
include/hw/arm/aspeed_soc.h | 4 +
include/hw/fsi/aspeed-apb2opb.h | 33 +++
include/hw/fsi/cfam.h | 58 +++++
include/hw/fsi/engine-scratchpad.h | 33 +++
include/hw/fsi/fsi-master.h | 30 +++
include/hw/fsi/fsi-slave.h | 29 +++
include/hw/fsi/fsi.h | 37 +++
include/hw/fsi/lbus.h | 51 +++++
include/hw/fsi/opb.h | 43 ++++
include/qemu/bitops.h | 6 +
hw/arm/aspeed_ast2600.c | 19 ++
hw/fsi/aspeed-apb2opb.c | 350 +++++++++++++++++++++++++++++
hw/fsi/cfam.c | 220 ++++++++++++++++++
hw/fsi/engine-scratchpad.c | 99 ++++++++
hw/fsi/fsi-master.c | 198 ++++++++++++++++
hw/fsi/fsi-slave.c | 96 ++++++++
hw/fsi/fsi.c | 54 +++++
hw/fsi/lbus.c | 87 +++++++
hw/fsi/opb.c | 185 +++++++++++++++
tests/qtest/fsi-test.c | 210 +++++++++++++++++
hw/Kconfig | 1 +
hw/arm/Kconfig | 1 +
hw/fsi/Kconfig | 23 ++
hw/fsi/meson.build | 6 +
hw/fsi/trace-events | 15 ++
hw/meson.build | 1 +
tests/qtest/meson.build | 2 +
31 files changed, 2042 insertions(+)
create mode 100644 docs/specs/fsi.rst
create mode 100644 hw/fsi/trace.h
create mode 100644 include/hw/fsi/aspeed-apb2opb.h
create mode 100644 include/hw/fsi/cfam.h
create mode 100644 include/hw/fsi/engine-scratchpad.h
create mode 100644 include/hw/fsi/fsi-master.h
create mode 100644 include/hw/fsi/fsi-slave.h
create mode 100644 include/hw/fsi/fsi.h
create mode 100644 include/hw/fsi/lbus.h
create mode 100644 include/hw/fsi/opb.h
create mode 100644 hw/fsi/aspeed-apb2opb.c
create mode 100644 hw/fsi/cfam.c
create mode 100644 hw/fsi/engine-scratchpad.c
create mode 100644 hw/fsi/fsi-master.c
create mode 100644 hw/fsi/fsi-slave.c
create mode 100644 hw/fsi/fsi.c
create mode 100644 hw/fsi/lbus.c
create mode 100644 hw/fsi/opb.c
create mode 100644 tests/qtest/fsi-test.c
create mode 100644 hw/fsi/Kconfig
create mode 100644 hw/fsi/meson.build
create mode 100644 hw/fsi/trace-events
--
2.39.2
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 8:03 ` Cédric Le Goater
` (2 more replies)
2023-10-11 15:13 ` [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad Ninad Palsule
` (9 subsequent siblings)
10 siblings, 3 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This is a part of patchset where IBM's Flexible Service Interface is
introduced.
The LBUS is modelled to maintain the qdev bus hierarchy and to take
advantage of the object model to automatically generate the CFAM
configuration block. The configuration block presents engines in the
order they are attached to the CFAM's LBUS. Engine implementations
should subclass the LBusDevice and set the 'config' member of
LBusDeviceClass to match the engine's type.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
v2:
- Incorporated Joel's review comments.
v5:
- Incorporated review comments by Cedric.
---
include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
include/qemu/bitops.h | 6 +++
hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
hw/Kconfig | 1 +
hw/fsi/Kconfig | 2 +
hw/fsi/meson.build | 1 +
hw/meson.build | 1 +
7 files changed, 149 insertions(+)
create mode 100644 include/hw/fsi/lbus.h
create mode 100644 hw/fsi/lbus.c
create mode 100644 hw/fsi/Kconfig
create mode 100644 hw/fsi/meson.build
diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
new file mode 100644
index 0000000000..408fe25831
--- /dev/null
+++ b/include/hw/fsi/lbus.h
@@ -0,0 +1,51 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Local bus and connected device structures.
+ */
+#ifndef FSI_LBUS_H
+#define FSI_LBUS_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+
+#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
+OBJECT_DECLARE_TYPE(FSILBusDevice, FSILBusDeviceClass, FSI_LBUS_DEVICE)
+
+#define FSI_LBUS_MEM_REGION_SIZE (2 * 1024 * 1024)
+#define FSI_LBUSDEV_IOMEM_SIZE 0x400
+
+typedef struct FSILBusDevice {
+ DeviceState parent;
+
+ MemoryRegion iomem;
+ uint32_t address;
+} FSILBusDevice;
+
+typedef struct FSILBusDeviceClass {
+ DeviceClass parent;
+
+ uint32_t config;
+} FSILBusDeviceClass;
+
+typedef struct FSILBusNode {
+ FSILBusDevice *ldev;
+
+ QLIST_ENTRY(FSILBusNode) next;
+} FSILBusNode;
+
+#define TYPE_FSI_LBUS "fsi.lbus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
+
+typedef struct FSILBus {
+ BusState bus;
+
+ MemoryRegion mr;
+
+ QLIST_HEAD(, FSILBusNode) devices;
+} FSILBus;
+
+DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr);
+int lbus_add_device(FSILBus *bus, FSILBusDevice *dev);
+#endif /* FSI_LBUS_H */
diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index cb3526d1f4..e12496f619 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -618,4 +618,10 @@ static inline uint64_t half_unshuffle64(uint64_t x)
return x;
}
+/* Bitwise operations at the word level. */
+#define BE_BIT(x) BIT(31 - (x))
+#define GENMASK(t, b) \
+ (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
+#define BE_GENMASK(t, b) GENMASK(BE_BIT(t), BE_BIT(b))
+
#endif
diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
new file mode 100644
index 0000000000..d7117d1299
--- /dev/null
+++ b/hw/fsi/lbus.c
@@ -0,0 +1,87 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Local bus where FSI slaves are connected
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/fsi/lbus.h"
+
+#include "hw/qdev-properties.h"
+
+static void lbus_realize(BusState *bus, Error **errp)
+{
+ FSILBusNode *node;
+ FSILBus *lbus = FSI_LBUS(bus);
+
+ memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_FSI_LBUS,
+ FSI_LBUS_MEM_REGION_SIZE - FSI_LBUSDEV_IOMEM_SIZE);
+
+ QLIST_FOREACH(node, &lbus->devices, next) {
+ memory_region_add_subregion(&lbus->mr, node->ldev->address,
+ &node->ldev->iomem);
+ }
+}
+
+static void lbus_class_init(ObjectClass *klass, void *data)
+{
+ BusClass *k = BUS_CLASS(klass);
+ k->realize = lbus_realize;
+}
+
+static const TypeInfo lbus_info = {
+ .name = TYPE_FSI_LBUS,
+ .parent = TYPE_BUS,
+ .instance_size = sizeof(FSILBus),
+ .class_init = lbus_class_init,
+};
+
+static Property lbus_device_props[] = {
+ DEFINE_PROP_UINT32("address", FSILBusDevice, address, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
+{
+ DeviceState *dev;
+ FSILBusNode *node;
+ BusState *state = BUS(bus);
+
+ dev = qdev_new(type);
+ qdev_prop_set_uint8(dev, "address", addr);
+ qdev_realize_and_unref(dev, state, &error_fatal);
+
+ /* Move to post_load */
+ node = g_malloc(sizeof(struct FSILBusNode));
+ node->ldev = FSI_LBUS_DEVICE(dev);
+ QLIST_INSERT_HEAD(&bus->devices, node, next);
+
+ return dev;
+}
+
+static void lbus_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->bus_type = TYPE_FSI_LBUS;
+ device_class_set_props(dc, lbus_device_props);
+}
+
+static const TypeInfo lbus_device_type_info = {
+ .name = TYPE_FSI_LBUS_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(FSILBusDevice),
+ .abstract = true,
+ .class_init = lbus_device_class_init,
+ .class_size = sizeof(FSILBusDeviceClass),
+};
+
+static void lbus_register_types(void)
+{
+ type_register_static(&lbus_info);
+ type_register_static(&lbus_device_type_info);
+}
+
+type_init(lbus_register_types);
diff --git a/hw/Kconfig b/hw/Kconfig
index ba62ff6417..2ccb73add5 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -9,6 +9,7 @@ source core/Kconfig
source cxl/Kconfig
source display/Kconfig
source dma/Kconfig
+source fsi/Kconfig
source gpio/Kconfig
source hyperv/Kconfig
source i2c/Kconfig
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
new file mode 100644
index 0000000000..e650c660f0
--- /dev/null
+++ b/hw/fsi/Kconfig
@@ -0,0 +1,2 @@
+config FSI_LBUS
+ bool
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
new file mode 100644
index 0000000000..4074d3a7d2
--- /dev/null
+++ b/hw/fsi/meson.build
@@ -0,0 +1 @@
+system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
diff --git a/hw/meson.build b/hw/meson.build
index c7ac7d3d75..6c71ee9cfa 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -43,6 +43,7 @@ subdir('virtio')
subdir('watchdog')
subdir('xen')
subdir('xenpv')
+subdir('fsi')
subdir('alpha')
subdir('arm')
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 8:20 ` Daniel P. Berrangé
2023-10-11 15:13 ` [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
` (8 subsequent siblings)
10 siblings, 1 reply; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This is a part of patchset where scratchpad is introduced.
The scratchpad provides a set of non-functional registers. The firmware
is free to use them, hardware does not support any special management
support. The scratchpad registers can be read or written from LBUS
slave.
In this model, The LBUS device is parent for the scratchpad.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
v2:
- Incorporated Joel's review comments.
v5:
- Incorporated review comments by Cedric.
---
include/hw/fsi/engine-scratchpad.h | 33 ++++++++++
hw/fsi/engine-scratchpad.c | 99 ++++++++++++++++++++++++++++++
hw/fsi/Kconfig | 4 ++
hw/fsi/meson.build | 1 +
hw/fsi/trace-events | 2 +
5 files changed, 139 insertions(+)
create mode 100644 include/hw/fsi/engine-scratchpad.h
create mode 100644 hw/fsi/engine-scratchpad.c
create mode 100644 hw/fsi/trace-events
diff --git a/include/hw/fsi/engine-scratchpad.h b/include/hw/fsi/engine-scratchpad.h
new file mode 100644
index 0000000000..17e9570c5c
--- /dev/null
+++ b/include/hw/fsi/engine-scratchpad.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM scratchpad engne
+ */
+#ifndef FSI_ENGINE_SCRATCHPAD_H
+#define FSI_ENGINE_SCRATCHPAD_H
+
+#include "qemu/bitops.h"
+
+#include "hw/fsi/lbus.h"
+
+#define ENGINE_CONFIG_NEXT BE_BIT(0)
+#define ENGINE_CONFIG_VPD BE_BIT(1)
+#define ENGINE_CONFIG_SLOTS BE_GENMASK(8, 15)
+#define ENGINE_CONFIG_VERSION BE_GENMASK(16, 19)
+#define ENGINE_CONFIG_TYPE BE_GENMASK(20, 27)
+#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4)
+#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4)
+#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4)
+#define ENGINE_CONFIG_CRC BE_GENMASK(28, 31)
+
+#define TYPE_SCRATCHPAD "scratchpad"
+#define SCRATCHPAD(obj) OBJECT_CHECK(ScratchPad, (obj), TYPE_SCRATCHPAD)
+
+typedef struct ScratchPad {
+ FSILBusDevice parent;
+
+ uint32_t reg;
+} ScratchPad;
+
+#endif /* FSI_ENGINE_SCRATCHPAD_H */
diff --git a/hw/fsi/engine-scratchpad.c b/hw/fsi/engine-scratchpad.c
new file mode 100644
index 0000000000..60f678eec4
--- /dev/null
+++ b/hw/fsi/engine-scratchpad.c
@@ -0,0 +1,99 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM scratchpad engine
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#include "hw/fsi/engine-scratchpad.h"
+
+static uint64_t scratchpad_read(void *opaque, hwaddr addr, unsigned size)
+{
+ ScratchPad *s = SCRATCHPAD(opaque);
+
+ trace_scratchpad_read(addr, size);
+
+ if (addr) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return 0;
+ }
+
+ return s->reg;
+}
+
+static void scratchpad_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ ScratchPad *s = SCRATCHPAD(opaque);
+
+ trace_scratchpad_write(addr, size, data);
+
+ if (addr) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return;
+ }
+
+ s->reg = data;
+}
+
+static const struct MemoryRegionOps scratchpad_ops = {
+ .read = scratchpad_read,
+ .write = scratchpad_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void scratchpad_realize(DeviceState *dev, Error **errp)
+{
+ FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev);
+
+ memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops,
+ ldev, TYPE_SCRATCHPAD, 0x400);
+}
+
+static void scratchpad_reset(DeviceState *dev)
+{
+ ScratchPad *s = SCRATCHPAD(dev);
+
+ s->reg = 0;
+}
+
+static void scratchpad_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ FSILBusDeviceClass *ldc = FSI_LBUS_DEVICE_CLASS(klass);
+
+ dc->realize = scratchpad_realize;
+ dc->reset = scratchpad_reset;
+
+ ldc->config =
+ ENGINE_CONFIG_NEXT /* valid */
+ | 0x00010000 /* slots */
+ | 0x00001000 /* version */
+ | ENGINE_CONFIG_TYPE_SCRATCHPAD /* type */
+ | 0x00000007; /* crc */
+}
+
+static const TypeInfo scratchpad_info = {
+ .name = TYPE_SCRATCHPAD,
+ .parent = TYPE_FSI_LBUS_DEVICE,
+ .instance_size = sizeof(ScratchPad),
+ .class_init = scratchpad_class_init,
+ .class_size = sizeof(FSILBusDeviceClass),
+};
+
+static void scratchpad_register_types(void)
+{
+ type_register_static(&scratchpad_info);
+}
+
+type_init(scratchpad_register_types);
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
index e650c660f0..f7c7fd1b28 100644
--- a/hw/fsi/Kconfig
+++ b/hw/fsi/Kconfig
@@ -1,2 +1,6 @@
+config FSI_SCRATCHPAD
+ bool
+ select FSI_LBUS
+
config FSI_LBUS
bool
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index 4074d3a7d2..d45a98c223 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -1 +1,2 @@
system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
+system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
new file mode 100644
index 0000000000..97fd070354
--- /dev/null
+++ b/hw/fsi/trace-events
@@ -0,0 +1,2 @@
+scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 8:00 ` Cédric Le Goater
` (2 more replies)
2023-10-11 15:13 ` [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI Ninad Palsule
` (7 subsequent siblings)
10 siblings, 3 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This is a part of patchset where IBM's Flexible Service Interface is
introduced.
The Common FRU Access Macro (CFAM), an address space containing
various "engines" that drive accesses on busses internal and external
to the POWER chip. Examples include the SBEFIFO and I2C masters. The
engines hang off of an internal Local Bus (LBUS) which is described
by the CFAM configuration block.
The FSI slave: The slave is the terminal point of the FSI bus for
FSI symbols addressed to it. Slaves can be cascaded off of one
another. The slave's configuration registers appear in address space
of the CFAM to which it is attached.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
v2:
- Incorporated Joel's review comments.
v3:
- Incorporated Thomas Huth's review comments.
v5:
- Incorporated review comments by Cedric.
---
include/hw/fsi/cfam.h | 58 ++++++++++
include/hw/fsi/fsi-slave.h | 29 +++++
hw/fsi/cfam.c | 220 +++++++++++++++++++++++++++++++++++++
hw/fsi/fsi-slave.c | 96 ++++++++++++++++
hw/fsi/Kconfig | 9 ++
hw/fsi/meson.build | 2 +
hw/fsi/trace-events | 7 ++
7 files changed, 421 insertions(+)
create mode 100644 include/hw/fsi/cfam.h
create mode 100644 include/hw/fsi/fsi-slave.h
create mode 100644 hw/fsi/cfam.c
create mode 100644 hw/fsi/fsi-slave.c
diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
new file mode 100644
index 0000000000..a828fd931e
--- /dev/null
+++ b/include/hw/fsi/cfam.h
@@ -0,0 +1,58 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+#ifndef FSI_CFAM_H
+#define FSI_CFAM_H
+
+#include "exec/memory.h"
+
+#include "hw/fsi/fsi-slave.h"
+#include "hw/fsi/lbus.h"
+
+#define TYPE_CFAM "cfam"
+#define CFAM(obj) OBJECT_CHECK(CFAMState, (obj), TYPE_CFAM)
+
+#define CFAM_NR_REGS ((0x2e0 >> 2) + 1)
+
+#define TYPE_CFAM_CONFIG "cfam.config"
+OBJECT_DECLARE_SIMPLE_TYPE(CFAMConfig, CFAM_CONFIG)
+
+/* P9-ism */
+#define CFAM_CONFIG_NR_REGS 0x28
+
+typedef struct CFAMState CFAMState;
+
+/* TODO: Generalise this accommodate different CFAM configurations */
+typedef struct CFAMConfig {
+ DeviceState parent;
+
+ MemoryRegion iomem;
+} CFAMConfig;
+
+#define TYPE_CFAM_PEEK "cfam.peek"
+OBJECT_DECLARE_SIMPLE_TYPE(CFAMPeek, CFAM_PEEK)
+#define CFAM_PEEK_NR_REGS ((0x130 >> 2) + 1)
+
+typedef struct CFAMPeek {
+ DeviceState parent;
+
+ MemoryRegion iomem;
+} CFAMPeek;
+
+struct CFAMState {
+ /* < private > */
+ FSISlaveState parent;
+
+ MemoryRegion mr;
+ AddressSpace as;
+
+ CFAMConfig config;
+ CFAMPeek peek;
+
+ FSILBus lbus;
+};
+
+#endif /* FSI_CFAM_H */
diff --git a/include/hw/fsi/fsi-slave.h b/include/hw/fsi/fsi-slave.h
new file mode 100644
index 0000000000..f5f23f4457
--- /dev/null
+++ b/include/hw/fsi/fsi-slave.h
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Flexible Service Interface slave
+ */
+#ifndef FSI_FSI_SLAVE_H
+#define FSI_FSI_SLAVE_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+
+#include "hw/fsi/lbus.h"
+
+#include <stdint.h>
+
+#define TYPE_FSI_SLAVE "fsi.slave"
+OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
+
+#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
+
+typedef struct FSISlaveState {
+ DeviceState parent;
+
+ MemoryRegion iomem;
+ uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
+} FSISlaveState;
+
+#endif /* FSI_FSI_H */
diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
new file mode 100644
index 0000000000..9044cc741b
--- /dev/null
+++ b/hw/fsi/cfam.c
@@ -0,0 +1,220 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Common FRU Access Macro
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/bits.h"
+#include "hw/fsi/cfam.h"
+#include "hw/fsi/engine-scratchpad.h"
+
+#include "hw/qdev-properties.h"
+
+#define TO_REG(x) ((x) >> 2)
+
+#define CFAM_ENGINE_CONFIG TO_REG(0x04)
+
+#define CFAM_CONFIG_CHIP_ID TO_REG(0x00)
+#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
+#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000
+
+static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned size)
+{
+ CFAMConfig *config;
+ CFAMState *cfam;
+ FSILBusNode *node;
+ int i;
+
+ config = CFAM_CONFIG(opaque);
+ cfam = container_of(config, CFAMState, config);
+
+ trace_cfam_config_read(addr, size);
+
+ switch (addr) {
+ case 0x00:
+ return CFAM_CONFIG_CHIP_ID_P9;
+ case 0x04:
+ return ENGINE_CONFIG_NEXT
+ | 0x00010000 /* slots */
+ | 0x00001000 /* version */
+ | ENGINE_CONFIG_TYPE_PEEK /* type */
+ | 0x0000000c; /* crc */
+ case 0x08:
+ return ENGINE_CONFIG_NEXT
+ | 0x00010000 /* slots */
+ | 0x00005000 /* version */
+ | ENGINE_CONFIG_TYPE_FSI /* type */
+ | 0x0000000a; /* crc */
+ break;
+ default:
+ /* FIXME: Improve this */
+ i = 0xc;
+ QLIST_FOREACH(node, &cfam->lbus.devices, next) {
+ if (i == addr) {
+ return FSI_LBUS_DEVICE_GET_CLASS(node->ldev)->config;
+ }
+ i += size;
+ }
+
+ if (i == addr) {
+ return 0;
+ }
+
+ /*
+ * As per FSI specification, This is a magic value at address 0 of
+ * given FSI port. This causes FSI master to send BREAK command for
+ * initialization and recovery.
+ */
+ return CFAM_CONFIG_CHIP_ID_BREAK;
+ }
+}
+
+static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ CFAMConfig *s = CFAM_CONFIG(opaque);
+
+ trace_cfam_config_write(addr, size, data);
+
+ switch (TO_REG(addr)) {
+ case CFAM_CONFIG_CHIP_ID:
+ case CFAM_CONFIG_CHIP_ID + 4:
+ if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
+ bus_cold_reset(qdev_get_parent_bus(DEVICE(s)));
+ }
+ break;
+ default:
+ trace_cfam_config_write_noaddr(addr, size, data);
+ }
+}
+
+static const struct MemoryRegionOps cfam_config_ops = {
+ .read = cfam_config_read,
+ .write = cfam_config_write,
+ .valid.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .impl.min_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void cfam_config_realize(DeviceState *dev, Error **errp)
+{
+ CFAMConfig *s = CFAM_CONFIG(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &cfam_config_ops, s,
+ TYPE_CFAM_CONFIG, 0x400);
+}
+
+static void cfam_config_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->bus_type = TYPE_FSI_LBUS;
+ dc->realize = cfam_config_realize;
+}
+
+static const TypeInfo cfam_config_info = {
+ .name = TYPE_CFAM_CONFIG,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(CFAMConfig),
+ .class_init = cfam_config_class_init,
+};
+
+static uint64_t cfam_unimplemented_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ trace_cfam_unimplemented_read(addr, size);
+
+ return 0;
+}
+
+static void cfam_unimplemented_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ trace_cfam_unimplemented_write(addr, size, data);
+}
+
+static const struct MemoryRegionOps cfam_unimplemented_ops = {
+ .read = cfam_unimplemented_read,
+ .write = cfam_unimplemented_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void cfam_realize(DeviceState *dev, Error **errp)
+{
+ CFAMState *cfam = CFAM(dev);
+ FSISlaveState *slave = FSI_SLAVE(dev);
+ Error *err = NULL;
+
+ /* Each slave has a 2MiB address space */
+ memory_region_init_io(&cfam->mr, OBJECT(cfam), &cfam_unimplemented_ops,
+ cfam, TYPE_CFAM, 2 * 1024 * 1024);
+ address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
+
+ qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
+ DEVICE(cfam), NULL);
+
+ lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
+
+ object_property_set_bool(OBJECT(&cfam->config), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus), &error_abort);
+
+ object_property_set_bool(OBJECT(&cfam->lbus), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
+ /* memory_region_add_subregion(&cfam->mr, 0x800, &cfam->lbus.peek.iomem); */
+ memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
+ memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
+}
+
+static void cfam_init(Object *o)
+{
+ CFAMState *s = CFAM(o);
+
+ object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config, TYPE_CFAM_CONFIG);
+}
+
+static void cfam_finalize(Object *o)
+{
+ CFAMState *s = CFAM(o);
+
+ address_space_destroy(&s->as);
+}
+
+static void cfam_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->bus_type = TYPE_FSI_BUS;
+ dc->realize = cfam_realize;
+}
+
+static const TypeInfo cfam_info = {
+ .name = TYPE_CFAM,
+ .parent = TYPE_FSI_SLAVE,
+ .instance_init = cfam_init,
+ .instance_finalize = cfam_finalize,
+ .instance_size = sizeof(CFAMState),
+ .class_init = cfam_class_init,
+};
+
+static void cfam_register_types(void)
+{
+ type_register_static(&cfam_config_info);
+ type_register_static(&cfam_info);
+}
+
+type_init(cfam_register_types);
diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
new file mode 100644
index 0000000000..127fdd8a4f
--- /dev/null
+++ b/hw/fsi/fsi-slave.c
@@ -0,0 +1,96 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Flexible Service Interface slave
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu/bitops.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#include "hw/fsi/fsi-slave.h"
+
+#define TO_REG(x) ((x) >> 2)
+
+#define FSI_SMODE TO_REG(0x00)
+#define FSI_SMODE_WSTART BE_BIT(0)
+#define FSI_SMODE_AUX_EN BE_BIT(1)
+#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
+#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
+#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
+#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
+#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
+#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
+
+#define FSI_SDMA TO_REG(0x04)
+#define FSI_SISC TO_REG(0x08)
+#define FSI_SCISC TO_REG(0x08)
+#define FSI_SISM TO_REG(0x0c)
+#define FSI_SISS TO_REG(0x10)
+#define FSI_SSISM TO_REG(0x10)
+#define FSI_SCISM TO_REG(0x14)
+
+static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
+{
+ FSISlaveState *s = FSI_SLAVE(opaque);
+
+ trace_fsi_slave_read(addr, size);
+
+ if (addr + size > sizeof(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return 0;
+ }
+
+ return s->regs[TO_REG(addr)];
+}
+
+static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ FSISlaveState *s = FSI_SLAVE(opaque);
+
+ trace_fsi_slave_write(addr, size, data);
+
+ if (addr + size > sizeof(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return;
+ }
+
+ s->regs[TO_REG(addr)] = data;
+}
+
+static const struct MemoryRegionOps fsi_slave_ops = {
+ .read = fsi_slave_read,
+ .write = fsi_slave_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsi_slave_init(Object *o)
+{
+ FSISlaveState *s = FSI_SLAVE(o);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
+ s, TYPE_FSI_SLAVE, 0x400);
+}
+
+static const TypeInfo fsi_slave_info = {
+ .name = TYPE_FSI_SLAVE,
+ .parent = TYPE_DEVICE,
+ .instance_init = fsi_slave_init,
+ .instance_size = sizeof(FSISlaveState),
+};
+
+static void fsi_slave_register_types(void)
+{
+ type_register_static(&fsi_slave_info);
+}
+
+type_init(fsi_slave_register_types);
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
index f7c7fd1b28..8d712e77ed 100644
--- a/hw/fsi/Kconfig
+++ b/hw/fsi/Kconfig
@@ -1,3 +1,12 @@
+config FSI_CFAM
+ bool
+ select FSI
+ select FSI_SCRATCHPAD
+ select FSI_LBUS
+
+config FSI
+ bool
+
config FSI_SCRATCHPAD
bool
select FSI_LBUS
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index d45a98c223..a9e7cd4099 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -1,2 +1,4 @@
system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
+system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
+system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index 97fd070354..752a5683a0 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -1,2 +1,9 @@
scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+cfam_config_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (2 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 7:44 ` Cédric Le Goater
2023-10-19 8:28 ` Daniel P. Berrangé
2023-10-11 15:13 ` [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus Ninad Palsule
` (6 subsequent siblings)
10 siblings, 2 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This is a part of patchset where IBM's Flexible Service Interface is
introduced.
This commit models the FSI bus. CFAM is hanging out of FSI bus. The bus
is model such a way that it is embedded inside the FSI master which is a
bus controller.
The FSI master: A controller in the platform service processor (e.g.
BMC) driving CFAM engine accesses into the POWER chip. At the
hardware level FSI is a bit-based protocol supporting synchronous and
DMA-driven accesses of engines in a CFAM.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
Reviewed-by: Joel Stanley <joel@jms.id.au>
---
v2:
- Incorporated review comments by Joel
v5:
- Incorporated review comments by Cedric.
---
include/hw/fsi/fsi-master.h | 30 ++++++
include/hw/fsi/fsi.h | 37 +++++++
hw/fsi/cfam.c | 2 +-
hw/fsi/fsi-master.c | 199 ++++++++++++++++++++++++++++++++++++
hw/fsi/fsi.c | 54 ++++++++++
hw/fsi/meson.build | 2 +-
hw/fsi/trace-events | 2 +
7 files changed, 324 insertions(+), 2 deletions(-)
create mode 100644 include/hw/fsi/fsi-master.h
create mode 100644 include/hw/fsi/fsi.h
create mode 100644 hw/fsi/fsi-master.c
create mode 100644 hw/fsi/fsi.c
diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h
new file mode 100644
index 0000000000..847078919c
--- /dev/null
+++ b/include/hw/fsi/fsi-master.h
@@ -0,0 +1,30 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2019 IBM Corp.
+ *
+ * IBM Flexible Service Interface Master
+ */
+#ifndef FSI_FSI_MASTER_H
+#define FSI_FSI_MASTER_H
+
+#include "exec/memory.h"
+#include "hw/qdev-core.h"
+#include "hw/fsi/fsi.h"
+
+#define TYPE_FSI_MASTER "fsi.master"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER)
+
+#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1)
+
+typedef struct FSIMasterState {
+ DeviceState parent;
+ MemoryRegion iomem;
+ MemoryRegion opb2fsi;
+
+ FSIBus bus;
+
+ uint32_t regs[FSI_MASTER_NR_REGS];
+} FSIMasterState;
+
+
+#endif /* FSI_FSI_H */
diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
new file mode 100644
index 0000000000..cf97645abf
--- /dev/null
+++ b/include/hw/fsi/fsi.h
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#ifndef FSI_FSI_H
+#define FSI_FSI_H
+
+#include "hw/qdev-core.h"
+
+/*
+ * TODO: Maybe unwind this dependency with const links? Store a
+ * pointer in FSIBus?
+ */
+#include "hw/fsi/cfam.h"
+
+/* Bitwise operations at the word level. */
+#define BE_BIT(x) BIT(31 - (x))
+#define GENMASK(t, b) \
+ (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
+#define BE_GENMASK(t, b) GENMASK(BE_BIT(t), BE_BIT(b))
+
+#define TYPE_FSI_BUS "fsi.bus"
+OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
+
+/* TODO: Figure out what's best with a point-to-point bus */
+typedef struct FSISlaveState FSISlaveState;
+
+typedef struct FSIBus {
+ BusState bus;
+
+ /* XXX: It's point-to-point, just instantiate the slave directly for now */
+ CFAMState slave;
+} FSIBus;
+
+#endif
diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
index 9044cc741b..74a10f9f4b 100644
--- a/hw/fsi/cfam.c
+++ b/hw/fsi/cfam.c
@@ -10,8 +10,8 @@
#include "qapi/error.h"
#include "trace.h"
-#include "hw/fsi/bits.h"
#include "hw/fsi/cfam.h"
+#include "hw/fsi/fsi.h"
#include "hw/fsi/engine-scratchpad.h"
#include "hw/qdev-properties.h"
diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
new file mode 100644
index 0000000000..8f4ae641c7
--- /dev/null
+++ b/hw/fsi/fsi-master.c
@@ -0,0 +1,199 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Flexible Service Interface master
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#include "hw/fsi/fsi-master.h"
+
+#define TYPE_OP_BUS "opb"
+
+#define TO_REG(x) ((x) >> 2)
+
+#define FSI_MMODE TO_REG(0x000)
+#define FSI_MMODE_IPOLL_DMA_EN BE_BIT(0)
+#define FSI_MMODE_HW_ERROR_RECOVERY_EN BE_BIT(1)
+#define FSI_MMODE_RELATIVE_ADDRESS_EN BE_BIT(2)
+#define FSI_MMODE_PARITY_CHECK_EN BE_BIT(3)
+#define FSI_MMODE_CLOCK_DIVIDER_0 BE_GENMASK(4, 13)
+#define FSI_MMODE_CLOCK_DIVIDER_1 BE_GENMASK(14, 23)
+#define FSI_MMODE_DEBUG_EN BE_BIT(24)
+
+#define FSI_MDELAY TO_REG(0x004)
+#define FSI_MDELAY_ECHO_0 BE_GENMASK(0, 3)
+#define FSI_MDELAY_SEND_0 BE_GENMASK(4, 7)
+#define FSI_MDELAY_ECHO_1 BE_GENMASK(8, 11)
+#define FSI_MDELAY_SEND_1 BE_GENMASK(12, 15)
+
+#define FSI_MENP0 TO_REG(0x010)
+#define FSI_MENP32 TO_REG(0x014)
+#define FSI_MSENP0 TO_REG(0x018)
+#define FSI_MLEVP0 TO_REG(0x018)
+#define FSI_MSENP32 TO_REG(0x01c)
+#define FSI_MLEVP32 TO_REG(0x01c)
+#define FSI_MCENP0 TO_REG(0x020)
+#define FSI_MREFP0 TO_REG(0x020)
+#define FSI_MCENP32 TO_REG(0x024)
+#define FSI_MREFP32 TO_REG(0x024)
+
+#define FSI_MAEB TO_REG(0x070)
+#define FSI_MAEB_ANY_CPU_ERROR BE_BIT(0)
+#define FSI_MAEB_ANY_DMA_ERROR BE_GENMASK(1, 16)
+#define FSI_MAEB_ANY_PARITY_ERROR BE_BIT(17)
+
+#define FSI_MVER TO_REG(0x074)
+#define FSI_MVER_VERSION BE_GENMASK(0, 7)
+#define FSI_MVER_BRIDGES BE_GENMASK(8, 15)
+#define FSI_MVER_PORTS BE_GENMASK(16, 23)
+
+#define FSI_MRESP0 TO_REG(0x0d0)
+#define FSI_MRESP0_RESET_PORT_GENERAL BE_BIT(0)
+#define FSI_MRESP0_RESET_PORT_ERROR BE_BIT(1)
+#define FSI_MRESP0_RESET_ALL_BRIDGES_GENERAL BE_BIT(2)
+#define FSI_MRESP0_RESET_ALL_PORTS_GENERAL BE_BIT(3)
+#define FSI_MRESP0_RESET_MASTER BE_BIT(4)
+#define FSI_MRESP0_RESET_PARITY_ERROR_LATCH BE_BIT(5)
+
+#define FSI_MRESB0 TO_REG(0x1d0)
+#define FSI_MRESB0_RESET_GENERAL BE_BIT(0)
+#define FSI_MRESB0_RESET_ERROR BE_BIT(1)
+#define FSI_MRESB0_SET_DMA_SUSPEND BE_BIT(5)
+#define FSI_MRESB0_CLEAR_DMA_SUSPEND BE_BIT(6)
+#define FSI_MRESB0_SET_DELAY_MEASURE BE_BIT(7)
+
+#define FSI_MECTRL TO_REG(0x2e0)
+#define FSI_MECTRL_TEST_PULSE BE_GENMASK(0, 7)
+#define FSI_MECTRL_INHIBIT_PARITY_ERROR BE_GENMASK(8, 15)
+#define FSI_MECTRL_ENABLE_OPB_ERR_ACK BE_BIT(16)
+#define FSI_MECTRL_AUTO_TERMINATE BE_BIT(17)
+#define FSI_MECTRL_PORT_ERROR_FREEZE BE_BIT(18)
+
+static uint64_t fsi_master_read(void *opaque, hwaddr addr, unsigned size)
+{
+ FSIMasterState *s = FSI_MASTER(opaque);
+
+ trace_fsi_master_read(addr, size);
+
+ if (addr + size > sizeof(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return 0;
+ }
+
+ return s->regs[TO_REG(addr)];
+}
+
+static void fsi_master_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ FSIMasterState *s = FSI_MASTER(opaque);
+
+ trace_fsi_master_write(addr, size, data);
+
+ if (addr + size > sizeof(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return;
+ }
+
+ switch (TO_REG(addr)) {
+ case FSI_MENP0:
+ s->regs[FSI_MENP0] = data;
+ break;
+ case FSI_MENP32:
+ s->regs[FSI_MENP32] = data;
+ break;
+ case FSI_MSENP0:
+ s->regs[FSI_MENP0] |= data;
+ break;
+ case FSI_MSENP32:
+ s->regs[FSI_MENP32] |= data;
+ break;
+ case FSI_MCENP0:
+ s->regs[FSI_MENP0] &= ~data;
+ break;
+ case FSI_MCENP32:
+ s->regs[FSI_MENP32] &= ~data;
+ break;
+ case FSI_MRESP0:
+ /* Perform necessary resets leave register 0 to indicate no errors */
+ break;
+ case FSI_MRESB0:
+ if (data & FSI_MRESB0_RESET_GENERAL) {
+ device_cold_reset(DEVICE(opaque));
+ }
+ if (data & FSI_MRESB0_RESET_ERROR) {
+ /* FIXME: this seems dubious */
+ device_cold_reset(DEVICE(opaque));
+ }
+ break;
+ default:
+ s->regs[TO_REG(addr)] = data;
+ }
+}
+
+static const struct MemoryRegionOps fsi_master_ops = {
+ .read = fsi_master_read,
+ .write = fsi_master_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void fsi_master_realize(DeviceState *dev, Error **errp)
+{
+ FSIMasterState *s = FSI_MASTER(dev);
+ Error *err = NULL;
+
+ qbus_init(&s->bus, sizeof(s->bus), TYPE_FSI_BUS, DEVICE(s), NULL);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &fsi_master_ops, s,
+ TYPE_FSI_MASTER, 0x10000000);
+ memory_region_init(&s->opb2fsi, OBJECT(s), "fsi.opb2fsi", 0x10000000);
+
+ object_property_set_bool(OBJECT(&s->bus), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ memory_region_add_subregion(&s->opb2fsi, 0, &s->bus.slave.mr);
+}
+
+static void fsi_master_reset(DeviceState *dev)
+{
+ FSIMasterState *s = FSI_MASTER(dev);
+
+ /* ASPEED default */
+ s->regs[FSI_MVER] = 0xe0050101;
+}
+
+static void fsi_master_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->bus_type = TYPE_OP_BUS;
+ dc->desc = "FSI Master";
+ dc->realize = fsi_master_realize;
+ dc->reset = fsi_master_reset;
+}
+
+static const TypeInfo fsi_master_info = {
+ .name = TYPE_FSI_MASTER,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(FSIMasterState),
+ .class_init = fsi_master_class_init,
+};
+
+static void fsi_register_types(void)
+{
+ type_register_static(&fsi_master_info);
+}
+
+type_init(fsi_register_types);
diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
new file mode 100644
index 0000000000..fbfb28a6fc
--- /dev/null
+++ b/hw/fsi/fsi.c
@@ -0,0 +1,54 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM Flexible Service Interface
+ */
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+
+#include "hw/fsi/fsi.h"
+#include "hw/fsi/cfam.h"
+
+static void fsi_bus_realize(BusState *bus, Error **errp)
+{
+ FSIBus *s = FSI_BUS(bus);
+ Error *err = NULL;
+
+ /* Note: Move it elsewhere when we add more CFAMs. */
+ object_property_set_bool(OBJECT(&s->slave), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ }
+}
+
+static void fsi_bus_init(Object *o)
+{
+ FSIBus *s = FSI_BUS(o);
+
+ /* Note: Move it elsewhere when we add more CFAMs. */
+ object_initialize_child(o, TYPE_CFAM, &s->slave, TYPE_CFAM);
+ qdev_set_parent_bus(DEVICE(&s->slave), BUS(o), &error_abort);
+}
+
+static void fsi_bus_class_init(ObjectClass *klass, void *data)
+{
+ BusClass *bc = BUS_CLASS(klass);
+ bc->realize = fsi_bus_realize;
+}
+
+static const TypeInfo fsi_bus_info = {
+ .name = TYPE_FSI_BUS,
+ .parent = TYPE_BUS,
+ .instance_init = fsi_bus_init,
+ .instance_size = sizeof(FSIBus),
+ .class_init = fsi_bus_class_init,
+};
+
+static void fsi_bus_register_types(void)
+{
+ type_register_static(&fsi_bus_info);
+}
+
+type_init(fsi_bus_register_types);
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index a9e7cd4099..f617943b4a 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -1,4 +1,4 @@
system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
-system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
+system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi.c','fsi-master.c','fsi-slave.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index 752a5683a0..d7afef0460 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -7,3 +7,5 @@ cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRI
cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (3 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 7:26 ` Cédric Le Goater
2023-10-19 8:30 ` Daniel P. Berrangé
2023-10-11 15:13 ` [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface Ninad Palsule
` (5 subsequent siblings)
10 siblings, 2 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This is a part of patchset where IBM's Flexible Service Interface is
introduced.
The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
POWER processors. This now makes an appearance in the ASPEED SoC due
to tight integration of the FSI master IP with the OPB, mainly the
existence of an MMIO-mapping of the CFAM address straight onto a
sub-region of the OPB address space.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
Reviewed-by: Joel Stanley <joel@jms.id.au>
---
v2:
- Incorporated review comment by Joel.
v5:
- Incorporated review comments by Cedric.
---
include/hw/fsi/opb.h | 43 ++++++++++
hw/fsi/fsi-master.c | 3 +-
hw/fsi/opb.c | 185 +++++++++++++++++++++++++++++++++++++++++++
hw/fsi/Kconfig | 4 +
hw/fsi/meson.build | 1 +
hw/fsi/trace-events | 2 +
6 files changed, 236 insertions(+), 2 deletions(-)
create mode 100644 include/hw/fsi/opb.h
create mode 100644 hw/fsi/opb.c
diff --git a/include/hw/fsi/opb.h b/include/hw/fsi/opb.h
new file mode 100644
index 0000000000..f8ce00383e
--- /dev/null
+++ b/include/hw/fsi/opb.h
@@ -0,0 +1,43 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM On-Chip Peripheral Bus
+ */
+#ifndef FSI_OPB_H
+#define FSI_OPB_H
+
+#include "exec/memory.h"
+#include "hw/fsi/fsi-master.h"
+
+#define TYPE_OP_BUS "opb"
+OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
+
+typedef struct OPBus {
+ /*< private >*/
+ BusState bus;
+
+ /*< public >*/
+ MemoryRegion mr;
+ AddressSpace as;
+
+ /* Model OPB as dumb enough just to provide an address-space */
+ /* TODO: Maybe don't store device state in the bus? */
+ FSIMasterState fsi;
+} OPBus;
+
+typedef struct OPBusClass {
+ BusClass parent_class;
+} OPBusClass;
+
+uint8_t opb_read8(OPBus *opb, hwaddr addr);
+uint16_t opb_read16(OPBus *opb, hwaddr addr);
+uint32_t opb_read32(OPBus *opb, hwaddr addr);
+void opb_write8(OPBus *opb, hwaddr addr, uint8_t data);
+void opb_write16(OPBus *opb, hwaddr addr, uint16_t data);
+void opb_write32(OPBus *opb, hwaddr addr, uint32_t data);
+
+void opb_fsi_master_address(OPBus *opb, hwaddr addr);
+void opb_opb2fsi_address(OPBus *opb, hwaddr addr);
+
+#endif /* FSI_OPB_H */
diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
index 8f4ae641c7..ede1a58e98 100644
--- a/hw/fsi/fsi-master.c
+++ b/hw/fsi/fsi-master.c
@@ -11,8 +11,7 @@
#include "trace.h"
#include "hw/fsi/fsi-master.h"
-
-#define TYPE_OP_BUS "opb"
+#include "hw/fsi/opb.h"
#define TO_REG(x) ((x) >> 2)
diff --git a/hw/fsi/opb.c b/hw/fsi/opb.c
new file mode 100644
index 0000000000..7ffd7730f7
--- /dev/null
+++ b/hw/fsi/opb.c
@@ -0,0 +1,185 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * IBM On-chip Peripheral Bus
+ */
+
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#include "hw/fsi/opb.h"
+
+static MemTxResult opb_read(OPBus *opb, hwaddr addr, void *data, size_t len)
+{
+ MemTxResult tx;
+ tx = address_space_read(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
+ len);
+ if (tx) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: OPB read failed: 0x%"HWADDR_PRIx" for %lu\n",
+ __func__, addr, len);
+ }
+ return tx;
+}
+
+uint8_t opb_read8(OPBus *opb, hwaddr addr)
+{
+ uint8_t data = -1;
+
+ (void)opb_read(opb, addr, &data, sizeof(data));
+
+ return data;
+}
+
+uint16_t opb_read16(OPBus *opb, hwaddr addr)
+{
+ uint16_t data = -1;
+
+ (void)opb_read(opb, addr, &data, sizeof(data));
+
+ return data;
+}
+
+uint32_t opb_read32(OPBus *opb, hwaddr addr)
+{
+ uint32_t data = -1;
+
+ (void)opb_read(opb, addr, &data, sizeof(data));
+
+ return data;
+}
+
+static void opb_write(OPBus *opb, hwaddr addr, void *data, size_t len)
+{
+ MemTxResult tx;
+ tx = address_space_write(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
+ len);
+ if (tx) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: OPB write failed: %"HWADDR_PRIx" for %lu\n",
+ __func__, addr, len);
+ }
+}
+
+void opb_write8(OPBus *opb, hwaddr addr, uint8_t data)
+{
+ opb_write(opb, addr, &data, sizeof(data));
+}
+
+void opb_write16(OPBus *opb, hwaddr addr, uint16_t data)
+{
+ opb_write(opb, addr, &data, sizeof(data));
+}
+
+void opb_write32(OPBus *opb, hwaddr addr, uint32_t data)
+{
+ opb_write(opb, addr, &data, sizeof(data));
+}
+
+void opb_fsi_master_address(OPBus *opb, hwaddr addr)
+{
+ memory_region_transaction_begin();
+ memory_region_set_address(&opb->fsi.iomem, addr);
+ memory_region_transaction_commit();
+}
+
+void opb_opb2fsi_address(OPBus *opb, hwaddr addr)
+{
+ memory_region_transaction_begin();
+ memory_region_set_address(&opb->fsi.opb2fsi, addr);
+ memory_region_transaction_commit();
+}
+
+static uint64_t opb_unimplemented_read(void *opaque, hwaddr addr, unsigned size)
+{
+ trace_opb_unimplemented_read(addr, size);
+
+ return 0;
+}
+
+static void opb_unimplemented_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ trace_opb_unimplemented_write(addr, size, data);
+}
+
+static const struct MemoryRegionOps opb_unimplemented_ops = {
+ .read = opb_unimplemented_read,
+ .write = opb_unimplemented_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void opb_realize(BusState *bus, Error **errp)
+{
+ OPBus *opb = OP_BUS(bus);
+ Error *err = NULL;
+
+ memory_region_init_io(&opb->mr, OBJECT(opb), &opb_unimplemented_ops, opb,
+ NULL, UINT32_MAX);
+ address_space_init(&opb->as, &opb->mr, "opb");
+
+ object_property_set_bool(OBJECT(&opb->fsi), "realized", true, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ memory_region_add_subregion(&opb->mr, 0x80000000, &opb->fsi.iomem);
+
+ /* OPB2FSI region */
+ /*
+ * Avoid endianness issues by mapping each slave's memory region directly.
+ * Manually bridging multiple address-spaces causes endian swapping
+ * headaches as memory_region_dispatch_read() and
+ * memory_region_dispatch_write() correct the endianness based on the
+ * target machine endianness and not relative to the device endianness on
+ * either side of the bridge.
+ */
+ /*
+ * XXX: This is a bit hairy and will need to be fixed when I sort out the
+ * bus/slave relationship and any changes to the CFAM modelling (multiple
+ * slaves, LBUS)
+ */
+ memory_region_add_subregion(&opb->mr, 0xa0000000, &opb->fsi.opb2fsi);
+}
+
+static void opb_init(Object *o)
+{
+ OPBus *opb = OP_BUS(o);
+
+ object_initialize_child(o, "fsi-master", &opb->fsi, TYPE_FSI_MASTER);
+ qdev_set_parent_bus(DEVICE(&opb->fsi), BUS(o), &error_abort);
+}
+
+static void opb_finalize(Object *o)
+{
+ OPBus *opb = OP_BUS(o);
+
+ address_space_destroy(&opb->as);
+}
+
+static void opb_class_init(ObjectClass *klass, void *data)
+{
+ BusClass *bc = BUS_CLASS(klass);
+ bc->realize = opb_realize;
+}
+
+static const TypeInfo opb_info = {
+ .name = TYPE_OP_BUS,
+ .parent = TYPE_BUS,
+ .instance_init = opb_init,
+ .instance_finalize = opb_finalize,
+ .instance_size = sizeof(OPBus),
+ .class_init = opb_class_init,
+ .class_size = sizeof(OPBusClass),
+};
+
+static void opb_register_types(void)
+{
+ type_register_static(&opb_info);
+}
+
+type_init(opb_register_types);
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
index 8d712e77ed..0f6e6d331a 100644
--- a/hw/fsi/Kconfig
+++ b/hw/fsi/Kconfig
@@ -1,3 +1,7 @@
+config FSI_OPB
+ bool
+ select FSI_CFAM
+
config FSI_CFAM
bool
select FSI
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index f617943b4a..407b8c2775 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -2,3 +2,4 @@ system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi.c','fsi-master.c','fsi-slave.c'))
+system_ss.add(when: 'CONFIG_FSI_OPB', if_true: files('opb.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index d7afef0460..ec9bab2fe8 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -9,3 +9,5 @@ fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (4 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 7:16 ` Cédric Le Goater
2023-10-11 15:13 ` [PATCH v5 07/10] hw/arm: Hook up FSI module in AST2600 Ninad Palsule
` (4 subsequent siblings)
10 siblings, 1 reply; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This is a part of patchset where IBM's Flexible Service Interface is
introduced.
An APB-to-OPB bridge enabling access to the OPB from the ARM core in
the AST2600. Hardware limitations prevent the OPB from being directly
mapped into APB, so all accesses are indirect through the bridge.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
v2:
- Incorporated review comments by Joel
v3:
- Incorporated review comments by Thomas Huth
v4:
- Compile FSI with ASPEED_SOC only.
v5:
- Incorporated review comments by Cedric.
---
meson.build | 1 +
hw/fsi/trace.h | 1 +
include/hw/fsi/aspeed-apb2opb.h | 33 +++
hw/fsi/aspeed-apb2opb.c | 350 ++++++++++++++++++++++++++++++++
hw/arm/Kconfig | 1 +
hw/fsi/Kconfig | 4 +
hw/fsi/meson.build | 1 +
hw/fsi/trace-events | 2 +
8 files changed, 393 insertions(+)
create mode 100644 hw/fsi/trace.h
create mode 100644 include/hw/fsi/aspeed-apb2opb.h
create mode 100644 hw/fsi/aspeed-apb2opb.c
diff --git a/meson.build b/meson.build
index 98e68ef0b1..1a722693a6 100644
--- a/meson.build
+++ b/meson.build
@@ -3244,6 +3244,7 @@ if have_system
'hw/char',
'hw/display',
'hw/dma',
+ 'hw/fsi',
'hw/hyperv',
'hw/i2c',
'hw/i386',
diff --git a/hw/fsi/trace.h b/hw/fsi/trace.h
new file mode 100644
index 0000000000..ee67c7fb04
--- /dev/null
+++ b/hw/fsi/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_fsi.h"
diff --git a/include/hw/fsi/aspeed-apb2opb.h b/include/hw/fsi/aspeed-apb2opb.h
new file mode 100644
index 0000000000..a81ae67023
--- /dev/null
+++ b/include/hw/fsi/aspeed-apb2opb.h
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * ASPEED APB2OPB Bridge
+ */
+#ifndef FSI_ASPEED_APB2OPB_H
+#define FSI_ASPEED_APB2OPB_H
+
+#include "hw/sysbus.h"
+#include "hw/fsi/opb.h"
+
+#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
+
+#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
+
+#define ASPEED_FSI_NUM 2
+
+typedef struct AspeedAPB2OPBState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+
+ uint32_t regs[ASPEED_APB2OPB_NR_REGS];
+ qemu_irq irq;
+
+ OPBus opb[ASPEED_FSI_NUM];
+} AspeedAPB2OPBState;
+
+#endif /* FSI_ASPEED_APB2OPB_H */
diff --git a/hw/fsi/aspeed-apb2opb.c b/hw/fsi/aspeed-apb2opb.c
new file mode 100644
index 0000000000..e4efc08778
--- /dev/null
+++ b/hw/fsi/aspeed-apb2opb.c
@@ -0,0 +1,350 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (C) 2023 IBM Corp.
+ *
+ * ASPEED APB-OPB FSI interface
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+#include "hw/fsi/aspeed-apb2opb.h"
+#include "hw/qdev-core.h"
+
+#define TO_REG(x) (x >> 2)
+#define GENMASK(t, b) (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
+
+#define APB2OPB_VERSION TO_REG(0x00)
+#define APB2OPB_VERSION_VER GENMASK(7, 0)
+
+#define APB2OPB_TRIGGER TO_REG(0x04)
+#define APB2OPB_TRIGGER_EN BIT(0)
+
+#define APB2OPB_CONTROL TO_REG(0x08)
+#define APB2OPB_CONTROL_OFF GENMASK(31, 13)
+
+#define APB2OPB_OPB2FSI TO_REG(0x0c)
+#define APB2OPB_OPB2FSI_OFF GENMASK(31, 22)
+
+#define APB2OPB_OPB0_SEL TO_REG(0x10)
+#define APB2OPB_OPB1_SEL TO_REG(0x28)
+#define APB2OPB_OPB_SEL_EN BIT(0)
+
+#define APB2OPB_OPB0_MODE TO_REG(0x14)
+#define APB2OPB_OPB1_MODE TO_REG(0x2c)
+#define APB2OPB_OPB_MODE_RD BIT(0)
+
+#define APB2OPB_OPB0_XFER TO_REG(0x18)
+#define APB2OPB_OPB1_XFER TO_REG(0x30)
+#define APB2OPB_OPB_XFER_FULL BIT(1)
+#define APB2OPB_OPB_XFER_HALF BIT(0)
+
+#define APB2OPB_OPB0_ADDR TO_REG(0x1c)
+#define APB2OPB_OPB0_WRITE_DATA TO_REG(0x20)
+
+#define APB2OPB_OPB1_DMA_EN TO_REG(0x24)
+#define APB2OPB_OPB1_DMA_EN_3 BIT(3)
+#define APB2OPB_OPB1_DMA_EN_2 BIT(2)
+#define APB2OPB_OPB1_DMA_EN_1 BIT(1)
+#define APB2OPB_OPB1_DMA_EN_0 BIT(0)
+
+#define APB2OPB_OPB1_ADDR TO_REG(0x34)
+#define APB2OPB_OPB1_WRITE_DATA TO_REG(0x38)
+
+#define APB2OPB_OPB_CLK TO_REG(0x3c)
+#define APB2OPB_OPB_CLK_SYNC BIT(0)
+
+#define APB2OPB_IRQ_CLEAR TO_REG(0x40)
+#define APB2OPB_IRQ_CLEAR_EN BIT(0)
+
+#define APB2OPB_IRQ_MASK TO_REG(0x44)
+#define APB2OPB_IRQ_MASK_OPB1_TX_ACK BIT(17)
+#define APB2OPB_IRQ_MASK_OPB0_TX_ACK BIT(16)
+#define APB2OPB_IRQ_MASK_CH3_TCONT BIT(15)
+#define APB2OPB_IRQ_MASK_CH2_TCONT BIT(14)
+#define APB2OPB_IRQ_MASK_CH1_TCONT BIT(13)
+#define APB2OPB_IRQ_MASK_CH0_TCONT BIT(12)
+#define APB2OPB_IRQ_MASK_CH3_FIFO_EMPTY BIT(11)
+#define APB2OPB_IRQ_MASK_CH2_FIFO_EMPTY BIT(10)
+#define APB2OPB_IRQ_MASK_CH1_FIFO_EMPTY BIT(9)
+#define APB2OPB_IRQ_MASK_CH0_FIFO_EMPTY BIT(8)
+#define APB2OPB_IRQ_MASK_CH3_FIFO_FULL BIT(7)
+#define APB2OPB_IRQ_MASK_CH2_FIFO_FULL BIT(6)
+#define APB2OPB_IRQ_MASK_CH1_FIFO_FULL BIT(5)
+#define APB2OPB_IRQ_MASK_CH0_FIFO_FULL BIT(4)
+#define APB2OPB_IRQ_MASK_CH3_DMA_EOT BIT(3)
+#define APB2OPB_IRQ_MASK_CH2_DMA_EOT BIT(2)
+#define APB2OPB_IRQ_MASK_CH1_DMA_EOT BIT(1)
+#define APB2OPB_IRQ_MASK_CH0_DMA_EOT BIT(0)
+
+#define APB2OPB_IRQ_STS TO_REG(0x48)
+#define APB2OPB_IRQ_STS_MASTER_ERROR BIT(28)
+#define APB2OPB_IRQ_STS_PORT_ERROR BIT(27)
+#define APB2OPB_IRQ_STS_HOTPLUG BIT(26)
+#define APB2OPB_IRQ_STS_SLAVE_7 BIT(25)
+#define APB2OPB_IRQ_STS_SLAVE_6 BIT(24)
+#define APB2OPB_IRQ_STS_SLAVE_5 BIT(23)
+#define APB2OPB_IRQ_STS_SLAVE_4 BIT(22)
+#define APB2OPB_IRQ_STS_SLAVE_3 BIT(21)
+#define APB2OPB_IRQ_STS_SLAVE_2 BIT(20)
+#define APB2OPB_IRQ_STS_SLAVE_1 BIT(19)
+#define APB2OPB_IRQ_STS_SLAVE_0 BIT(18)
+#define APB2OPB_IRQ_STS_OPB1_TX_ACK BIT(17)
+#define APB2OPB_IRQ_STS_OPB0_TX_ACK BIT(16)
+#define APB2OPB_IRQ_STS_CH3_TCONT BIT(15)
+#define APB2OPB_IRQ_STS_CH2_TCONT BIT(14)
+#define APB2OPB_IRQ_STS_CH1_TCONT BIT(13)
+#define APB2OPB_IRQ_STS_CH0_TCONT BIT(12)
+#define APB2OPB_IRQ_STS_CH3_FIFO_EMPTY BIT(11)
+#define APB2OPB_IRQ_STS_CH2_FIFO_EMPTY BIT(10)
+#define APB2OPB_IRQ_STS_CH1_FIFO_EMPTY BIT(9)
+#define APB2OPB_IRQ_STS_CH0_FIFO_EMPTY BIT(8)
+#define APB2OPB_IRQ_STS_CH3_FIFO_FULL BIT(7)
+#define APB2OPB_IRQ_STS_CH2_FIFO_FULL BIT(6)
+#define APB2OPB_IRQ_STS_CH1_FIFO_FULL BIT(5)
+#define APB2OPB_IRQ_STS_CH0_FIFO_FULL BIT(4)
+#define APB2OPB_IRQ_STS_CH3_DMA_EOT BIT(3)
+#define APB2OPB_IRQ_STS_CH2_DMA_EOT BIT(2)
+#define APB2OPB_IRQ_STS_CH1_DMA_EOT BIT(1)
+#define APB2OPB_IRQ_STS_CH0_DMA_EOT BIT(0)
+
+#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
+#define APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b
+#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50)
+#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f
+#define APB2OPB_OPB1_WRITE_WORD_ENDIAN TO_REG(0x54)
+#define APB2OPB_OPB1_WRITE_BYTE_ENDIAN TO_REG(0x58)
+#define APB2OPB_OPB0_READ_BYTE_ENDIAN TO_REG(0x5c)
+#define APB2OPB_OPB0_READ_WORD_ENDIAN_BE 0x00030b1b
+#define APB2OPB_OPB1_READ_BYTE_ENDIAN TO_REG(0x60)
+
+#define APB2OPB_RETRY TO_REG(0x64)
+#define APB2OPB_RETRY_COUNTER GENMASK(15, 0)
+
+#define APB2OPB_OPB0_STATUS TO_REG(0x80)
+#define APB2OPB_OPB1_STATUS TO_REG(0x8c)
+#define APB2OPB_OPB_STATUS_TIMEOUT BIT(4)
+#define APB2OPB_OPB_STATUS_RETRY BIT(3)
+#define APB2OPB_OPB_STATUS_ERROR_ACK BIT(2)
+#define APB2OPB_OPB_STATUS_FW_ACK BIT(1)
+#define APB2OPB_OPB_STATUS_HW_ACK BIT(0)
+
+#define APB2OPB_OPB0_READ_DATA TO_REG(0x84)
+
+#define APB2OPB_OPB1_DMA_STATUS TO_REG(0x88)
+#define APB2OPB_OPB1_DMA_STATUS_CH3_EOT BIT(7)
+#define APB2OPB_OPB1_DMA_STATUS_CH2_EOT BIT(6)
+#define APB2OPB_OPB1_DMA_STATUS_CH1_EOT BIT(5)
+#define APB2OPB_OPB1_DMA_STATUS_CH0_EOT BIT(4)
+#define APB2OPB_OPB1_DMA_STATUS_CH3_REQ BIT(3)
+#define APB2OPB_OPB1_DMA_STATUS_CH2_REQ BIT(2)
+#define APB2OPB_OPB1_DMA_STATUS_CH1_REQ BIT(1)
+#define APB2OPB_OPB1_DMA_STATUS_CH0_REQ BIT(0)
+
+#define APB2OPB_OPB1_READ_DATA TO_REG(0x90)
+
+static uint64_t aspeed_apb2opb_read(void *opaque, hwaddr addr, unsigned size)
+{
+ AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
+
+ trace_aspeed_apb2opb_read(addr, size);
+
+ if (addr + size > sizeof(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return 0;
+ }
+
+ return s->regs[TO_REG(addr)];
+}
+
+static void aspeed_apb2opb_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
+
+ trace_aspeed_apb2opb_write(addr, size, data);
+
+ if (addr + size > sizeof(s->regs)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n",
+ __func__, addr, size);
+ return;
+ }
+
+ switch (TO_REG(addr)) {
+ case APB2OPB_CONTROL:
+ opb_fsi_master_address(&s->opb[0], data & APB2OPB_CONTROL_OFF);
+ break;
+ case APB2OPB_OPB2FSI:
+ opb_opb2fsi_address(&s->opb[0], data & APB2OPB_OPB2FSI_OFF);
+ break;
+ case APB2OPB_OPB0_WRITE_WORD_ENDIAN:
+ if (data != APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bridge needs to be driven as BE (0x%x)\n",
+ __func__, APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE);
+ }
+ break;
+ case APB2OPB_OPB0_WRITE_BYTE_ENDIAN:
+ if (data != APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bridge needs to be driven as BE (0x%x)\n",
+ __func__, APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE);
+ }
+ break;
+ case APB2OPB_OPB0_READ_BYTE_ENDIAN:
+ if (data != APB2OPB_OPB0_READ_WORD_ENDIAN_BE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bridge needs to be driven as BE (0x%x)\n",
+ __func__, APB2OPB_OPB0_READ_WORD_ENDIAN_BE);
+ }
+ break;
+ case APB2OPB_TRIGGER:
+ {
+ uint32_t opb, op_mode, op_size, op_addr, op_data;
+
+ assert((s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) ^
+ (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN));
+
+ if (s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) {
+ opb = 0;
+ op_mode = s->regs[APB2OPB_OPB0_MODE];
+ op_size = s->regs[APB2OPB_OPB0_XFER];
+ op_addr = s->regs[APB2OPB_OPB0_ADDR];
+ op_data = s->regs[APB2OPB_OPB0_WRITE_DATA];
+ } else if (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN) {
+ opb = 1;
+ op_mode = s->regs[APB2OPB_OPB1_MODE];
+ op_size = s->regs[APB2OPB_OPB1_XFER];
+ op_addr = s->regs[APB2OPB_OPB1_ADDR];
+ op_data = s->regs[APB2OPB_OPB1_WRITE_DATA];
+ } else {
+ g_assert_not_reached();
+ }
+
+ if (op_size & ~(APB2OPB_OPB_XFER_HALF | APB2OPB_OPB_XFER_FULL)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "OPB transaction failed: Unrecognised access width: %d\n",
+ op_size);
+ return;
+ }
+
+ op_size += 1;
+
+ if (op_mode & APB2OPB_OPB_MODE_RD) {
+ int index = opb ? APB2OPB_OPB1_READ_DATA
+ : APB2OPB_OPB0_READ_DATA;
+
+ switch (op_size) {
+ case 1:
+ s->regs[index] = opb_read8(&s->opb[opb], op_addr);
+ break;
+ case 2:
+ s->regs[index] = opb_read16(&s->opb[opb], op_addr);
+ break;
+ case 4:
+ s->regs[index] = opb_read32(&s->opb[opb], op_addr);
+ break;
+ default:
+ g_assert_not_reached(); /* should have bailed above */
+ }
+ } else {
+ /* FIXME: Endian swizzling */
+ switch (op_size) {
+ case 1:
+ opb_write8(&s->opb[opb], op_addr, op_data);
+ break;
+ case 2:
+ opb_write16(&s->opb[opb], op_addr, op_data);
+ break;
+ case 4:
+ opb_write32(&s->opb[opb], op_addr, op_data);
+ break;
+ default:
+ g_assert_not_reached(); /* should have bailed above */
+ }
+ }
+ s->regs[APB2OPB_IRQ_STS] |= opb ? APB2OPB_IRQ_STS_OPB1_TX_ACK
+ : APB2OPB_IRQ_STS_OPB0_TX_ACK;
+ break;
+ }
+ }
+
+ s->regs[TO_REG(addr)] = data;
+}
+
+static const struct MemoryRegionOps aspeed_apb2opb_ops = {
+ .read = aspeed_apb2opb_read,
+ .write = aspeed_apb2opb_write,
+ .valid.max_access_size = 4,
+ .valid.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .impl.min_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void aspeed_apb2opb_realize(DeviceState *dev, Error **errp)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev);
+
+ qbus_init(&s->opb[0], sizeof(s->opb[0]), TYPE_OP_BUS,
+ DEVICE(s), NULL);
+ qbus_init(&s->opb[1], sizeof(s->opb[1]), TYPE_OP_BUS,
+ DEVICE(s), NULL);
+
+ sysbus_init_irq(sbd, &s->irq);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_apb2opb_ops, s,
+ TYPE_ASPEED_APB2OPB, 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void aspeed_apb2opb_reset(DeviceState *dev)
+{
+ AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev);
+
+ memset(s->regs, 0, sizeof(s->regs));
+
+ s->regs[APB2OPB_VERSION] = 0x000000a1;
+
+ /*
+ * The following magic values came from AST2600 data sheet
+ * The register values are defined under section "FSI controller"
+ * as initial values.
+ */
+ s->regs[APB2OPB_OPB0_WRITE_WORD_ENDIAN] = 0x0044eee4;
+ s->regs[APB2OPB_OPB0_WRITE_BYTE_ENDIAN] = 0x0055aaff;
+ s->regs[APB2OPB_OPB1_WRITE_WORD_ENDIAN] = 0x00117717;
+ s->regs[APB2OPB_OPB1_WRITE_BYTE_ENDIAN] = 0xffaa5500;
+ s->regs[APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x0044eee4;
+ s->regs[APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x00117717;
+}
+
+static void aspeed_apb2opb_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "ASPEED APB2OPB Bridge";
+ dc->realize = aspeed_apb2opb_realize;
+ dc->reset = aspeed_apb2opb_reset;
+}
+
+static const TypeInfo aspeed_apb2opb_info = {
+ .name = TYPE_ASPEED_APB2OPB,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(AspeedAPB2OPBState),
+ .class_init = aspeed_apb2opb_class_init,
+};
+
+static void aspeed_apb2opb_register_types(void)
+{
+ type_register_static(&aspeed_apb2opb_info);
+}
+
+type_init(aspeed_apb2opb_register_types);
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7e68348440..d963de74c9 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -555,6 +555,7 @@ config ASPEED_SOC
select LED
select PMBUS
select MAX31785
+ select FSI_APB2OPB_ASPEED
config MPS2
bool
diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
index 0f6e6d331a..6bbcb8f6ca 100644
--- a/hw/fsi/Kconfig
+++ b/hw/fsi/Kconfig
@@ -1,3 +1,7 @@
+config FSI_APB2OPB_ASPEED
+ bool
+ select FSI_OPB
+
config FSI_OPB
bool
select FSI_CFAM
diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
index 407b8c2775..1bc6bb63cc 100644
--- a/hw/fsi/meson.build
+++ b/hw/fsi/meson.build
@@ -3,3 +3,4 @@ system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c
system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi.c','fsi-master.c','fsi-slave.c'))
system_ss.add(when: 'CONFIG_FSI_OPB', if_true: files('opb.c'))
+system_ss.add(when: 'CONFIG_FSI_APB2OPB_ASPEED', if_true: files('aspeed-apb2opb.c'))
diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
index ec9bab2fe8..4d4eb47c0b 100644
--- a/hw/fsi/trace-events
+++ b/hw/fsi/trace-events
@@ -11,3 +11,5 @@ fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
+aspeed_apb2opb_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
+aspeed_apb2opb_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 07/10] hw/arm: Hook up FSI module in AST2600
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (5 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 08/10] hw/fsi: Added qtest Ninad Palsule
` (3 subsequent siblings)
10 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
This patchset introduces IBM's Flexible Service Interface(FSI).
Time for some fun with inter-processor buses. FSI allows a service
processor access to the internal buses of a host POWER processor to
perform configuration or debugging.
FSI has long existed in POWER processes and so comes with some baggage,
including how it has been integrated into the ASPEED SoC.
Working backwards from the POWER processor, the fundamental pieces of
interest for the implementation are:
1. The Common FRU Access Macro (CFAM), an address space containing
various "engines" that drive accesses on buses internal and external
to the POWER chip. Examples include the SBEFIFO and I2C masters. The
engines hang off of an internal Local Bus (LBUS) which is described
by the CFAM configuration block.
2. The FSI slave: The slave is the terminal point of the FSI bus for
FSI symbols addressed to it. Slaves can be cascaded off of one
another. The slave's configuration registers appear in address space
of the CFAM to which it is attached.
3. The FSI master: A controller in the platform service processor (e.g.
BMC) driving CFAM engine accesses into the POWER chip. At the
hardware level FSI is a bit-based protocol supporting synchronous and
DMA-driven accesses of engines in a CFAM.
4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
POWER processors. This now makes an appearance in the ASPEED SoC due
to tight integration of the FSI master IP with the OPB, mainly the
existence of an MMIO-mapping of the CFAM address straight onto a
sub-region of the OPB address space.
5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in
the AST2600. Hardware limitations prevent the OPB from being directly
mapped into APB, so all accesses are indirect through the bridge.
The implementation appears as following in the qemu device tree:
(qemu) info qtree
bus: main-system-bus
type System
...
dev: aspeed.apb2opb, id ""
gpio-out "sysbus-irq" 1
mmio 000000001e79b000/0000000000001000
bus: opb.1
type opb
dev: fsi.master, id ""
bus: fsi.bus.1
type fsi.bus
dev: cfam.config, id ""
dev: cfam, id ""
bus: lbus.1
type lbus
dev: scratchpad, id ""
address = 0 (0x0)
bus: opb.0
type opb
dev: fsi.master, id ""
bus: fsi.bus.0
type fsi.bus
dev: cfam.config, id ""
dev: cfam, id ""
bus: lbus.0
type lbus
dev: scratchpad, id ""
address = 0 (0x0)
The LBUS is modelled to maintain the qdev bus hierarchy and to take
advantage of the object model to automatically generate the CFAM
configuration block. The configuration block presents engines in the
order they are attached to the CFAM's LBUS. Engine implementations
should subclass the LBusDevice and set the 'config' member of
LBusDeviceClass to match the engine's type.
CFAM designs offer a lot of flexibility, for instance it is possible for
a CFAM to be simultaneously driven from multiple FSI links. The modeling
is not so complete; it's assumed that each CFAM is attached to a single
FSI slave (as a consequence the CFAM subclasses the FSI slave).
As for FSI, its symbols and wire-protocol are not modelled at all. This
is not necessary to get FSI off the ground thanks to the mapping of the
CFAM address space onto the OPB address space - the models follow this
directly and map the CFAM memory region into the OPB's memory region.
Future work includes supporting more advanced accesses that drive the
FSI master directly rather than indirectly via the CFAM mapping, which
will require implementing the FSI state machine and methods for each of
the FSI symbols on the slave. Further down the track we can also look at
supporting the bitbanged SoftFSI drivers in Linux by extending the FSI
slave model to resolve sequences of GPIO IRQs into FSI symbols, and
calling the associated symbol method on the slave to map the access onto
the CFAM.
Testing:
Tested by reading cfam config address 0 on rainier machine type.
root@p10bmc:~# pdbg -a getcfam 0x0
p0: 0x0 = 0xc0022d15
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
include/hw/arm/aspeed_soc.h | 4 ++++
hw/arm/aspeed_ast2600.c | 19 +++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 8adff70072..db3ba3abc7 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -36,6 +36,7 @@
#include "hw/misc/aspeed_lpc.h"
#include "hw/misc/unimp.h"
#include "hw/misc/aspeed_peci.h"
+#include "hw/fsi/aspeed-apb2opb.h"
#include "hw/char/serial.h"
#define ASPEED_SPIS_NUM 2
@@ -96,6 +97,7 @@ struct AspeedSoCState {
UnimplementedDeviceState udc;
UnimplementedDeviceState sgpiom;
UnimplementedDeviceState jtag[ASPEED_JTAG_NUM];
+ AspeedAPB2OPBState fsi[2];
};
#define TYPE_ASPEED_SOC "aspeed-soc"
@@ -191,6 +193,8 @@ enum {
ASPEED_DEV_SGPIOM,
ASPEED_DEV_JTAG0,
ASPEED_DEV_JTAG1,
+ ASPEED_DEV_FSI1,
+ ASPEED_DEV_FSI2,
};
#define ASPEED_SOC_SPI_BOOT_ADDR 0x0
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index a8b3a8065a..010c9cee8a 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -75,6 +75,8 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
[ASPEED_DEV_UART12] = 0x1E790600,
[ASPEED_DEV_UART13] = 0x1E790700,
[ASPEED_DEV_VUART] = 0x1E787000,
+ [ASPEED_DEV_FSI1] = 0x1E79B000,
+ [ASPEED_DEV_FSI2] = 0x1E79B100,
[ASPEED_DEV_I3C] = 0x1E7A0000,
[ASPEED_DEV_SDRAM] = 0x80000000,
};
@@ -132,6 +134,8 @@ static const int aspeed_soc_ast2600_irqmap[] = {
[ASPEED_DEV_ETH4] = 33,
[ASPEED_DEV_KCS] = 138, /* 138 -> 142 */
[ASPEED_DEV_DP] = 62,
+ [ASPEED_DEV_FSI1] = 100,
+ [ASPEED_DEV_FSI2] = 101,
[ASPEED_DEV_I3C] = 102, /* 102 -> 107 */
};
@@ -262,6 +266,10 @@ static void aspeed_soc_ast2600_init(Object *obj)
object_initialize_child(obj, "emmc-boot-controller",
&s->emmc_boot_controller,
TYPE_UNIMPLEMENTED_DEVICE);
+
+ for (i = 0; i < ASPEED_FSI_NUM; i++) {
+ object_initialize_child(obj, "fsi[*]", &s->fsi[i], TYPE_ASPEED_APB2OPB);
+ }
}
/*
@@ -622,6 +630,17 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
return;
}
aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->sbc), 0, sc->memmap[ASPEED_DEV_SBC]);
+
+ /* FSI */
+ for (i = 0; i < ASPEED_FSI_NUM; i++) {
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->fsi[i]), errp)) {
+ return;
+ }
+ aspeed_mmio_map(s, SYS_BUS_DEVICE(&s->fsi[i]), 0,
+ sc->memmap[ASPEED_DEV_FSI1 + i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->fsi[i]), 0,
+ aspeed_soc_get_irq(s, ASPEED_DEV_FSI1 + i));
+ }
}
static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 08/10] hw/fsi: Added qtest
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (6 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 07/10] hw/arm: Hook up FSI module in AST2600 Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-11 15:35 ` Thomas Huth
2023-10-11 15:13 ` [PATCH v5 09/10] hw/fsi: Added FSI documentation Ninad Palsule
` (2 subsequent siblings)
10 siblings, 1 reply; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
Added basic qtests for FSI model.
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
v3:
- Added new qtest as per Cedric's comment.
V4:
- Remove MAINTAINER and documentation changes from this commit
---
tests/qtest/fsi-test.c | 210 ++++++++++++++++++++++++++++++++++++++++
tests/qtest/meson.build | 2 +
2 files changed, 212 insertions(+)
create mode 100644 tests/qtest/fsi-test.c
diff --git a/tests/qtest/fsi-test.c b/tests/qtest/fsi-test.c
new file mode 100644
index 0000000000..30bb7475c7
--- /dev/null
+++ b/tests/qtest/fsi-test.c
@@ -0,0 +1,210 @@
+/*
+ * QTest testcases for IBM's Flexible Service Interface (FSI)
+ *
+ * Copyright (c) 2023 IBM Corporation
+ *
+ * Authors:
+ * Ninad Palsule <ninad@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib/gstdio.h>
+
+#include "qemu/module.h"
+#include "libqtest-single.h"
+
+/* Registers from ast2600 specifications */
+#define ASPEED_FSI_ENGINER_TRIGGER 0x04
+#define ASPEED_FSI_OPB0_BUS_SELECT 0x10
+#define ASPEED_FSI_OPB1_BUS_SELECT 0x28
+#define ASPEED_FSI_OPB0_RW_DIRECTION 0x14
+#define ASPEED_FSI_OPB1_RW_DIRECTION 0x2c
+#define ASPEED_FSI_OPB0_XFER_SIZE 0x18
+#define ASPEED_FSI_OPB1_XFER_SIZE 0x30
+#define ASPEED_FSI_OPB0_BUS_ADDR 0x1c
+#define ASPEED_FSI_OPB1_BUS_ADDR 0x34
+#define ASPEED_FSI_INTRRUPT_CLEAR 0x40
+#define ASPEED_FSI_INTRRUPT_STATUS 0x48
+#define ASPEED_FSI_OPB0_BUS_STATUS 0x80
+#define ASPEED_FSI_OPB1_BUS_STATUS 0x8c
+#define ASPEED_FSI_OPB0_READ_DATA 0x84
+#define ASPEED_FSI_OPB1_READ_DATA 0x90
+
+/*
+ * FSI Base addresses from the ast2600 specifications.
+ */
+#define AST2600_OPB_FSI0_BASE_ADDR 0x1e79b000
+#define AST2600_OPB_FSI1_BASE_ADDR 0x1e79b100
+
+static uint32_t aspeed_fsi_base_addr;
+
+static uint32_t aspeed_fsi_readl(QTestState *s, uint32_t reg)
+{
+ return qtest_readl(s, aspeed_fsi_base_addr + reg);
+}
+
+static void aspeed_fsi_writel(QTestState *s, uint32_t reg, uint32_t val)
+{
+ qtest_writel(s, aspeed_fsi_base_addr + reg, val);
+}
+
+/* Setup base address and select register */
+static void test_fsi_setup(QTestState *s, uint32_t base_addr)
+{
+ uint32_t curval;
+
+ /* Set the base select register */
+ if (base_addr == AST2600_OPB_FSI0_BASE_ADDR) {
+ aspeed_fsi_base_addr = base_addr;
+
+ /* Unselect FSI1 */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x0);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT);
+ g_assert_cmpuint(curval, ==, 0x0);
+
+ /* Select FSI0 */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x1);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT);
+ g_assert_cmpuint(curval, ==, 0x1);
+ } else if (base_addr == AST2600_OPB_FSI1_BASE_ADDR) {
+ aspeed_fsi_base_addr = base_addr;
+
+ /* Unselect FSI0 */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x0);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT);
+ g_assert_cmpuint(curval, ==, 0x0);
+
+ /* Select FSI1 */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x1);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT);
+ g_assert_cmpuint(curval, ==, 0x1);
+ } else {
+ g_assert_not_reached();
+ }
+}
+
+static void test_fsi_reg_change(QTestState *s, uint32_t reg, uint32_t newval)
+{
+ uint32_t base;
+ uint32_t curval;
+
+ base = aspeed_fsi_readl(s, reg);
+ aspeed_fsi_writel(s, reg, newval);
+ curval = aspeed_fsi_readl(s, reg);
+ g_assert_cmpuint(curval, ==, newval);
+ aspeed_fsi_writel(s, reg, base);
+ curval = aspeed_fsi_readl(s, reg);
+ g_assert_cmpuint(curval, ==, base);
+}
+
+static void test_fsi0_master_regs(const void *data)
+{
+ QTestState *s = (QTestState *)data;
+
+ test_fsi_setup(s, AST2600_OPB_FSI0_BASE_ADDR);
+
+ test_fsi_reg_change(s, ASPEED_FSI_OPB0_RW_DIRECTION, 0xF3F4F514);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB0_XFER_SIZE, 0xF3F4F518);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB0_BUS_ADDR, 0xF3F4F51c);
+ test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_CLEAR, 0xF3F4F540);
+ test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_STATUS, 0xF3F4F548);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB0_BUS_STATUS, 0xF3F4F580);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB0_READ_DATA, 0xF3F4F584);
+}
+
+static void test_fsi1_master_regs(const void *data)
+{
+ QTestState *s = (QTestState *)data;
+
+ test_fsi_setup(s, AST2600_OPB_FSI1_BASE_ADDR);
+
+ test_fsi_reg_change(s, ASPEED_FSI_OPB1_RW_DIRECTION, 0xF3F4F514);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB1_XFER_SIZE, 0xF3F4F518);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB1_BUS_ADDR, 0xF3F4F51c);
+ test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_CLEAR, 0xF3F4F540);
+ test_fsi_reg_change(s, ASPEED_FSI_INTRRUPT_STATUS, 0xF3F4F548);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB1_BUS_STATUS, 0xF3F4F580);
+ test_fsi_reg_change(s, ASPEED_FSI_OPB1_READ_DATA, 0xF3F4F584);
+}
+
+static void test_fsi0_getcfam_addr0(const void *data)
+{
+ QTestState *s = (QTestState *)data;
+ uint32_t curval;
+
+ test_fsi_setup(s, AST2600_OPB_FSI0_BASE_ADDR);
+
+ /* Master access direction read */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB0_RW_DIRECTION, 0x1);
+ /* word */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB0_XFER_SIZE, 0x3);
+ /* Address */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_ADDR, 0xa0000000);
+ aspeed_fsi_writel(s, ASPEED_FSI_INTRRUPT_CLEAR, 0x1);
+ aspeed_fsi_writel(s, ASPEED_FSI_ENGINER_TRIGGER, 0x1);
+
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_INTRRUPT_STATUS);
+ g_assert_cmpuint(curval, ==, 0x10000);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_STATUS);
+ g_assert_cmpuint(curval, ==, 0x0);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_READ_DATA);
+ g_assert_cmpuint(curval, ==, 0x152d02c0);
+}
+
+static void test_fsi1_getcfam_addr0(const void *data)
+{
+ QTestState *s = (QTestState *)data;
+ uint32_t curval;
+
+ test_fsi_setup(s, AST2600_OPB_FSI1_BASE_ADDR);
+
+ /* Master access direction read */
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB1_RW_DIRECTION, 0x1);
+
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB1_XFER_SIZE, 0x3);
+ aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_ADDR, 0xa0000000);
+ aspeed_fsi_writel(s, ASPEED_FSI_INTRRUPT_CLEAR, 0x1);
+ aspeed_fsi_writel(s, ASPEED_FSI_ENGINER_TRIGGER, 0x1);
+
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_INTRRUPT_STATUS);
+ g_assert_cmpuint(curval, ==, 0x20000);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_STATUS);
+ g_assert_cmpuint(curval, ==, 0x0);
+ curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_READ_DATA);
+ g_assert_cmpuint(curval, ==, 0x152d02c0);
+}
+
+int main(int argc, char **argv)
+{
+ int ret = -1;
+ QTestState *s;
+
+ g_test_init(&argc, &argv, NULL);
+
+ s = qtest_init("-machine ast2600-evb ");
+ if (s == NULL) {
+ return -ENOMEM;
+ }
+
+ /* Tests for OPB/FSI0 */
+ qtest_add_data_func("/fsi-test/test_fsi0_master_regs", s,
+ test_fsi0_master_regs);
+
+ qtest_add_data_func("/fsi-test/test_fsi0_getcfam_addr0", s,
+ test_fsi0_getcfam_addr0);
+
+ /* Tests for OPB/FSI1 */
+ qtest_add_data_func("/fsi-test/test_fsi1_master_regs", s,
+ test_fsi1_master_regs);
+
+ qtest_add_data_func("/fsi-test/test_fsi1_getcfam_addr0", s,
+ test_fsi1_getcfam_addr0);
+
+ ret = g_test_run();
+ qtest_quit(s);
+
+ return ret;
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index b071d400b3..5976081b44 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -207,6 +207,7 @@ qtests_arm = \
(config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
(config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : []) + \
(config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['fsi-test'] : []) + \
['arm-cpu-features',
'boot-serial-test']
@@ -318,6 +319,7 @@ qtests = {
'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
+ 'fsi-test': files('fsi-test.c'),
}
if vnc.found()
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 09/10] hw/fsi: Added FSI documentation
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (7 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 08/10] hw/fsi: Added qtest Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 10/10] hw/fsi: Update MAINTAINER list Ninad Palsule
2023-10-19 8:16 ` [PATCH v5 00/10] Introduce model for IBM's FSI Cédric Le Goater
10 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
Documentation for IBM FSI model.
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
v4:
- Added separate commit for documentation
---
docs/specs/fsi.rst | 141 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+)
create mode 100644 docs/specs/fsi.rst
diff --git a/docs/specs/fsi.rst b/docs/specs/fsi.rst
new file mode 100644
index 0000000000..73b082afe1
--- /dev/null
+++ b/docs/specs/fsi.rst
@@ -0,0 +1,141 @@
+======================================
+IBM's Flexible Service Interface (FSI)
+======================================
+
+The QEMU FSI emulation implements hardware interfaces between ASPEED SOC, FSI
+master/slave and the end engine.
+
+FSI is a point-to-point two wire interface which is capable of supporting
+distances of up to 4 meters. FSI interfaces have been used successfully for
+many years in IBM servers to attach IBM Flexible Support Processors(FSP) to
+CPUs and IBM ASICs.
+
+FSI allows a service processor access to the internal buses of a host POWER
+processor to perform configuration or debugging. FSI has long existed in POWER
+processes and so comes with some baggage, including how it has been integrated
+into the ASPEED SoC.
+
+Working backwards from the POWER processor, the fundamental pieces of interest
+for the implementation are:
+
+1. The Common FRU Access Macro (CFAM), an address space containing various
+ "engines" that drive accesses on buses internal and external to the POWER
+ chip. Examples include the SBEFIFO and I2C masters. The engines hang off of
+ an internal Local Bus (LBUS) which is described by the CFAM configuration
+ block.
+
+2. The FSI slave: The slave is the terminal point of the FSI bus for FSI
+ symbols addressed to it. Slaves can be cascaded off of one another. The
+ slave's configuration registers appear in address space of the CFAM to
+ which it is attached.
+
+3. The FSI master: A controller in the platform service processor (e.g. BMC)
+ driving CFAM engine accesses into the POWER chip. At the hardware level
+ FSI is a bit-based protocol supporting synchronous and DMA-driven accesses
+ of engines in a CFAM.
+
+4. The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in POWER
+ processors. This now makes an appearance in the ASPEED SoC due to tight
+ integration of the FSI master IP with the OPB, mainly the existence of an
+ MMIO-mapping of the CFAM address straight onto a sub-region of the OPB
+ address space.
+
+5. An APB-to-OPB bridge enabling access to the OPB from the ARM core in the
+ AST2600. Hardware limitations prevent the OPB from being directly mapped
+ into APB, so all accesses are indirect through the bridge.
+
+The LBUS is modelled to maintain the qdev bus hierarchy and to take advantages
+of the object model to automatically generate the CFAM configuration block.
+The configuration block presents engines in the order they are attached to the
+CFAM's LBUS. Engine implementations should subclass the LBusDevice and set the
+'config' member of LBusDeviceClass to match the engine's type.
+
+CFAM designs offer a lot of flexibility, for instance it is possible for a
+CFAM to be simultaneously driven from multiple FSI links. The modeling is not
+so complete; it's assumed that each CFAM is attached to a single FSI slave (as
+a consequence the CFAM subclasses the FSI slave).
+
+As for FSI, its symbols and wire-protocol are not modelled at all. This is not
+necessary to get FSI off the ground thanks to the mapping of the CFAM address
+space onto the OPB address space - the models follow this directly and map the
+CFAM memory region into the OPB's memory region.
+
+QEMU files related to FSI interface:
+ - ``hw/fsi/aspeed-apb2opb.c``
+ - ``include/hw/fsi/aspeed-apb2opb.h``
+ - ``hw/fsi/opb.c``
+ - ``include/hw/fsi/opb.h``
+ - ``hw/fsi/fsi.c``
+ - ``include/hw/fsi/fsi.h``
+ - ``hw/fsi/fsi-master.c``
+ - ``include/hw/fsi/fsi-master.h``
+ - ``hw/fsi/fsi-slave.c``
+ - ``include/hw/fsi/fsi-slave.h``
+ - ``hw/fsi/cfam.c``
+ - ``include/hw/fsi/cfam.h``
+ - ``hw/fsi/engine-scratchpad.c``
+ - ``include/hw/fsi/engine-scratchpad.h``
+ - ``include/hw/fsi/lbus.h``
+
+The following commands start the rainier machine with built-in FSI model.
+There are no model specific arguments.
+
+.. code-block:: console
+
+ qemu-system-arm -M rainier-bmc -nographic \
+ -kernel fitImage-linux.bin \
+ -dtb aspeed-bmc-ibm-rainier.dtb \
+ -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \
+ -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \
+ -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a"
+
+The implementation appears as following in the qemu device tree:
+
+.. code-block:: console
+
+ (qemu) info qtree
+ bus: main-system-bus
+ type System
+ ...
+ dev: aspeed.apb2opb, id ""
+ gpio-out "sysbus-irq" 1
+ mmio 000000001e79b000/0000000000001000
+ bus: opb.1
+ type opb
+ dev: fsi.master, id ""
+ bus: fsi.bus.1
+ type fsi.bus
+ dev: cfam.config, id ""
+ dev: cfam, id ""
+ bus: lbus.1
+ type lbus
+ dev: scratchpad, id ""
+ address = 0 (0x0)
+ bus: opb.0
+ type opb
+ dev: fsi.master, id ""
+ bus: fsi.bus.0
+ type fsi.bus
+ dev: cfam.config, id ""
+ dev: cfam, id ""
+ bus: lbus.0
+ type lbus
+ dev: scratchpad, id ""
+ address = 0 (0x0)
+
+pdbg is a simple application to allow debugging of the host POWER processors
+from the BMC. (see the `pdbg source repository` for more details)
+
+.. code-block:: console
+
+ root@p10bmc:~# pdbg -a getcfam 0x0
+ p0: 0x0 = 0xc0022d15
+
+Refer following documents for more details.
+
+.. _FSI specification:
+ https://openpowerfoundation.org/specifications/fsi/
+ https://wiki.raptorcs.com/w/images/9/97/OpenFSI-spec-20161212.pdf
+
+.. _pdbg source repository:
+ https://github.com/open-power/pdbg
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v5 10/10] hw/fsi: Update MAINTAINER list
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (8 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 09/10] hw/fsi: Added FSI documentation Ninad Palsule
@ 2023-10-11 15:13 ` Ninad Palsule
2023-10-19 8:16 ` [PATCH v5 00/10] Introduce model for IBM's FSI Cédric Le Goater
10 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 15:13 UTC (permalink / raw
To: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: Ninad Palsule, qemu-arm
Added maintainer for IBM FSI model
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
V4:
- Added separate commit for MAINTAINER change.
V5:
- Use * instead of listing all files in dir
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6111b6b4d9..c69f90b227 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3395,6 +3395,14 @@ F: tests/qtest/adm1272-test.c
F: tests/qtest/max34451-test.c
F: tests/qtest/isl_pmbus_vr-test.c
+FSI
+M: Ninad Palsule <ninad@linux.ibm.com>
+S: Maintained
+F: hw/fsi/*
+F: include/hw/fsi/*
+F: docs/specs/fsi.rst
+F: tests/qtest/fsi-test.c
+
Firmware schema specifications
M: Philippe Mathieu-Daudé <philmd@linaro.org>
R: Daniel P. Berrange <berrange@redhat.com>
--
2.39.2
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH v5 08/10] hw/fsi: Added qtest
2023-10-11 15:13 ` [PATCH v5 08/10] hw/fsi: Added qtest Ninad Palsule
@ 2023-10-11 15:35 ` Thomas Huth
2023-10-11 16:54 ` Ninad Palsule
0 siblings, 1 reply; 41+ messages in thread
From: Thomas Huth @ 2023-10-11 15:35 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, clg, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, philmd, lvivier
Cc: qemu-arm
On 11/10/2023 17.13, Ninad Palsule wrote:
> Added basic qtests for FSI model.
>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v3:
> - Added new qtest as per Cedric's comment.
> V4:
> - Remove MAINTAINER and documentation changes from this commit
> ---
> tests/qtest/fsi-test.c | 210 ++++++++++++++++++++++++++++++++++++++++
> tests/qtest/meson.build | 2 +
> 2 files changed, 212 insertions(+)
> create mode 100644 tests/qtest/fsi-test.c
>
> diff --git a/tests/qtest/fsi-test.c b/tests/qtest/fsi-test.c
> new file mode 100644
> index 0000000000..30bb7475c7
> --- /dev/null
> +++ b/tests/qtest/fsi-test.c
> @@ -0,0 +1,210 @@
...
> +int main(int argc, char **argv)
> +{
> + int ret = -1;
> + QTestState *s;
> +
> + g_test_init(&argc, &argv, NULL);
> +
> + s = qtest_init("-machine ast2600-evb ");
> + if (s == NULL) {
> + return -ENOMEM;
returning -ENOMEM here does not make too much sense ... and actually
qtest_init() cannot return NULL. So please drop this if-statement.
> + }
> +
> + /* Tests for OPB/FSI0 */
> + qtest_add_data_func("/fsi-test/test_fsi0_master_regs", s,
> + test_fsi0_master_regs);
> +
> + qtest_add_data_func("/fsi-test/test_fsi0_getcfam_addr0", s,
> + test_fsi0_getcfam_addr0);
> +
> + /* Tests for OPB/FSI1 */
> + qtest_add_data_func("/fsi-test/test_fsi1_master_regs", s,
> + test_fsi1_master_regs);
> +
> + qtest_add_data_func("/fsi-test/test_fsi1_getcfam_addr0", s,
> + test_fsi1_getcfam_addr0);
> +
> + ret = g_test_run();
> + qtest_quit(s);
> +
> + return ret;
> +}
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index b071d400b3..5976081b44 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -207,6 +207,7 @@ qtests_arm = \
> (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
> (config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : []) + \
> (config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
> + (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ? ['fsi-test'] : []) + \
> ['arm-cpu-features',
> 'boot-serial-test']
>
> @@ -318,6 +319,7 @@ qtests = {
> 'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
> 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
> 'netdev-socket': files('netdev-socket.c', '../unit/socket-helpers.c'),
> + 'fsi-test': files('fsi-test.c'),
I think this hunk here is not required - you only need to specify additional
dependencies here, not the main file.
Thomas
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 08/10] hw/fsi: Added qtest
2023-10-11 15:35 ` Thomas Huth
@ 2023-10-11 16:54 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-11 16:54 UTC (permalink / raw
To: Thomas Huth, qemu-devel, clg, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, philmd, lvivier
Cc: qemu-arm
Hello Thomas,
Thanks for the review.
On 10/11/23 10:35, Thomas Huth wrote:
> On 11/10/2023 17.13, Ninad Palsule wrote:
>> Added basic qtests for FSI model.
>>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v3:
>> - Added new qtest as per Cedric's comment.
>> V4:
>> - Remove MAINTAINER and documentation changes from this commit
>> ---
>> tests/qtest/fsi-test.c | 210 ++++++++++++++++++++++++++++++++++++++++
>> tests/qtest/meson.build | 2 +
>> 2 files changed, 212 insertions(+)
>> create mode 100644 tests/qtest/fsi-test.c
>>
>> diff --git a/tests/qtest/fsi-test.c b/tests/qtest/fsi-test.c
>> new file mode 100644
>> index 0000000000..30bb7475c7
>> --- /dev/null
>> +++ b/tests/qtest/fsi-test.c
>> @@ -0,0 +1,210 @@
> ...
>> +int main(int argc, char **argv)
>> +{
>> + int ret = -1;
>> + QTestState *s;
>> +
>> + g_test_init(&argc, &argv, NULL);
>> +
>> + s = qtest_init("-machine ast2600-evb ");
>> + if (s == NULL) {
>> + return -ENOMEM;
>
> returning -ENOMEM here does not make too much sense ... and actually
> qtest_init() cannot return NULL. So please drop this if-statement.
Removed if condition.
>
>> + }
>> +
>> + /* Tests for OPB/FSI0 */
>> + qtest_add_data_func("/fsi-test/test_fsi0_master_regs", s,
>> + test_fsi0_master_regs);
>> +
>> + qtest_add_data_func("/fsi-test/test_fsi0_getcfam_addr0", s,
>> + test_fsi0_getcfam_addr0);
>> +
>> + /* Tests for OPB/FSI1 */
>> + qtest_add_data_func("/fsi-test/test_fsi1_master_regs", s,
>> + test_fsi1_master_regs);
>> +
>> + qtest_add_data_func("/fsi-test/test_fsi1_getcfam_addr0", s,
>> + test_fsi1_getcfam_addr0);
>> +
>> + ret = g_test_run();
>> + qtest_quit(s);
>> +
>> + return ret;
>> +}
>> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
>> index b071d400b3..5976081b44 100644
>> --- a/tests/qtest/meson.build
>> +++ b/tests/qtest/meson.build
>> @@ -207,6 +207,7 @@ qtests_arm = \
>> (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ?
>> ['tpm-tis-i2c-test'] : []) + \
>> (config_all_devices.has_key('CONFIG_VEXPRESS') ?
>> ['test-arm-mptimer'] : []) + \
>> (config_all_devices.has_key('CONFIG_MICROBIT') ?
>> ['microbit-test'] : []) + \
>> + (config_all_devices.has_key('CONFIG_FSI_APB2OPB_ASPEED') ?
>> ['fsi-test'] : []) + \
>> ['arm-cpu-features',
>> 'boot-serial-test']
>> @@ -318,6 +319,7 @@ qtests = {
>> 'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
>> 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
>> 'netdev-socket': files('netdev-socket.c',
>> '../unit/socket-helpers.c'),
>> + 'fsi-test': files('fsi-test.c'),
>
> I think this hunk here is not required - you only need to specify
> additional dependencies here, not the main file.
Removed list of files.
Thanks!
~Ninad
>
> Thomas
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface
2023-10-11 15:13 ` [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface Ninad Palsule
@ 2023-10-19 7:16 ` Cédric Le Goater
2023-10-21 20:43 ` Ninad Palsule
0 siblings, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 7:16 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> An APB-to-OPB bridge enabling access to the OPB from the ARM core in
> the AST2600. Hardware limitations prevent the OPB from being directly
> mapped into APB, so all accesses are indirect through the bridge.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated review comments by Joel
> v3:
> - Incorporated review comments by Thomas Huth
> v4:
> - Compile FSI with ASPEED_SOC only.
> v5:
> - Incorporated review comments by Cedric.
> ---
> meson.build | 1 +
> hw/fsi/trace.h | 1 +
> include/hw/fsi/aspeed-apb2opb.h | 33 +++
> hw/fsi/aspeed-apb2opb.c | 350 ++++++++++++++++++++++++++++++++
> hw/arm/Kconfig | 1 +
> hw/fsi/Kconfig | 4 +
> hw/fsi/meson.build | 1 +
> hw/fsi/trace-events | 2 +
> 8 files changed, 393 insertions(+)
> create mode 100644 hw/fsi/trace.h
> create mode 100644 include/hw/fsi/aspeed-apb2opb.h
> create mode 100644 hw/fsi/aspeed-apb2opb.c
>
> diff --git a/meson.build b/meson.build
> index 98e68ef0b1..1a722693a6 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -3244,6 +3244,7 @@ if have_system
> 'hw/char',
> 'hw/display',
> 'hw/dma',
> + 'hw/fsi',
> 'hw/hyperv',
> 'hw/i2c',
> 'hw/i386',
> diff --git a/hw/fsi/trace.h b/hw/fsi/trace.h
> new file mode 100644
> index 0000000000..ee67c7fb04
> --- /dev/null
> +++ b/hw/fsi/trace.h
> @@ -0,0 +1 @@
> +#include "trace/trace-hw_fsi.h"
> diff --git a/include/hw/fsi/aspeed-apb2opb.h b/include/hw/fsi/aspeed-apb2opb.h
> new file mode 100644
> index 0000000000..a81ae67023
> --- /dev/null
> +++ b/include/hw/fsi/aspeed-apb2opb.h
> @@ -0,0 +1,33 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * ASPEED APB2OPB Bridge
> + */
> +#ifndef FSI_ASPEED_APB2OPB_H
> +#define FSI_ASPEED_APB2OPB_H
> +
> +#include "hw/sysbus.h"
> +#include "hw/fsi/opb.h"
> +
> +#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
> +OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
> +
> +#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
> +
> +#define ASPEED_FSI_NUM 2
> +
> +typedef struct AspeedAPB2OPBState {
> + /*< private >*/
> + SysBusDevice parent_obj;
> +
> + /*< public >*/
> + MemoryRegion iomem;
> +
> + uint32_t regs[ASPEED_APB2OPB_NR_REGS];
> + qemu_irq irq;
> +
> + OPBus opb[ASPEED_FSI_NUM];
> +} AspeedAPB2OPBState;
> +
> +#endif /* FSI_ASPEED_APB2OPB_H */
> diff --git a/hw/fsi/aspeed-apb2opb.c b/hw/fsi/aspeed-apb2opb.c
> new file mode 100644
> index 0000000000..e4efc08778
> --- /dev/null
> +++ b/hw/fsi/aspeed-apb2opb.c
> @@ -0,0 +1,350 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * ASPEED APB-OPB FSI interface
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "qom/object.h"
> +#include "qapi/error.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/aspeed-apb2opb.h"
> +#include "hw/qdev-core.h"
> +
> +#define TO_REG(x) (x >> 2)
> +#define GENMASK(t, b) (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
> +
> +#define APB2OPB_VERSION TO_REG(0x00)
> +#define APB2OPB_VERSION_VER GENMASK(7, 0)
> +
> +#define APB2OPB_TRIGGER TO_REG(0x04)
> +#define APB2OPB_TRIGGER_EN BIT(0)
> +
> +#define APB2OPB_CONTROL TO_REG(0x08)
> +#define APB2OPB_CONTROL_OFF GENMASK(31, 13)
> +
> +#define APB2OPB_OPB2FSI TO_REG(0x0c)
> +#define APB2OPB_OPB2FSI_OFF GENMASK(31, 22)
> +
> +#define APB2OPB_OPB0_SEL TO_REG(0x10)
> +#define APB2OPB_OPB1_SEL TO_REG(0x28)
> +#define APB2OPB_OPB_SEL_EN BIT(0)
> +
> +#define APB2OPB_OPB0_MODE TO_REG(0x14)
> +#define APB2OPB_OPB1_MODE TO_REG(0x2c)
> +#define APB2OPB_OPB_MODE_RD BIT(0)
> +
> +#define APB2OPB_OPB0_XFER TO_REG(0x18)
> +#define APB2OPB_OPB1_XFER TO_REG(0x30)
> +#define APB2OPB_OPB_XFER_FULL BIT(1)
> +#define APB2OPB_OPB_XFER_HALF BIT(0)
> +
> +#define APB2OPB_OPB0_ADDR TO_REG(0x1c)
> +#define APB2OPB_OPB0_WRITE_DATA TO_REG(0x20)
> +
> +#define APB2OPB_OPB1_DMA_EN TO_REG(0x24)
> +#define APB2OPB_OPB1_DMA_EN_3 BIT(3)
> +#define APB2OPB_OPB1_DMA_EN_2 BIT(2)
> +#define APB2OPB_OPB1_DMA_EN_1 BIT(1)
> +#define APB2OPB_OPB1_DMA_EN_0 BIT(0)
> +
> +#define APB2OPB_OPB1_ADDR TO_REG(0x34)
> +#define APB2OPB_OPB1_WRITE_DATA TO_REG(0x38)
> +
> +#define APB2OPB_OPB_CLK TO_REG(0x3c)
> +#define APB2OPB_OPB_CLK_SYNC BIT(0)
> +
> +#define APB2OPB_IRQ_CLEAR TO_REG(0x40)
> +#define APB2OPB_IRQ_CLEAR_EN BIT(0)
> +
> +#define APB2OPB_IRQ_MASK TO_REG(0x44)
> +#define APB2OPB_IRQ_MASK_OPB1_TX_ACK BIT(17)
> +#define APB2OPB_IRQ_MASK_OPB0_TX_ACK BIT(16)
> +#define APB2OPB_IRQ_MASK_CH3_TCONT BIT(15)
> +#define APB2OPB_IRQ_MASK_CH2_TCONT BIT(14)
> +#define APB2OPB_IRQ_MASK_CH1_TCONT BIT(13)
> +#define APB2OPB_IRQ_MASK_CH0_TCONT BIT(12)
> +#define APB2OPB_IRQ_MASK_CH3_FIFO_EMPTY BIT(11)
> +#define APB2OPB_IRQ_MASK_CH2_FIFO_EMPTY BIT(10)
> +#define APB2OPB_IRQ_MASK_CH1_FIFO_EMPTY BIT(9)
> +#define APB2OPB_IRQ_MASK_CH0_FIFO_EMPTY BIT(8)
> +#define APB2OPB_IRQ_MASK_CH3_FIFO_FULL BIT(7)
> +#define APB2OPB_IRQ_MASK_CH2_FIFO_FULL BIT(6)
> +#define APB2OPB_IRQ_MASK_CH1_FIFO_FULL BIT(5)
> +#define APB2OPB_IRQ_MASK_CH0_FIFO_FULL BIT(4)
> +#define APB2OPB_IRQ_MASK_CH3_DMA_EOT BIT(3)
> +#define APB2OPB_IRQ_MASK_CH2_DMA_EOT BIT(2)
> +#define APB2OPB_IRQ_MASK_CH1_DMA_EOT BIT(1)
> +#define APB2OPB_IRQ_MASK_CH0_DMA_EOT BIT(0)
> +
> +#define APB2OPB_IRQ_STS TO_REG(0x48)
> +#define APB2OPB_IRQ_STS_MASTER_ERROR BIT(28)
> +#define APB2OPB_IRQ_STS_PORT_ERROR BIT(27)
> +#define APB2OPB_IRQ_STS_HOTPLUG BIT(26)
> +#define APB2OPB_IRQ_STS_SLAVE_7 BIT(25)
> +#define APB2OPB_IRQ_STS_SLAVE_6 BIT(24)
> +#define APB2OPB_IRQ_STS_SLAVE_5 BIT(23)
> +#define APB2OPB_IRQ_STS_SLAVE_4 BIT(22)
> +#define APB2OPB_IRQ_STS_SLAVE_3 BIT(21)
> +#define APB2OPB_IRQ_STS_SLAVE_2 BIT(20)
> +#define APB2OPB_IRQ_STS_SLAVE_1 BIT(19)
> +#define APB2OPB_IRQ_STS_SLAVE_0 BIT(18)
> +#define APB2OPB_IRQ_STS_OPB1_TX_ACK BIT(17)
> +#define APB2OPB_IRQ_STS_OPB0_TX_ACK BIT(16)
> +#define APB2OPB_IRQ_STS_CH3_TCONT BIT(15)
> +#define APB2OPB_IRQ_STS_CH2_TCONT BIT(14)
> +#define APB2OPB_IRQ_STS_CH1_TCONT BIT(13)
> +#define APB2OPB_IRQ_STS_CH0_TCONT BIT(12)
> +#define APB2OPB_IRQ_STS_CH3_FIFO_EMPTY BIT(11)
> +#define APB2OPB_IRQ_STS_CH2_FIFO_EMPTY BIT(10)
> +#define APB2OPB_IRQ_STS_CH1_FIFO_EMPTY BIT(9)
> +#define APB2OPB_IRQ_STS_CH0_FIFO_EMPTY BIT(8)
> +#define APB2OPB_IRQ_STS_CH3_FIFO_FULL BIT(7)
> +#define APB2OPB_IRQ_STS_CH2_FIFO_FULL BIT(6)
> +#define APB2OPB_IRQ_STS_CH1_FIFO_FULL BIT(5)
> +#define APB2OPB_IRQ_STS_CH0_FIFO_FULL BIT(4)
> +#define APB2OPB_IRQ_STS_CH3_DMA_EOT BIT(3)
> +#define APB2OPB_IRQ_STS_CH2_DMA_EOT BIT(2)
> +#define APB2OPB_IRQ_STS_CH1_DMA_EOT BIT(1)
> +#define APB2OPB_IRQ_STS_CH0_DMA_EOT BIT(0)
> +
> +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
> +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b
> +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50)
> +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f
> +#define APB2OPB_OPB1_WRITE_WORD_ENDIAN TO_REG(0x54)
> +#define APB2OPB_OPB1_WRITE_BYTE_ENDIAN TO_REG(0x58)
> +#define APB2OPB_OPB0_READ_BYTE_ENDIAN TO_REG(0x5c)
> +#define APB2OPB_OPB0_READ_WORD_ENDIAN_BE 0x00030b1b
> +#define APB2OPB_OPB1_READ_BYTE_ENDIAN TO_REG(0x60)
> +
> +#define APB2OPB_RETRY TO_REG(0x64)
> +#define APB2OPB_RETRY_COUNTER GENMASK(15, 0)
> +
> +#define APB2OPB_OPB0_STATUS TO_REG(0x80)
> +#define APB2OPB_OPB1_STATUS TO_REG(0x8c)
> +#define APB2OPB_OPB_STATUS_TIMEOUT BIT(4)
> +#define APB2OPB_OPB_STATUS_RETRY BIT(3)
> +#define APB2OPB_OPB_STATUS_ERROR_ACK BIT(2)
> +#define APB2OPB_OPB_STATUS_FW_ACK BIT(1)
> +#define APB2OPB_OPB_STATUS_HW_ACK BIT(0)
> +
> +#define APB2OPB_OPB0_READ_DATA TO_REG(0x84)
> +
> +#define APB2OPB_OPB1_DMA_STATUS TO_REG(0x88)
> +#define APB2OPB_OPB1_DMA_STATUS_CH3_EOT BIT(7)
> +#define APB2OPB_OPB1_DMA_STATUS_CH2_EOT BIT(6)
> +#define APB2OPB_OPB1_DMA_STATUS_CH1_EOT BIT(5)
> +#define APB2OPB_OPB1_DMA_STATUS_CH0_EOT BIT(4)
> +#define APB2OPB_OPB1_DMA_STATUS_CH3_REQ BIT(3)
> +#define APB2OPB_OPB1_DMA_STATUS_CH2_REQ BIT(2)
> +#define APB2OPB_OPB1_DMA_STATUS_CH1_REQ BIT(1)
> +#define APB2OPB_OPB1_DMA_STATUS_CH0_REQ BIT(0)
> +
> +#define APB2OPB_OPB1_READ_DATA TO_REG(0x90)
I think you can reduce this list of define to the minimum and re-introduce
the definitions when they are needed.
> +
> +static uint64_t aspeed_apb2opb_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
> +
> + trace_aspeed_apb2opb_read(addr, size);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return 0;
> + }
> +
> + return s->regs[TO_REG(addr)];
> +}
> +
> +static void aspeed_apb2opb_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
> +
> + trace_aspeed_apb2opb_write(addr, size, data);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return;
> + }
> +
> + switch (TO_REG(addr)) {
> + case APB2OPB_CONTROL:
> + opb_fsi_master_address(&s->opb[0], data & APB2OPB_CONTROL_OFF);
> + break;
> + case APB2OPB_OPB2FSI:
> + opb_opb2fsi_address(&s->opb[0], data & APB2OPB_OPB2FSI_OFF);
> + break;
> + case APB2OPB_OPB0_WRITE_WORD_ENDIAN:
> + if (data != APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Bridge needs to be driven as BE (0x%x)\n",
> + __func__, APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE);
> + }
> + break;
> + case APB2OPB_OPB0_WRITE_BYTE_ENDIAN:
> + if (data != APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Bridge needs to be driven as BE (0x%x)\n",
> + __func__, APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE);
> + }
> + break;
> + case APB2OPB_OPB0_READ_BYTE_ENDIAN:
> + if (data != APB2OPB_OPB0_READ_WORD_ENDIAN_BE) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Bridge needs to be driven as BE (0x%x)\n",
> + __func__, APB2OPB_OPB0_READ_WORD_ENDIAN_BE);
> + }
> + break;
> + case APB2OPB_TRIGGER:
> + {
> + uint32_t opb, op_mode, op_size, op_addr, op_data;
> +
> + assert((s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) ^
> + (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN));
> +
> + if (s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) {
> + opb = 0;
> + op_mode = s->regs[APB2OPB_OPB0_MODE];
> + op_size = s->regs[APB2OPB_OPB0_XFER];
> + op_addr = s->regs[APB2OPB_OPB0_ADDR];
> + op_data = s->regs[APB2OPB_OPB0_WRITE_DATA];
> + } else if (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN) {
> + opb = 1;
> + op_mode = s->regs[APB2OPB_OPB1_MODE];
> + op_size = s->regs[APB2OPB_OPB1_XFER];
> + op_addr = s->regs[APB2OPB_OPB1_ADDR];
> + op_data = s->regs[APB2OPB_OPB1_WRITE_DATA];
> + } else {
> + g_assert_not_reached();
This makes the memop quite fatal. A LOG_GUEST_ERROR would be more appropriate.
> + }
> +
> + if (op_size & ~(APB2OPB_OPB_XFER_HALF | APB2OPB_OPB_XFER_FULL)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "OPB transaction failed: Unrecognised access width: %d\n",
> + op_size);
> + return;
> + }
> +
> + op_size += 1;
> +
> + if (op_mode & APB2OPB_OPB_MODE_RD) {
> + int index = opb ? APB2OPB_OPB1_READ_DATA
> + : APB2OPB_OPB0_READ_DATA;
> +
> + switch (op_size) {
> + case 1:
> + s->regs[index] = opb_read8(&s->opb[opb], op_addr);
> + break;
> + case 2:
> + s->regs[index] = opb_read16(&s->opb[opb], op_addr);
> + break;
> + case 4:
> + s->regs[index] = opb_read32(&s->opb[opb], op_addr);
> + break;
> + default:
> + g_assert_not_reached(); /* should have bailed above */
> + }
> + } else {
> + /* FIXME: Endian swizzling */
> + switch (op_size) {
> + case 1:
> + opb_write8(&s->opb[opb], op_addr, op_data);
> + break;
> + case 2:
> + opb_write16(&s->opb[opb], op_addr, op_data);
> + break;
> + case 4:
> + opb_write32(&s->opb[opb], op_addr, op_data);
> + break;
> + default:
> + g_assert_not_reached(); /* should have bailed above */
> + }
> + }
> + s->regs[APB2OPB_IRQ_STS] |= opb ? APB2OPB_IRQ_STS_OPB1_TX_ACK
> + : APB2OPB_IRQ_STS_OPB0_TX_ACK;
> + break;
> + }
> + }
> +
> + s->regs[TO_REG(addr)] = data;
> +}
> +
> +static const struct MemoryRegionOps aspeed_apb2opb_ops = {
> + .read = aspeed_apb2opb_read,
> + .write = aspeed_apb2opb_write,
> + .valid.max_access_size = 4,
> + .valid.min_access_size = 4,
> + .impl.max_access_size = 4,
> + .impl.min_access_size = 4,
> + .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
> +static void aspeed_apb2opb_realize(DeviceState *dev, Error **errp)
> +{
> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev);
> +
> + qbus_init(&s->opb[0], sizeof(s->opb[0]), TYPE_OP_BUS,
> + DEVICE(s), NULL);
> + qbus_init(&s->opb[1], sizeof(s->opb[1]), TYPE_OP_BUS,
> + DEVICE(s), NULL);
> +
> + sysbus_init_irq(sbd, &s->irq);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_apb2opb_ops, s,
> + TYPE_ASPEED_APB2OPB, 0x1000);
> + sysbus_init_mmio(sbd, &s->iomem);
> +}
> +
> +static void aspeed_apb2opb_reset(DeviceState *dev)
> +{
> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev);
> +
> + memset(s->regs, 0, sizeof(s->regs));
> +
> + s->regs[APB2OPB_VERSION] = 0x000000a1;
> +
> + /*
> + * The following magic values came from AST2600 data sheet
> + * The register values are defined under section "FSI controller"
> + * as initial values.
> + */
> + s->regs[APB2OPB_OPB0_WRITE_WORD_ENDIAN] = 0x0044eee4;
> + s->regs[APB2OPB_OPB0_WRITE_BYTE_ENDIAN] = 0x0055aaff;
> + s->regs[APB2OPB_OPB1_WRITE_WORD_ENDIAN] = 0x00117717;
> + s->regs[APB2OPB_OPB1_WRITE_BYTE_ENDIAN] = 0xffaa5500;
> + s->regs[APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x0044eee4;
> + s->regs[APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x00117717;
You could use a reset array to set the values. See SCU.
The reset looks good.
Thanks,
C.
> +}
> +
> +static void aspeed_apb2opb_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->desc = "ASPEED APB2OPB Bridge";
> + dc->realize = aspeed_apb2opb_realize;
> + dc->reset = aspeed_apb2opb_reset;
> +}
> +
> +static const TypeInfo aspeed_apb2opb_info = {
> + .name = TYPE_ASPEED_APB2OPB,
> + .parent = TYPE_SYS_BUS_DEVICE,
> + .instance_size = sizeof(AspeedAPB2OPBState),
> + .class_init = aspeed_apb2opb_class_init,
> +};
> +
> +static void aspeed_apb2opb_register_types(void)
> +{
> + type_register_static(&aspeed_apb2opb_info);
> +}
> +
> +type_init(aspeed_apb2opb_register_types);
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 7e68348440..d963de74c9 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -555,6 +555,7 @@ config ASPEED_SOC
> select LED
> select PMBUS
> select MAX31785
> + select FSI_APB2OPB_ASPEED
>
> config MPS2
> bool
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> index 0f6e6d331a..6bbcb8f6ca 100644
> --- a/hw/fsi/Kconfig
> +++ b/hw/fsi/Kconfig
> @@ -1,3 +1,7 @@
> +config FSI_APB2OPB_ASPEED
> + bool
> + select FSI_OPB
> +
> config FSI_OPB
> bool
> select FSI_CFAM
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index 407b8c2775..1bc6bb63cc 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -3,3 +3,4 @@ system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c
> system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
> system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi.c','fsi-master.c','fsi-slave.c'))
> system_ss.add(when: 'CONFIG_FSI_OPB', if_true: files('opb.c'))
> +system_ss.add(when: 'CONFIG_FSI_APB2OPB_ASPEED', if_true: files('aspeed-apb2opb.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index ec9bab2fe8..4d4eb47c0b 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -11,3 +11,5 @@ fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +aspeed_apb2opb_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +aspeed_apb2opb_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus
2023-10-11 15:13 ` [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus Ninad Palsule
@ 2023-10-19 7:26 ` Cédric Le Goater
2023-10-21 20:40 ` Ninad Palsule
2023-10-19 8:30 ` Daniel P. Berrangé
1 sibling, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 7:26 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
> POWER processors. This now makes an appearance in the ASPEED SoC due
> to tight integration of the FSI master IP with the OPB, mainly the
> existence of an MMIO-mapping of the CFAM address straight onto a
> sub-region of the OPB address space.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
> v2:
> - Incorporated review comment by Joel.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/opb.h | 43 ++++++++++
> hw/fsi/fsi-master.c | 3 +-
> hw/fsi/opb.c | 185 +++++++++++++++++++++++++++++++++++++++++++
> hw/fsi/Kconfig | 4 +
> hw/fsi/meson.build | 1 +
> hw/fsi/trace-events | 2 +
> 6 files changed, 236 insertions(+), 2 deletions(-)
> create mode 100644 include/hw/fsi/opb.h
> create mode 100644 hw/fsi/opb.c
>
> diff --git a/include/hw/fsi/opb.h b/include/hw/fsi/opb.h
> new file mode 100644
> index 0000000000..f8ce00383e
> --- /dev/null
> +++ b/include/hw/fsi/opb.h
> @@ -0,0 +1,43 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM On-Chip Peripheral Bus
> + */
> +#ifndef FSI_OPB_H
> +#define FSI_OPB_H
> +
> +#include "exec/memory.h"
> +#include "hw/fsi/fsi-master.h"
> +
> +#define TYPE_OP_BUS "opb"
> +OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
> +
> +typedef struct OPBus {
> + /*< private >*/
> + BusState bus;
> +
> + /*< public >*/
> + MemoryRegion mr;
> + AddressSpace as;
> +
> + /* Model OPB as dumb enough just to provide an address-space */
> + /* TODO: Maybe don't store device state in the bus? */
> + FSIMasterState fsi;
> +} OPBus;
> +
> +typedef struct OPBusClass {
> + BusClass parent_class;
> +} OPBusClass;
> +
> +uint8_t opb_read8(OPBus *opb, hwaddr addr);
> +uint16_t opb_read16(OPBus *opb, hwaddr addr);
> +uint32_t opb_read32(OPBus *opb, hwaddr addr);
> +void opb_write8(OPBus *opb, hwaddr addr, uint8_t data);
> +void opb_write16(OPBus *opb, hwaddr addr, uint16_t data);
> +void opb_write32(OPBus *opb, hwaddr addr, uint32_t data);
> +
> +void opb_fsi_master_address(OPBus *opb, hwaddr addr);
> +void opb_opb2fsi_address(OPBus *opb, hwaddr addr);
> +
> +#endif /* FSI_OPB_H */
> diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
> index 8f4ae641c7..ede1a58e98 100644
> --- a/hw/fsi/fsi-master.c
> +++ b/hw/fsi/fsi-master.c
> @@ -11,8 +11,7 @@
> #include "trace.h"
>
> #include "hw/fsi/fsi-master.h"
> -
> -#define TYPE_OP_BUS "opb"
> +#include "hw/fsi/opb.h"
>
> #define TO_REG(x) ((x) >> 2)
>
> diff --git a/hw/fsi/opb.c b/hw/fsi/opb.c
> new file mode 100644
> index 0000000000..7ffd7730f7
> --- /dev/null
> +++ b/hw/fsi/opb.c
> @@ -0,0 +1,185 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM On-chip Peripheral Bus
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/opb.h"
> +
> +static MemTxResult opb_read(OPBus *opb, hwaddr addr, void *data, size_t len)
> +{
> + MemTxResult tx;
> + tx = address_space_read(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
> + len);
> + if (tx) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: OPB read failed: 0x%"HWADDR_PRIx" for %lu\n",
> + __func__, addr, len);
> + }
> + return tx;
> +}
> +
> +uint8_t opb_read8(OPBus *opb, hwaddr addr)
> +{
> + uint8_t data = -1;
> +
> + (void)opb_read(opb, addr, &data, sizeof(data));
> +
> + return data;
> +}
> +
> +uint16_t opb_read16(OPBus *opb, hwaddr addr)
> +{
> + uint16_t data = -1;
> +
> + (void)opb_read(opb, addr, &data, sizeof(data));
> +
> + return data;
> +}
> +
> +uint32_t opb_read32(OPBus *opb, hwaddr addr)
> +{
> + uint32_t data = -1;
> +
> + (void)opb_read(opb, addr, &data, sizeof(data));
> +
> + return data;
> +}
> +
> +static void opb_write(OPBus *opb, hwaddr addr, void *data, size_t len)
> +{
> + MemTxResult tx;
> + tx = address_space_write(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
> + len);
> + if (tx) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: OPB write failed: %"HWADDR_PRIx" for %lu\n",
> + __func__, addr, len);
> + }
> +}
> +
> +void opb_write8(OPBus *opb, hwaddr addr, uint8_t data)
> +{
> + opb_write(opb, addr, &data, sizeof(data));
> +}
> +
> +void opb_write16(OPBus *opb, hwaddr addr, uint16_t data)
> +{
> + opb_write(opb, addr, &data, sizeof(data));
> +}
> +
> +void opb_write32(OPBus *opb, hwaddr addr, uint32_t data)
> +{
> + opb_write(opb, addr, &data, sizeof(data));
> +}
Please remove all the above opb_* helpers and replace them with
address_space_rw() where they are use. Previous patch.
> +void opb_fsi_master_address(OPBus *opb, hwaddr addr)
> +{
> + memory_region_transaction_begin();
> + memory_region_set_address(&opb->fsi.iomem, addr);
> + memory_region_transaction_commit();
> +}
> +
> +void opb_opb2fsi_address(OPBus *opb, hwaddr addr)
> +{
> + memory_region_transaction_begin();
> + memory_region_set_address(&opb->fsi.opb2fsi, addr);
> + memory_region_transaction_commit();
> +}
These opb_opb2fs_* routines belong to PATCH 6.
> +static uint64_t opb_unimplemented_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + trace_opb_unimplemented_read(addr, size);
> +
> + return 0;
> +}
> +
> +static void opb_unimplemented_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + trace_opb_unimplemented_write(addr, size, data);
> +}
> +
> +static const struct MemoryRegionOps opb_unimplemented_ops = {
> + .read = opb_unimplemented_read,
> + .write = opb_unimplemented_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
have you checked if create_unimplemented_device() could be used ?
> +static void opb_realize(BusState *bus, Error **errp)
> +{
> + OPBus *opb = OP_BUS(bus);
> + Error *err = NULL;
> +
> + memory_region_init_io(&opb->mr, OBJECT(opb), &opb_unimplemented_ops, opb,
> + NULL, UINT32_MAX);
> + address_space_init(&opb->as, &opb->mr, "opb");
> +
> + object_property_set_bool(OBJECT(&opb->fsi), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> + memory_region_add_subregion(&opb->mr, 0x80000000, &opb->fsi.iomem);
> +
> + /* OPB2FSI region */
> + /*
> + * Avoid endianness issues by mapping each slave's memory region directly.
> + * Manually bridging multiple address-spaces causes endian swapping
> + * headaches as memory_region_dispatch_read() and
> + * memory_region_dispatch_write() correct the endianness based on the
> + * target machine endianness and not relative to the device endianness on
> + * either side of the bridge.
> + */
> + /*
> + * XXX: This is a bit hairy and will need to be fixed when I sort out the
> + * bus/slave relationship and any changes to the CFAM modelling (multiple
> + * slaves, LBUS)
> + */
> + memory_region_add_subregion(&opb->mr, 0xa0000000, &opb->fsi.opb2fsi);
> +}
> +
> +static void opb_init(Object *o)
> +{
> + OPBus *opb = OP_BUS(o);
> +
> + object_initialize_child(o, "fsi-master", &opb->fsi, TYPE_FSI_MASTER);
> + qdev_set_parent_bus(DEVICE(&opb->fsi), BUS(o), &error_abort);
This fsi object should be a child of TYPE_ASPEED_APB2OPB and created
with qdev_realize_and_unref() in aspeed_apb2opb_realize().
> +}
> +
> +static void opb_finalize(Object *o)
> +{
> + OPBus *opb = OP_BUS(o);
> +
> + address_space_destroy(&opb->as);
> +}
The finalize op is not strictly necessary.
Thanks,
C.
> +static void opb_class_init(ObjectClass *klass, void *data)
> +{
> + BusClass *bc = BUS_CLASS(klass);
> + bc->realize = opb_realize;
> +}
> +
> +static const TypeInfo opb_info = {
> + .name = TYPE_OP_BUS,
> + .parent = TYPE_BUS,
> + .instance_init = opb_init,
> + .instance_finalize = opb_finalize,
> + .instance_size = sizeof(OPBus),
> + .class_init = opb_class_init,
> + .class_size = sizeof(OPBusClass),
> +};
> +
> +static void opb_register_types(void)
> +{
> + type_register_static(&opb_info);
> +}
> +
> +type_init(opb_register_types);
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> index 8d712e77ed..0f6e6d331a 100644
> --- a/hw/fsi/Kconfig
> +++ b/hw/fsi/Kconfig
> @@ -1,3 +1,7 @@
> +config FSI_OPB
> + bool
> + select FSI_CFAM
> +
> config FSI_CFAM
> bool
> select FSI
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index f617943b4a..407b8c2775 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -2,3 +2,4 @@ system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
> system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
> system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi.c','fsi-master.c','fsi-slave.c'))
> +system_ss.add(when: 'CONFIG_FSI_OPB', if_true: files('opb.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index d7afef0460..ec9bab2fe8 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -9,3 +9,5 @@ fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI
2023-10-11 15:13 ` [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI Ninad Palsule
@ 2023-10-19 7:44 ` Cédric Le Goater
2023-10-21 20:36 ` Ninad Palsule
2023-10-19 8:28 ` Daniel P. Berrangé
1 sibling, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 7:44 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> This commit models the FSI bus. CFAM is hanging out of FSI bus. The bus
> is model such a way that it is embedded inside the FSI master which is a
> bus controller.
>
> The FSI master: A controller in the platform service processor (e.g.
> BMC) driving CFAM engine accesses into the POWER chip. At the
> hardware level FSI is a bit-based protocol supporting synchronous and
> DMA-driven accesses of engines in a CFAM.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
> v2:
> - Incorporated review comments by Joel
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/fsi-master.h | 30 ++++++
> include/hw/fsi/fsi.h | 37 +++++++
> hw/fsi/cfam.c | 2 +-
> hw/fsi/fsi-master.c | 199 ++++++++++++++++++++++++++++++++++++
> hw/fsi/fsi.c | 54 ++++++++++
> hw/fsi/meson.build | 2 +-
> hw/fsi/trace-events | 2 +
> 7 files changed, 324 insertions(+), 2 deletions(-)
> create mode 100644 include/hw/fsi/fsi-master.h
> create mode 100644 include/hw/fsi/fsi.h
> create mode 100644 hw/fsi/fsi-master.c
> create mode 100644 hw/fsi/fsi.c
>
> diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h
> new file mode 100644
> index 0000000000..847078919c
> --- /dev/null
> +++ b/include/hw/fsi/fsi-master.h
> @@ -0,0 +1,30 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2019 IBM Corp.
> + *
> + * IBM Flexible Service Interface Master
> + */
> +#ifndef FSI_FSI_MASTER_H
> +#define FSI_FSI_MASTER_H
> +
> +#include "exec/memory.h"
> +#include "hw/qdev-core.h"
> +#include "hw/fsi/fsi.h"
> +
> +#define TYPE_FSI_MASTER "fsi.master"
> +OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER)
> +
> +#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1)
> +
> +typedef struct FSIMasterState {
> + DeviceState parent;
> + MemoryRegion iomem;
> + MemoryRegion opb2fsi;
> +
> + FSIBus bus;
> +
> + uint32_t regs[FSI_MASTER_NR_REGS];
> +} FSIMasterState;
> +
> +
> +#endif /* FSI_FSI_H */
> diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
> new file mode 100644
> index 0000000000..cf97645abf
> --- /dev/null
> +++ b/include/hw/fsi/fsi.h
> @@ -0,0 +1,37 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface
> + */
> +#ifndef FSI_FSI_H
> +#define FSI_FSI_H
> +
> +#include "hw/qdev-core.h"
> +
> +/*
> + * TODO: Maybe unwind this dependency with const links? Store a
> + * pointer in FSIBus?
> + */
> +#include "hw/fsi/cfam.h"
> +
> +/* Bitwise operations at the word level. */
> +#define BE_BIT(x) BIT(31 - (x))
> +#define GENMASK(t, b) \
> + (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
> +#define BE_GENMASK(t, b) GENMASK(BE_BIT(t), BE_BIT(b))
> +
> +#define TYPE_FSI_BUS "fsi.bus"
> +OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
> +
> +/* TODO: Figure out what's best with a point-to-point bus */
> +typedef struct FSISlaveState FSISlaveState;
> +
> +typedef struct FSIBus {
> + BusState bus;
> +
> + /* XXX: It's point-to-point, just instantiate the slave directly for now */
> + CFAMState slave;
> +} FSIBus;
> +
> +#endif
> diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
> index 9044cc741b..74a10f9f4b 100644
> --- a/hw/fsi/cfam.c
> +++ b/hw/fsi/cfam.c
> @@ -10,8 +10,8 @@
> #include "qapi/error.h"
> #include "trace.h"
>
> -#include "hw/fsi/bits.h"
> #include "hw/fsi/cfam.h"
> +#include "hw/fsi/fsi.h"
> #include "hw/fsi/engine-scratchpad.h"
>
> #include "hw/qdev-properties.h"
> diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
> new file mode 100644
> index 0000000000..8f4ae641c7
> --- /dev/null
> +++ b/hw/fsi/fsi-master.c
> @@ -0,0 +1,199 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface master
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/fsi-master.h"
> +
> +#define TYPE_OP_BUS "opb"
> +
> +#define TO_REG(x) ((x) >> 2)
> +
> +#define FSI_MMODE TO_REG(0x000)
> +#define FSI_MMODE_IPOLL_DMA_EN BE_BIT(0)
> +#define FSI_MMODE_HW_ERROR_RECOVERY_EN BE_BIT(1)
> +#define FSI_MMODE_RELATIVE_ADDRESS_EN BE_BIT(2)
> +#define FSI_MMODE_PARITY_CHECK_EN BE_BIT(3)
> +#define FSI_MMODE_CLOCK_DIVIDER_0 BE_GENMASK(4, 13)
> +#define FSI_MMODE_CLOCK_DIVIDER_1 BE_GENMASK(14, 23)
> +#define FSI_MMODE_DEBUG_EN BE_BIT(24)
> +
> +#define FSI_MDELAY TO_REG(0x004)
> +#define FSI_MDELAY_ECHO_0 BE_GENMASK(0, 3)
> +#define FSI_MDELAY_SEND_0 BE_GENMASK(4, 7)
> +#define FSI_MDELAY_ECHO_1 BE_GENMASK(8, 11)
> +#define FSI_MDELAY_SEND_1 BE_GENMASK(12, 15)
> +
> +#define FSI_MENP0 TO_REG(0x010)
> +#define FSI_MENP32 TO_REG(0x014)
> +#define FSI_MSENP0 TO_REG(0x018)
> +#define FSI_MLEVP0 TO_REG(0x018)
> +#define FSI_MSENP32 TO_REG(0x01c)
> +#define FSI_MLEVP32 TO_REG(0x01c)
> +#define FSI_MCENP0 TO_REG(0x020)
> +#define FSI_MREFP0 TO_REG(0x020)
> +#define FSI_MCENP32 TO_REG(0x024)
> +#define FSI_MREFP32 TO_REG(0x024)
> +
> +#define FSI_MAEB TO_REG(0x070)
> +#define FSI_MAEB_ANY_CPU_ERROR BE_BIT(0)
> +#define FSI_MAEB_ANY_DMA_ERROR BE_GENMASK(1, 16)
> +#define FSI_MAEB_ANY_PARITY_ERROR BE_BIT(17)
> +
> +#define FSI_MVER TO_REG(0x074)
> +#define FSI_MVER_VERSION BE_GENMASK(0, 7)
> +#define FSI_MVER_BRIDGES BE_GENMASK(8, 15)
> +#define FSI_MVER_PORTS BE_GENMASK(16, 23)
> +
> +#define FSI_MRESP0 TO_REG(0x0d0)
> +#define FSI_MRESP0_RESET_PORT_GENERAL BE_BIT(0)
> +#define FSI_MRESP0_RESET_PORT_ERROR BE_BIT(1)
> +#define FSI_MRESP0_RESET_ALL_BRIDGES_GENERAL BE_BIT(2)
> +#define FSI_MRESP0_RESET_ALL_PORTS_GENERAL BE_BIT(3)
> +#define FSI_MRESP0_RESET_MASTER BE_BIT(4)
> +#define FSI_MRESP0_RESET_PARITY_ERROR_LATCH BE_BIT(5)
> +
> +#define FSI_MRESB0 TO_REG(0x1d0)
> +#define FSI_MRESB0_RESET_GENERAL BE_BIT(0)
> +#define FSI_MRESB0_RESET_ERROR BE_BIT(1)
> +#define FSI_MRESB0_SET_DMA_SUSPEND BE_BIT(5)
> +#define FSI_MRESB0_CLEAR_DMA_SUSPEND BE_BIT(6)
> +#define FSI_MRESB0_SET_DELAY_MEASURE BE_BIT(7)
> +
> +#define FSI_MECTRL TO_REG(0x2e0)
> +#define FSI_MECTRL_TEST_PULSE BE_GENMASK(0, 7)
> +#define FSI_MECTRL_INHIBIT_PARITY_ERROR BE_GENMASK(8, 15)
> +#define FSI_MECTRL_ENABLE_OPB_ERR_ACK BE_BIT(16)
> +#define FSI_MECTRL_AUTO_TERMINATE BE_BIT(17)
> +#define FSI_MECTRL_PORT_ERROR_FREEZE BE_BIT(18)
> +
> +static uint64_t fsi_master_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + FSIMasterState *s = FSI_MASTER(opaque);
> +
> + trace_fsi_master_read(addr, size);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return 0;
> + }
> +
> + return s->regs[TO_REG(addr)];
> +}
> +
> +static void fsi_master_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + FSIMasterState *s = FSI_MASTER(opaque);
> +
> + trace_fsi_master_write(addr, size, data);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds write: %"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return;
> + }
> +
> + switch (TO_REG(addr)) {
> + case FSI_MENP0:
> + s->regs[FSI_MENP0] = data;
> + break;
> + case FSI_MENP32:
> + s->regs[FSI_MENP32] = data;
> + break;
> + case FSI_MSENP0:
> + s->regs[FSI_MENP0] |= data;
> + break;
> + case FSI_MSENP32:
> + s->regs[FSI_MENP32] |= data;
> + break;
> + case FSI_MCENP0:
> + s->regs[FSI_MENP0] &= ~data;
> + break;
> + case FSI_MCENP32:
> + s->regs[FSI_MENP32] &= ~data;
> + break;
> + case FSI_MRESP0:
> + /* Perform necessary resets leave register 0 to indicate no errors */
> + break;
> + case FSI_MRESB0:
> + if (data & FSI_MRESB0_RESET_GENERAL) {
> + device_cold_reset(DEVICE(opaque));
> + }
> + if (data & FSI_MRESB0_RESET_ERROR) {
> + /* FIXME: this seems dubious */
> + device_cold_reset(DEVICE(opaque));
> + }
> + break;
> + default:
> + s->regs[TO_REG(addr)] = data;
> + }
> +}
> +
> +static const struct MemoryRegionOps fsi_master_ops = {
> + .read = fsi_master_read,
> + .write = fsi_master_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void fsi_master_realize(DeviceState *dev, Error **errp)
> +{
> + FSIMasterState *s = FSI_MASTER(dev);
> + Error *err = NULL;
> +
> + qbus_init(&s->bus, sizeof(s->bus), TYPE_FSI_BUS, DEVICE(s), NULL);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_master_ops, s,
> + TYPE_FSI_MASTER, 0x10000000);
> + memory_region_init(&s->opb2fsi, OBJECT(s), "fsi.opb2fsi", 0x10000000);
> +
> + object_property_set_bool(OBJECT(&s->bus), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> +
> + memory_region_add_subregion(&s->opb2fsi, 0, &s->bus.slave.mr);
> +}
> +
> +static void fsi_master_reset(DeviceState *dev)
> +{
> + FSIMasterState *s = FSI_MASTER(dev);
> +
> + /* ASPEED default */
> + s->regs[FSI_MVER] = 0xe0050101;
> +}
> +
> +static void fsi_master_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->bus_type = TYPE_OP_BUS;
> + dc->desc = "FSI Master";
> + dc->realize = fsi_master_realize;
> + dc->reset = fsi_master_reset;
> +}
> +
> +static const TypeInfo fsi_master_info = {
> + .name = TYPE_FSI_MASTER,
> + .parent = TYPE_DEVICE,
> + .instance_size = sizeof(FSIMasterState),
> + .class_init = fsi_master_class_init,
> +};
> +
> +static void fsi_register_types(void)
> +{
> + type_register_static(&fsi_master_info);
> +}
> +
> +type_init(fsi_register_types);
> diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
> new file mode 100644
> index 0000000000..fbfb28a6fc
> --- /dev/null
> +++ b/hw/fsi/fsi.c
> @@ -0,0 +1,54 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface
> + */
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +
> +#include "hw/fsi/fsi.h"
> +#include "hw/fsi/cfam.h"
> +
> +static void fsi_bus_realize(BusState *bus, Error **errp)
> +{
> + FSIBus *s = FSI_BUS(bus);
> + Error *err = NULL;
> +
> + /* Note: Move it elsewhere when we add more CFAMs. */
> + object_property_set_bool(OBJECT(&s->slave), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + }
> +}
> +
> +static void fsi_bus_init(Object *o)
> +{
> + FSIBus *s = FSI_BUS(o);
> +
> + /* Note: Move it elsewhere when we add more CFAMs. */
> + object_initialize_child(o, TYPE_CFAM, &s->slave, TYPE_CFAM);
> + qdev_set_parent_bus(DEVICE(&s->slave), BUS(o), &error_abort);
This should be moved elsewhere, in fsi_master_realize() I beleive.
Thanks,
C.
> +}
> +
> +static void fsi_bus_class_init(ObjectClass *klass, void *data)
> +{
> + BusClass *bc = BUS_CLASS(klass);
> + bc->realize = fsi_bus_realize;
> +}
> +
> +static const TypeInfo fsi_bus_info = {
> + .name = TYPE_FSI_BUS,
> + .parent = TYPE_BUS,
> + .instance_init = fsi_bus_init,
> + .instance_size = sizeof(FSIBus),
> + .class_init = fsi_bus_class_init,
> +};
> +
> +static void fsi_bus_register_types(void)
> +{
> + type_register_static(&fsi_bus_info);
> +}
> +
> +type_init(fsi_bus_register_types);
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index a9e7cd4099..f617943b4a 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -1,4 +1,4 @@
> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
> system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
> -system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi.c','fsi-master.c','fsi-slave.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index 752a5683a0..d7afef0460 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -7,3 +7,5 @@ cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRI
> cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-11 15:13 ` [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
@ 2023-10-19 8:00 ` Cédric Le Goater
2023-10-21 20:33 ` Ninad Palsule
2023-10-19 8:26 ` Daniel P. Berrangé
2023-10-19 17:28 ` Cédric Le Goater
2 siblings, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 8:00 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The Common FRU Access Macro (CFAM), an address space containing
> various "engines" that drive accesses on busses internal and external
> to the POWER chip. Examples include the SBEFIFO and I2C masters. The
> engines hang off of an internal Local Bus (LBUS) which is described
> by the CFAM configuration block.
>
> The FSI slave: The slave is the terminal point of the FSI bus for
> FSI symbols addressed to it. Slaves can be cascaded off of one
> another. The slave's configuration registers appear in address space
> of the CFAM to which it is attached.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v3:
> - Incorporated Thomas Huth's review comments.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/cfam.h | 58 ++++++++++
> include/hw/fsi/fsi-slave.h | 29 +++++
> hw/fsi/cfam.c | 220 +++++++++++++++++++++++++++++++++++++
> hw/fsi/fsi-slave.c | 96 ++++++++++++++++
> hw/fsi/Kconfig | 9 ++
> hw/fsi/meson.build | 2 +
> hw/fsi/trace-events | 7 ++
> 7 files changed, 421 insertions(+)
> create mode 100644 include/hw/fsi/cfam.h
> create mode 100644 include/hw/fsi/fsi-slave.h
> create mode 100644 hw/fsi/cfam.c
> create mode 100644 hw/fsi/fsi-slave.c
>
> diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
> new file mode 100644
> index 0000000000..a828fd931e
> --- /dev/null
> +++ b/include/hw/fsi/cfam.h
> @@ -0,0 +1,58 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Common FRU Access Macro
> + */
> +#ifndef FSI_CFAM_H
> +#define FSI_CFAM_H
> +
> +#include "exec/memory.h"
> +
> +#include "hw/fsi/fsi-slave.h"
> +#include "hw/fsi/lbus.h"
> +
> +#define TYPE_CFAM "cfam"
> +#define CFAM(obj) OBJECT_CHECK(CFAMState, (obj), TYPE_CFAM)
> +
> +#define CFAM_NR_REGS ((0x2e0 >> 2) + 1)
> +
> +#define TYPE_CFAM_CONFIG "cfam.config"
> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMConfig, CFAM_CONFIG)
> +
> +/* P9-ism */
> +#define CFAM_CONFIG_NR_REGS 0x28
> +
> +typedef struct CFAMState CFAMState;
> +
> +/* TODO: Generalise this accommodate different CFAM configurations */
> +typedef struct CFAMConfig {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> +} CFAMConfig;
> +
> +#define TYPE_CFAM_PEEK "cfam.peek"
> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMPeek, CFAM_PEEK)
> +#define CFAM_PEEK_NR_REGS ((0x130 >> 2) + 1)
> +
> +typedef struct CFAMPeek {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> +} CFAMPeek;
> +
> +struct CFAMState {
> + /* < private > */
> + FSISlaveState parent;
> +
> + MemoryRegion mr;
> + AddressSpace as;
> +
> + CFAMConfig config;
> + CFAMPeek peek;
> +
> + FSILBus lbus;
> +};
> +
> +#endif /* FSI_CFAM_H */
> diff --git a/include/hw/fsi/fsi-slave.h b/include/hw/fsi/fsi-slave.h
> new file mode 100644
> index 0000000000..f5f23f4457
> --- /dev/null
> +++ b/include/hw/fsi/fsi-slave.h
> @@ -0,0 +1,29 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface slave
> + */
> +#ifndef FSI_FSI_SLAVE_H
> +#define FSI_FSI_SLAVE_H
> +
> +#include "exec/memory.h"
> +#include "hw/qdev-core.h"
> +
> +#include "hw/fsi/lbus.h"
> +
> +#include <stdint.h>
> +
> +#define TYPE_FSI_SLAVE "fsi.slave"
> +OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
> +
> +#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
> +
> +typedef struct FSISlaveState {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> + uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
> +} FSISlaveState;
> +
> +#endif /* FSI_FSI_H */
> diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
> new file mode 100644
> index 0000000000..9044cc741b
> --- /dev/null
> +++ b/hw/fsi/cfam.c
> @@ -0,0 +1,220 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Common FRU Access Macro
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/bits.h"
> +#include "hw/fsi/cfam.h"
> +#include "hw/fsi/engine-scratchpad.h"
> +
> +#include "hw/qdev-properties.h"
> +
> +#define TO_REG(x) ((x) >> 2)
> +
> +#define CFAM_ENGINE_CONFIG TO_REG(0x04)
> +
> +#define CFAM_CONFIG_CHIP_ID TO_REG(0x00)
> +#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
> +#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000
> +
> +static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + CFAMConfig *config;
> + CFAMState *cfam;
> + FSILBusNode *node;
> + int i;
> +
> + config = CFAM_CONFIG(opaque);
> + cfam = container_of(config, CFAMState, config);
> +
> + trace_cfam_config_read(addr, size);
> +
> + switch (addr) {
> + case 0x00:
> + return CFAM_CONFIG_CHIP_ID_P9;
> + case 0x04:
> + return ENGINE_CONFIG_NEXT
> + | 0x00010000 /* slots */
> + | 0x00001000 /* version */
> + | ENGINE_CONFIG_TYPE_PEEK /* type */
> + | 0x0000000c; /* crc */
> + case 0x08:
> + return ENGINE_CONFIG_NEXT
> + | 0x00010000 /* slots */
> + | 0x00005000 /* version */
> + | ENGINE_CONFIG_TYPE_FSI /* type */
> + | 0x0000000a; /* crc */
> + break;
> + default:
> + /* FIXME: Improve this */
> + i = 0xc;
> + QLIST_FOREACH(node, &cfam->lbus.devices, next) {
> + if (i == addr) {
> + return FSI_LBUS_DEVICE_GET_CLASS(node->ldev)->config;
> + }
> + i += size;
> + }
Please use qbus_walk_children() and drop the devices list.
> + if (i == addr) {
> + return 0;
> + }
> +
> + /*
> + * As per FSI specification, This is a magic value at address 0 of
> + * given FSI port. This causes FSI master to send BREAK command for
> + * initialization and recovery.
> + */
> + return CFAM_CONFIG_CHIP_ID_BREAK;
> + }
> +}
> +
> +static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + CFAMConfig *s = CFAM_CONFIG(opaque);
> +
> + trace_cfam_config_write(addr, size, data);
> +
> + switch (TO_REG(addr)) {
> + case CFAM_CONFIG_CHIP_ID:
> + case CFAM_CONFIG_CHIP_ID + 4:
> + if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
> + bus_cold_reset(qdev_get_parent_bus(DEVICE(s)));
> + }
> + break;
> + default:
> + trace_cfam_config_write_noaddr(addr, size, data);
> + }
> +}
> +
> +static const struct MemoryRegionOps cfam_config_ops = {
> + .read = cfam_config_read,
> + .write = cfam_config_write,
> + .valid.max_access_size = 4,
> + .valid.min_access_size = 4,
> + .impl.max_access_size = 4,
> + .impl.min_access_size = 4,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void cfam_config_realize(DeviceState *dev, Error **errp)
> +{
> + CFAMConfig *s = CFAM_CONFIG(dev);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &cfam_config_ops, s,
> + TYPE_CFAM_CONFIG, 0x400);
> +}
> +
> +static void cfam_config_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->bus_type = TYPE_FSI_LBUS;
> + dc->realize = cfam_config_realize;
> +}
> +
> +static const TypeInfo cfam_config_info = {
> + .name = TYPE_CFAM_CONFIG,
> + .parent = TYPE_DEVICE,
> + .instance_size = sizeof(CFAMConfig),
> + .class_init = cfam_config_class_init,
> +};
Please drop the TYPE_CFAM_CONFIG object and move the config MMIO
under the CFAM object. It will simplify the model.
> +
> +static uint64_t cfam_unimplemented_read(void *opaque, hwaddr addr,
> + unsigned size)
> +{
> + trace_cfam_unimplemented_read(addr, size);
> +
> + return 0;
> +}
> +
> +static void cfam_unimplemented_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + trace_cfam_unimplemented_write(addr, size, data);
> +}
> +
> +static const struct MemoryRegionOps cfam_unimplemented_ops = {
> + .read = cfam_unimplemented_read,
> + .write = cfam_unimplemented_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
Is it possible to use create_unimplemented_device() ?
> +static void cfam_realize(DeviceState *dev, Error **errp)
> +{
> + CFAMState *cfam = CFAM(dev);
> + FSISlaveState *slave = FSI_SLAVE(dev);
> + Error *err = NULL;
> +
> + /* Each slave has a 2MiB address space */
> + memory_region_init_io(&cfam->mr, OBJECT(cfam), &cfam_unimplemented_ops,
> + cfam, TYPE_CFAM, 2 * 1024 * 1024);
> + address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
> +
> + qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
> + DEVICE(cfam), NULL);
> +
> + lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
> +
> + object_property_set_bool(OBJECT(&cfam->config), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> + qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus), &error_abort);
> +
> + object_property_set_bool(OBJECT(&cfam->lbus), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> +
> + memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
> + /* memory_region_add_subregion(&cfam->mr, 0x800, &cfam->lbus.peek.iomem); */
> + memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
> + memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
> +}
> +
> +static void cfam_init(Object *o)
> +{
> + CFAMState *s = CFAM(o);
> +
> + object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config, TYPE_CFAM_CONFIG);
> +}
> +
> +static void cfam_finalize(Object *o)
> +{
> + CFAMState *s = CFAM(o);
> +
> + address_space_destroy(&s->as);
> +}
finalize only really needed for hotpluggable devices.
> +
> +static void cfam_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->bus_type = TYPE_FSI_BUS;
> + dc->realize = cfam_realize;
> +}
> +
> +static const TypeInfo cfam_info = {
> + .name = TYPE_CFAM,
> + .parent = TYPE_FSI_SLAVE,
> + .instance_init = cfam_init,
> + .instance_finalize = cfam_finalize,
> + .instance_size = sizeof(CFAMState),
> + .class_init = cfam_class_init,
> +};
> +
> +static void cfam_register_types(void)
> +{
> + type_register_static(&cfam_config_info);
> + type_register_static(&cfam_info);
> +}
> +
> +type_init(cfam_register_types);
> diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
> new file mode 100644
> index 0000000000..127fdd8a4f
> --- /dev/null
> +++ b/hw/fsi/fsi-slave.c
> @@ -0,0 +1,96 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface slave
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qemu/bitops.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/fsi-slave.h"
> +
> +#define TO_REG(x) ((x) >> 2)
> +
> +#define FSI_SMODE TO_REG(0x00)
> +#define FSI_SMODE_WSTART BE_BIT(0)
> +#define FSI_SMODE_AUX_EN BE_BIT(1)
> +#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
> +#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
> +#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
> +#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
> +#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
> +#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
> +
> +#define FSI_SDMA TO_REG(0x04)
> +#define FSI_SISC TO_REG(0x08)
> +#define FSI_SCISC TO_REG(0x08)
> +#define FSI_SISM TO_REG(0x0c)
> +#define FSI_SISS TO_REG(0x10)
> +#define FSI_SSISM TO_REG(0x10)
> +#define FSI_SCISM TO_REG(0x14)
> +
> +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + FSISlaveState *s = FSI_SLAVE(opaque);
> +
> + trace_fsi_slave_read(addr, size);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return 0;
> + }
> +
> + return s->regs[TO_REG(addr)];
> +}
> +
> +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + FSISlaveState *s = FSI_SLAVE(opaque);
> +
> + trace_fsi_slave_write(addr, size, data);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return;
> + }
> +
> + s->regs[TO_REG(addr)] = data;
> +}
> +
> +static const struct MemoryRegionOps fsi_slave_ops = {
> + .read = fsi_slave_read,
> + .write = fsi_slave_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void fsi_slave_init(Object *o)
> +{
> + FSISlaveState *s = FSI_SLAVE(o);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
> + s, TYPE_FSI_SLAVE, 0x400);
> +}
> +
> +static const TypeInfo fsi_slave_info = {
> + .name = TYPE_FSI_SLAVE,
> + .parent = TYPE_DEVICE,
> + .instance_init = fsi_slave_init,
> + .instance_size = sizeof(FSISlaveState),
> +};
> +
> +static void fsi_slave_register_types(void)
> +{
> + type_register_static(&fsi_slave_info);
> +}
> +
> +type_init(fsi_slave_register_types);
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> index f7c7fd1b28..8d712e77ed 100644
> --- a/hw/fsi/Kconfig
> +++ b/hw/fsi/Kconfig
> @@ -1,3 +1,12 @@
> +config FSI_CFAM
> + bool
> + select FSI
> + select FSI_SCRATCHPAD
> + select FSI_LBUS
> +
> +config FSI
> + bool
> +
> config FSI_SCRATCHPAD
> bool
> select FSI_LBUS
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index d45a98c223..a9e7cd4099 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -1,2 +1,4 @@
> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
> +system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index 97fd070354..752a5683a0 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -1,2 +1,9 @@
> scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +cfam_config_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
@ 2023-10-19 8:03 ` Cédric Le Goater
2023-10-21 20:20 ` Ninad Palsule
2023-10-19 8:08 ` Cédric Le Goater
2023-10-19 8:14 ` Daniel P. Berrangé
2 siblings, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 8:03 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The LBUS is modelled to maintain the qdev bus hierarchy and to take
> advantage of the object model to automatically generate the CFAM
> configuration block. The configuration block presents engines in the
> order they are attached to the CFAM's LBUS. Engine implementations
> should subclass the LBusDevice and set the 'config' member of
> LBusDeviceClass to match the engine's type.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
> include/qemu/bitops.h | 6 +++
> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
> hw/Kconfig | 1 +
> hw/fsi/Kconfig | 2 +
> hw/fsi/meson.build | 1 +
> hw/meson.build | 1 +
> 7 files changed, 149 insertions(+)
> create mode 100644 include/hw/fsi/lbus.h
> create mode 100644 hw/fsi/lbus.c
> create mode 100644 hw/fsi/Kconfig
> create mode 100644 hw/fsi/meson.build
>
> diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
> new file mode 100644
> index 0000000000..408fe25831
> --- /dev/null
> +++ b/include/hw/fsi/lbus.h
> @@ -0,0 +1,51 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Local bus and connected device structures.
> + */
> +#ifndef FSI_LBUS_H
> +#define FSI_LBUS_H
> +
> +#include "exec/memory.h"
> +#include "hw/qdev-core.h"
> +
> +#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
> +OBJECT_DECLARE_TYPE(FSILBusDevice, FSILBusDeviceClass, FSI_LBUS_DEVICE)
> +
> +#define FSI_LBUS_MEM_REGION_SIZE (2 * 1024 * 1024)
> +#define FSI_LBUSDEV_IOMEM_SIZE 0x400
> +
> +typedef struct FSILBusDevice {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> + uint32_t address;
> +} FSILBusDevice;
> +
> +typedef struct FSILBusDeviceClass {
> + DeviceClass parent;
> +
> + uint32_t config;
> +} FSILBusDeviceClass;
> +
> +typedef struct FSILBusNode {
> + FSILBusDevice *ldev;
> +
> + QLIST_ENTRY(FSILBusNode) next;
> +} FSILBusNode;
> +
> +#define TYPE_FSI_LBUS "fsi.lbus"
> +OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
> +
> +typedef struct FSILBus {
> + BusState bus;
> +
> + MemoryRegion mr;
> +
> + QLIST_HEAD(, FSILBusNode) devices;
> +} FSILBus;
> +
> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr);
> +int lbus_add_device(FSILBus *bus, FSILBusDevice *dev);
> +#endif /* FSI_LBUS_H */
> diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
> index cb3526d1f4..e12496f619 100644
> --- a/include/qemu/bitops.h
> +++ b/include/qemu/bitops.h
> @@ -618,4 +618,10 @@ static inline uint64_t half_unshuffle64(uint64_t x)
> return x;
> }
>
> +/* Bitwise operations at the word level. */
> +#define BE_BIT(x) BIT(31 - (x))
> +#define GENMASK(t, b) \
> + (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
> +#define BE_GENMASK(t, b) GENMASK(BE_BIT(t), BE_BIT(b))
> +
> #endif
> diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
> new file mode 100644
> index 0000000000..d7117d1299
> --- /dev/null
> +++ b/hw/fsi/lbus.c
> @@ -0,0 +1,87 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Local bus where FSI slaves are connected
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/fsi/lbus.h"
> +
> +#include "hw/qdev-properties.h"
> +
> +static void lbus_realize(BusState *bus, Error **errp)
> +{
> + FSILBusNode *node;
> + FSILBus *lbus = FSI_LBUS(bus);
> +
> + memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_FSI_LBUS,
> + FSI_LBUS_MEM_REGION_SIZE - FSI_LBUSDEV_IOMEM_SIZE);
the region init should be done in an init handler (this to avoid the realize
of the bus)
> +
> + QLIST_FOREACH(node, &lbus->devices, next) {
> + memory_region_add_subregion(&lbus->mr, node->ldev->address,
> + &node->ldev->iomem);
This is redudant with what is done in cfam_realize() and please
remove this list, also redudant with the bus list.
Thanks,
C.
> + }
> +}
> +
> +static void lbus_class_init(ObjectClass *klass, void *data)
> +{
> + BusClass *k = BUS_CLASS(klass);
> + k->realize = lbus_realize;
> +}
> +
> +static const TypeInfo lbus_info = {
> + .name = TYPE_FSI_LBUS,
> + .parent = TYPE_BUS,
> + .instance_size = sizeof(FSILBus),
> + .class_init = lbus_class_init,
> +};
> +
> +static Property lbus_device_props[] = {
> + DEFINE_PROP_UINT32("address", FSILBusDevice, address, 0),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
> +{
> + DeviceState *dev;
> + FSILBusNode *node;
> + BusState *state = BUS(bus);
> +
> + dev = qdev_new(type);
> + qdev_prop_set_uint8(dev, "address", addr);
> + qdev_realize_and_unref(dev, state, &error_fatal);
> +
> + /* Move to post_load */
> + node = g_malloc(sizeof(struct FSILBusNode));
> + node->ldev = FSI_LBUS_DEVICE(dev);
> + QLIST_INSERT_HEAD(&bus->devices, node, next);
> +
> + return dev;
> +}
> +
> +static void lbus_device_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->bus_type = TYPE_FSI_LBUS;
> + device_class_set_props(dc, lbus_device_props);
> +}
> +
> +static const TypeInfo lbus_device_type_info = {
> + .name = TYPE_FSI_LBUS_DEVICE,
> + .parent = TYPE_DEVICE,
> + .instance_size = sizeof(FSILBusDevice),
> + .abstract = true,
> + .class_init = lbus_device_class_init,
> + .class_size = sizeof(FSILBusDeviceClass),
> +};
> +
> +static void lbus_register_types(void)
> +{
> + type_register_static(&lbus_info);
> + type_register_static(&lbus_device_type_info);
> +}
> +
> +type_init(lbus_register_types);
> diff --git a/hw/Kconfig b/hw/Kconfig
> index ba62ff6417..2ccb73add5 100644
> --- a/hw/Kconfig
> +++ b/hw/Kconfig
> @@ -9,6 +9,7 @@ source core/Kconfig
> source cxl/Kconfig
> source display/Kconfig
> source dma/Kconfig
> +source fsi/Kconfig
> source gpio/Kconfig
> source hyperv/Kconfig
> source i2c/Kconfig
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> new file mode 100644
> index 0000000000..e650c660f0
> --- /dev/null
> +++ b/hw/fsi/Kconfig
> @@ -0,0 +1,2 @@
> +config FSI_LBUS
> + bool
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> new file mode 100644
> index 0000000000..4074d3a7d2
> --- /dev/null
> +++ b/hw/fsi/meson.build
> @@ -0,0 +1 @@
> +system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> diff --git a/hw/meson.build b/hw/meson.build
> index c7ac7d3d75..6c71ee9cfa 100644
> --- a/hw/meson.build
> +++ b/hw/meson.build
> @@ -43,6 +43,7 @@ subdir('virtio')
> subdir('watchdog')
> subdir('xen')
> subdir('xenpv')
> +subdir('fsi')
>
> subdir('alpha')
> subdir('arm')
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
2023-10-19 8:03 ` Cédric Le Goater
@ 2023-10-19 8:08 ` Cédric Le Goater
2023-10-21 20:21 ` Ninad Palsule
2023-10-19 8:14 ` Daniel P. Berrangé
2 siblings, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 8:08 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The LBUS is modelled to maintain the qdev bus hierarchy and to take
> advantage of the object model to automatically generate the CFAM
> configuration block. The configuration block presents engines in the
> order they are attached to the CFAM's LBUS. Engine implementations
> should subclass the LBusDevice and set the 'config' member of
> LBusDeviceClass to match the engine's type.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
> include/qemu/bitops.h | 6 +++
> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
> hw/Kconfig | 1 +
> hw/fsi/Kconfig | 2 +
> hw/fsi/meson.build | 1 +
> hw/meson.build | 1 +
> 7 files changed, 149 insertions(+)
> create mode 100644 include/hw/fsi/lbus.h
> create mode 100644 hw/fsi/lbus.c
> create mode 100644 hw/fsi/Kconfig
> create mode 100644 hw/fsi/meson.build
>
> diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
> new file mode 100644
> index 0000000000..408fe25831
> --- /dev/null
> +++ b/include/hw/fsi/lbus.h
> @@ -0,0 +1,51 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Local bus and connected device structures.
> + */
> +#ifndef FSI_LBUS_H
> +#define FSI_LBUS_H
> +
> +#include "exec/memory.h"
> +#include "hw/qdev-core.h"
> +
> +#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
> +OBJECT_DECLARE_TYPE(FSILBusDevice, FSILBusDeviceClass, FSI_LBUS_DEVICE)
> +
> +#define FSI_LBUS_MEM_REGION_SIZE (2 * 1024 * 1024)
> +#define FSI_LBUSDEV_IOMEM_SIZE 0x400
> +
> +typedef struct FSILBusDevice {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> + uint32_t address;
> +} FSILBusDevice;
> +
> +typedef struct FSILBusDeviceClass {
> + DeviceClass parent;
> +
> + uint32_t config;
> +} FSILBusDeviceClass;
> +
> +typedef struct FSILBusNode {
> + FSILBusDevice *ldev;
> +
> + QLIST_ENTRY(FSILBusNode) next;
> +} FSILBusNode;
> +
> +#define TYPE_FSI_LBUS "fsi.lbus"
> +OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
> +
> +typedef struct FSILBus {
> + BusState bus;
> +
> + MemoryRegion mr;
> +
> + QLIST_HEAD(, FSILBusNode) devices;
> +} FSILBus;
> +
> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr);
> +int lbus_add_device(FSILBus *bus, FSILBusDevice *dev);
> +#endif /* FSI_LBUS_H */
> diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
> index cb3526d1f4..e12496f619 100644
> --- a/include/qemu/bitops.h
> +++ b/include/qemu/bitops.h
> @@ -618,4 +618,10 @@ static inline uint64_t half_unshuffle64(uint64_t x)
> return x;
> }
>
> +/* Bitwise operations at the word level. */
> +#define BE_BIT(x) BIT(31 - (x))
> +#define GENMASK(t, b) \
> + (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
> +#define BE_GENMASK(t, b) GENMASK(BE_BIT(t), BE_BIT(b))
> +
> #endif
Oh I forgot. please remove this change above.
Thanks,
C.
> diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
> new file mode 100644
> index 0000000000..d7117d1299
> --- /dev/null
> +++ b/hw/fsi/lbus.c
> @@ -0,0 +1,87 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Local bus where FSI slaves are connected
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/fsi/lbus.h"
> +
> +#include "hw/qdev-properties.h"
> +
> +static void lbus_realize(BusState *bus, Error **errp)
> +{
> + FSILBusNode *node;
> + FSILBus *lbus = FSI_LBUS(bus);
> +
> + memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_FSI_LBUS,
> + FSI_LBUS_MEM_REGION_SIZE - FSI_LBUSDEV_IOMEM_SIZE);
> +
> + QLIST_FOREACH(node, &lbus->devices, next) {
> + memory_region_add_subregion(&lbus->mr, node->ldev->address,
> + &node->ldev->iomem);
> + }
> +}
> +
> +static void lbus_class_init(ObjectClass *klass, void *data)
> +{
> + BusClass *k = BUS_CLASS(klass);
> + k->realize = lbus_realize;
> +}
> +
> +static const TypeInfo lbus_info = {
> + .name = TYPE_FSI_LBUS,
> + .parent = TYPE_BUS,
> + .instance_size = sizeof(FSILBus),
> + .class_init = lbus_class_init,
> +};
> +
> +static Property lbus_device_props[] = {
> + DEFINE_PROP_UINT32("address", FSILBusDevice, address, 0),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
> +{
> + DeviceState *dev;
> + FSILBusNode *node;
> + BusState *state = BUS(bus);
> +
> + dev = qdev_new(type);
> + qdev_prop_set_uint8(dev, "address", addr);
> + qdev_realize_and_unref(dev, state, &error_fatal);
> +
> + /* Move to post_load */
> + node = g_malloc(sizeof(struct FSILBusNode));
> + node->ldev = FSI_LBUS_DEVICE(dev);
> + QLIST_INSERT_HEAD(&bus->devices, node, next);
> +
> + return dev;
> +}
> +
> +static void lbus_device_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> +
> + dc->bus_type = TYPE_FSI_LBUS;
> + device_class_set_props(dc, lbus_device_props);
> +}
> +
> +static const TypeInfo lbus_device_type_info = {
> + .name = TYPE_FSI_LBUS_DEVICE,
> + .parent = TYPE_DEVICE,
> + .instance_size = sizeof(FSILBusDevice),
> + .abstract = true,
> + .class_init = lbus_device_class_init,
> + .class_size = sizeof(FSILBusDeviceClass),
> +};
> +
> +static void lbus_register_types(void)
> +{
> + type_register_static(&lbus_info);
> + type_register_static(&lbus_device_type_info);
> +}
> +
> +type_init(lbus_register_types);
> diff --git a/hw/Kconfig b/hw/Kconfig
> index ba62ff6417..2ccb73add5 100644
> --- a/hw/Kconfig
> +++ b/hw/Kconfig
> @@ -9,6 +9,7 @@ source core/Kconfig
> source cxl/Kconfig
> source display/Kconfig
> source dma/Kconfig
> +source fsi/Kconfig
> source gpio/Kconfig
> source hyperv/Kconfig
> source i2c/Kconfig
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> new file mode 100644
> index 0000000000..e650c660f0
> --- /dev/null
> +++ b/hw/fsi/Kconfig
> @@ -0,0 +1,2 @@
> +config FSI_LBUS
> + bool
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> new file mode 100644
> index 0000000000..4074d3a7d2
> --- /dev/null
> +++ b/hw/fsi/meson.build
> @@ -0,0 +1 @@
> +system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> diff --git a/hw/meson.build b/hw/meson.build
> index c7ac7d3d75..6c71ee9cfa 100644
> --- a/hw/meson.build
> +++ b/hw/meson.build
> @@ -43,6 +43,7 @@ subdir('virtio')
> subdir('watchdog')
> subdir('xen')
> subdir('xenpv')
> +subdir('fsi')
>
> subdir('alpha')
> subdir('arm')
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
2023-10-19 8:03 ` Cédric Le Goater
2023-10-19 8:08 ` Cédric Le Goater
@ 2023-10-19 8:14 ` Daniel P. Berrangé
2023-10-19 15:34 ` Ninad Palsule
2 siblings, 1 reply; 41+ messages in thread
From: Daniel P. Berrangé @ 2023-10-19 8:14 UTC (permalink / raw
To: Ninad Palsule
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
On Wed, Oct 11, 2023 at 10:13:30AM -0500, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The LBUS is modelled to maintain the qdev bus hierarchy and to take
> advantage of the object model to automatically generate the CFAM
> configuration block. The configuration block presents engines in the
> order they are attached to the CFAM's LBUS. Engine implementations
> should subclass the LBusDevice and set the 'config' member of
> LBusDeviceClass to match the engine's type.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
> include/qemu/bitops.h | 6 +++
> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
> hw/Kconfig | 1 +
> hw/fsi/Kconfig | 2 +
> hw/fsi/meson.build | 1 +
> hw/meson.build | 1 +
> 7 files changed, 149 insertions(+)
> create mode 100644 include/hw/fsi/lbus.h
> create mode 100644 hw/fsi/lbus.c
> create mode 100644 hw/fsi/Kconfig
> create mode 100644 hw/fsi/meson.build
> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
> +{
> + DeviceState *dev;
> + FSILBusNode *node;
> + BusState *state = BUS(bus);
> +
> + dev = qdev_new(type);
> + qdev_prop_set_uint8(dev, "address", addr);
> + qdev_realize_and_unref(dev, state, &error_fatal);
> +
> + /* Move to post_load */
> + node = g_malloc(sizeof(struct FSILBusNode));
This allocation pattern is discouraged in favour of:
node = g_new0(FSILBusNode, 1);
> + node->ldev = FSI_LBUS_DEVICE(dev);
> + QLIST_INSERT_HEAD(&bus->devices, node, next);
> +
> + return dev;
> +}
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 00/10] Introduce model for IBM's FSI
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
` (9 preceding siblings ...)
2023-10-11 15:13 ` [PATCH v5 10/10] hw/fsi: Update MAINTAINER list Ninad Palsule
@ 2023-10-19 8:16 ` Cédric Le Goater
2023-10-21 20:45 ` Ninad Palsule
10 siblings, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 8:16 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Ninad,
On 10/11/23 17:13, Ninad Palsule wrote:
> Hello,
>
> Please review the patch-set version 5.
> I have incorporated review comments from Cedric.
>
> Ninad Palsule (10):
> hw/fsi: Introduce IBM's Local bus
> hw/fsi: Introduce IBM's scratchpad
> hw/fsi: Introduce IBM's cfam,fsi-slave
> hw/fsi: Introduce IBM's FSI
> hw/fsi: IBM's On-chip Peripheral Bus
> hw/fsi: Aspeed APB2OPB interface
> hw/arm: Hook up FSI module in AST2600
> hw/fsi: Added qtest
> hw/fsi: Added FSI documentation
> hw/fsi: Update MAINTAINER list
I made some comments, mostly on the bus models which need to be reworked.
This is code reshuffling and it should simplify the models. Please consider
reducing the amount of files.
Also, could please remove my Sob ? I didn't write any of this, only did
quick fixes over the years because I kept the series in my aspeed tree.
And this would help me to add a Rb :)
I expect one or two respins before merge. 8.2 freeze window is in less
than 3 weeks. It could make it, else the next. No big issue since I think
we have been dragging these models for at least 5/6 years.
Thanks,
C.
>
> MAINTAINERS | 8 +
> docs/specs/fsi.rst | 141 ++++++++++++
> meson.build | 1 +
> hw/fsi/trace.h | 1 +
> include/hw/arm/aspeed_soc.h | 4 +
> include/hw/fsi/aspeed-apb2opb.h | 33 +++
> include/hw/fsi/cfam.h | 58 +++++
> include/hw/fsi/engine-scratchpad.h | 33 +++
> include/hw/fsi/fsi-master.h | 30 +++
> include/hw/fsi/fsi-slave.h | 29 +++
> include/hw/fsi/fsi.h | 37 +++
> include/hw/fsi/lbus.h | 51 +++++
> include/hw/fsi/opb.h | 43 ++++
> include/qemu/bitops.h | 6 +
> hw/arm/aspeed_ast2600.c | 19 ++
> hw/fsi/aspeed-apb2opb.c | 350 +++++++++++++++++++++++++++++
> hw/fsi/cfam.c | 220 ++++++++++++++++++
> hw/fsi/engine-scratchpad.c | 99 ++++++++
> hw/fsi/fsi-master.c | 198 ++++++++++++++++
> hw/fsi/fsi-slave.c | 96 ++++++++
> hw/fsi/fsi.c | 54 +++++
> hw/fsi/lbus.c | 87 +++++++
> hw/fsi/opb.c | 185 +++++++++++++++
> tests/qtest/fsi-test.c | 210 +++++++++++++++++
> hw/Kconfig | 1 +
> hw/arm/Kconfig | 1 +
> hw/fsi/Kconfig | 23 ++
> hw/fsi/meson.build | 6 +
> hw/fsi/trace-events | 15 ++
> hw/meson.build | 1 +
> tests/qtest/meson.build | 2 +
> 31 files changed, 2042 insertions(+)
> create mode 100644 docs/specs/fsi.rst
> create mode 100644 hw/fsi/trace.h
> create mode 100644 include/hw/fsi/aspeed-apb2opb.h
> create mode 100644 include/hw/fsi/cfam.h
> create mode 100644 include/hw/fsi/engine-scratchpad.h
> create mode 100644 include/hw/fsi/fsi-master.h
> create mode 100644 include/hw/fsi/fsi-slave.h
> create mode 100644 include/hw/fsi/fsi.h
> create mode 100644 include/hw/fsi/lbus.h
> create mode 100644 include/hw/fsi/opb.h
> create mode 100644 hw/fsi/aspeed-apb2opb.c
> create mode 100644 hw/fsi/cfam.c
> create mode 100644 hw/fsi/engine-scratchpad.c
> create mode 100644 hw/fsi/fsi-master.c
> create mode 100644 hw/fsi/fsi-slave.c
> create mode 100644 hw/fsi/fsi.c
> create mode 100644 hw/fsi/lbus.c
> create mode 100644 hw/fsi/opb.c
> create mode 100644 tests/qtest/fsi-test.c
> create mode 100644 hw/fsi/Kconfig
> create mode 100644 hw/fsi/meson.build
> create mode 100644 hw/fsi/trace-events
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad
2023-10-11 15:13 ` [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad Ninad Palsule
@ 2023-10-19 8:20 ` Daniel P. Berrangé
2023-10-21 20:27 ` Ninad Palsule
0 siblings, 1 reply; 41+ messages in thread
From: Daniel P. Berrangé @ 2023-10-19 8:20 UTC (permalink / raw
To: Ninad Palsule
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
On Wed, Oct 11, 2023 at 10:13:31AM -0500, Ninad Palsule wrote:
> This is a part of patchset where scratchpad is introduced.
>
> The scratchpad provides a set of non-functional registers. The firmware
> is free to use them, hardware does not support any special management
> support. The scratchpad registers can be read or written from LBUS
> slave.
>
> In this model, The LBUS device is parent for the scratchpad.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/engine-scratchpad.h | 33 ++++++++++
> hw/fsi/engine-scratchpad.c | 99 ++++++++++++++++++++++++++++++
> hw/fsi/Kconfig | 4 ++
> hw/fsi/meson.build | 1 +
> hw/fsi/trace-events | 2 +
> 5 files changed, 139 insertions(+)
> create mode 100644 include/hw/fsi/engine-scratchpad.h
> create mode 100644 hw/fsi/engine-scratchpad.c
> create mode 100644 hw/fsi/trace-events
>
> diff --git a/include/hw/fsi/engine-scratchpad.h b/include/hw/fsi/engine-scratchpad.h
> new file mode 100644
> index 0000000000..17e9570c5c
> --- /dev/null
> +++ b/include/hw/fsi/engine-scratchpad.h
> @@ -0,0 +1,33 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM scratchpad engne
> + */
> +#ifndef FSI_ENGINE_SCRATCHPAD_H
> +#define FSI_ENGINE_SCRATCHPAD_H
> +
> +#include "qemu/bitops.h"
> +
> +#include "hw/fsi/lbus.h"
> +
> +#define ENGINE_CONFIG_NEXT BE_BIT(0)
> +#define ENGINE_CONFIG_VPD BE_BIT(1)
> +#define ENGINE_CONFIG_SLOTS BE_GENMASK(8, 15)
> +#define ENGINE_CONFIG_VERSION BE_GENMASK(16, 19)
> +#define ENGINE_CONFIG_TYPE BE_GENMASK(20, 27)
> +#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4)
> +#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4)
> +#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4)
> +#define ENGINE_CONFIG_CRC BE_GENMASK(28, 31)
> +
> +#define TYPE_SCRATCHPAD "scratchpad"
> +#define SCRATCHPAD(obj) OBJECT_CHECK(ScratchPad, (obj), TYPE_SCRATCHPAD)
> +
> +typedef struct ScratchPad {
> + FSILBusDevice parent;
> +
> + uint32_t reg;
> +} ScratchPad;
> +
> +#endif /* FSI_ENGINE_SCRATCHPAD_H */
> diff --git a/hw/fsi/engine-scratchpad.c b/hw/fsi/engine-scratchpad.c
> new file mode 100644
> index 0000000000..60f678eec4
> --- /dev/null
> +++ b/hw/fsi/engine-scratchpad.c
> @@ -0,0 +1,99 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM scratchpad engine
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/engine-scratchpad.h"
> +
> +static uint64_t scratchpad_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + ScratchPad *s = SCRATCHPAD(opaque);
> +
> + trace_scratchpad_read(addr, size);
> +
> + if (addr) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
We already have a trace point in the line above. I don't think we should
be unconditionally logging errors like this, as this becomes a guest
triggerable denial of service on the host log collector for the guest.
eg it could flood the logfile connected to stderr with unlimited data
by repeatedly doing bad reads/writes.
> + return 0;
> + }
> +
> + return s->reg;
> +}
> +
> +static void scratchpad_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + ScratchPad *s = SCRATCHPAD(opaque);
> +
> + trace_scratchpad_write(addr, size, data);
> +
> + if (addr) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return;
> + }
> +
> + s->reg = data;
> +}
> +
> +static const struct MemoryRegionOps scratchpad_ops = {
> + .read = scratchpad_read,
> + .write = scratchpad_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void scratchpad_realize(DeviceState *dev, Error **errp)
> +{
> + FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev);
> +
> + memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops,
> + ldev, TYPE_SCRATCHPAD, 0x400);
> +}
> +
> +static void scratchpad_reset(DeviceState *dev)
> +{
> + ScratchPad *s = SCRATCHPAD(dev);
> +
> + s->reg = 0;
> +}
> +
> +static void scratchpad_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + FSILBusDeviceClass *ldc = FSI_LBUS_DEVICE_CLASS(klass);
> +
> + dc->realize = scratchpad_realize;
> + dc->reset = scratchpad_reset;
> +
> + ldc->config =
> + ENGINE_CONFIG_NEXT /* valid */
> + | 0x00010000 /* slots */
> + | 0x00001000 /* version */
> + | ENGINE_CONFIG_TYPE_SCRATCHPAD /* type */
> + | 0x00000007; /* crc */
More common QEMU style would be for the "|" to be on the end
of line rather than start.
End of line:
$ git grep '.*\s|\s*$' "*.c" | wc -l
5381
Start of line:
$ git grep '^\s*|\s.*' "*.c" | wc -l
581
> +}
> +
> +static const TypeInfo scratchpad_info = {
> + .name = TYPE_SCRATCHPAD,
> + .parent = TYPE_FSI_LBUS_DEVICE,
> + .instance_size = sizeof(ScratchPad),
> + .class_init = scratchpad_class_init,
> + .class_size = sizeof(FSILBusDeviceClass),
> +};
> +
> +static void scratchpad_register_types(void)
> +{
> + type_register_static(&scratchpad_info);
> +}
> +
> +type_init(scratchpad_register_types);
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> index e650c660f0..f7c7fd1b28 100644
> --- a/hw/fsi/Kconfig
> +++ b/hw/fsi/Kconfig
> @@ -1,2 +1,6 @@
> +config FSI_SCRATCHPAD
> + bool
> + select FSI_LBUS
> +
> config FSI_LBUS
> bool
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index 4074d3a7d2..d45a98c223 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -1 +1,2 @@
> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> +system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> new file mode 100644
> index 0000000000..97fd070354
> --- /dev/null
> +++ b/hw/fsi/trace-events
> @@ -0,0 +1,2 @@
> +scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> --
> 2.39.2
>
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-11 15:13 ` [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
2023-10-19 8:00 ` Cédric Le Goater
@ 2023-10-19 8:26 ` Daniel P. Berrangé
2023-10-21 20:34 ` Ninad Palsule
2023-10-19 17:28 ` Cédric Le Goater
2 siblings, 1 reply; 41+ messages in thread
From: Daniel P. Berrangé @ 2023-10-19 8:26 UTC (permalink / raw
To: Ninad Palsule
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
On Wed, Oct 11, 2023 at 10:13:32AM -0500, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The Common FRU Access Macro (CFAM), an address space containing
> various "engines" that drive accesses on busses internal and external
> to the POWER chip. Examples include the SBEFIFO and I2C masters. The
> engines hang off of an internal Local Bus (LBUS) which is described
> by the CFAM configuration block.
>
> The FSI slave: The slave is the terminal point of the FSI bus for
> FSI symbols addressed to it. Slaves can be cascaded off of one
> another. The slave's configuration registers appear in address space
> of the CFAM to which it is attached.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v3:
> - Incorporated Thomas Huth's review comments.
> v5:
> - Incorporated review comments by Cedric.
> +static void cfam_realize(DeviceState *dev, Error **errp)
> +{
> + CFAMState *cfam = CFAM(dev);
> + FSISlaveState *slave = FSI_SLAVE(dev);
> + Error *err = NULL;
> +
> + /* Each slave has a 2MiB address space */
> + memory_region_init_io(&cfam->mr, OBJECT(cfam), &cfam_unimplemented_ops,
> + cfam, TYPE_CFAM, 2 * 1024 * 1024);
> + address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
> +
> + qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
> + DEVICE(cfam), NULL);
> +
> + lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
> +
> + object_property_set_bool(OBJECT(&cfam->config), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
object_property_set_bool returns false on error so this use of a local
Error object is redundant.
if (!object_property_set_bool(..., &errp)) {
return;
}
If a local Error had been required though, this code should have instead
been using ERRP_GUARD - see include/qapi/error.h docs for illustration
for future work.
> + qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus), &error_abort);
> +
> + object_property_set_bool(OBJECT(&cfam->lbus), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
Likewise
> +
> + memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
> + /* memory_region_add_subregion(&cfam->mr, 0x800, &cfam->lbus.peek.iomem); */
> + memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
> + memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
> +}
> +
> +static void cfam_init(Object *o)
> +{
> + CFAMState *s = CFAM(o);
> +
> + object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config, TYPE_CFAM_CONFIG);
> +}
> +
> +static void cfam_finalize(Object *o)
> +{
> + CFAMState *s = CFAM(o);
> +
> + address_space_destroy(&s->as);
> +}
> +
> +static void cfam_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->bus_type = TYPE_FSI_BUS;
> + dc->realize = cfam_realize;
> +}
> +
> +static const TypeInfo cfam_info = {
> + .name = TYPE_CFAM,
> + .parent = TYPE_FSI_SLAVE,
> + .instance_init = cfam_init,
> + .instance_finalize = cfam_finalize,
> + .instance_size = sizeof(CFAMState),
> + .class_init = cfam_class_init,
> +};
> +
> +static void cfam_register_types(void)
> +{
> + type_register_static(&cfam_config_info);
> + type_register_static(&cfam_info);
> +}
> +
> +type_init(cfam_register_types);
> diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
> new file mode 100644
> index 0000000000..127fdd8a4f
> --- /dev/null
> +++ b/hw/fsi/fsi-slave.c
> @@ -0,0 +1,96 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface slave
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qemu/bitops.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/fsi-slave.h"
> +
> +#define TO_REG(x) ((x) >> 2)
> +
> +#define FSI_SMODE TO_REG(0x00)
> +#define FSI_SMODE_WSTART BE_BIT(0)
> +#define FSI_SMODE_AUX_EN BE_BIT(1)
> +#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
> +#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
> +#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
> +#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
> +#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
> +#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
> +
> +#define FSI_SDMA TO_REG(0x04)
> +#define FSI_SISC TO_REG(0x08)
> +#define FSI_SCISC TO_REG(0x08)
> +#define FSI_SISM TO_REG(0x0c)
> +#define FSI_SISS TO_REG(0x10)
> +#define FSI_SSISM TO_REG(0x10)
> +#define FSI_SCISM TO_REG(0x14)
> +
> +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + FSISlaveState *s = FSI_SLAVE(opaque);
> +
> + trace_fsi_slave_read(addr, size);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return 0;
> + }
> +
> + return s->regs[TO_REG(addr)];
> +}
> +
> +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + FSISlaveState *s = FSI_SLAVE(opaque);
> +
> + trace_fsi_slave_write(addr, size, data);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return;
> + }
> +
> + s->regs[TO_REG(addr)] = data;
> +}
> +
> +static const struct MemoryRegionOps fsi_slave_ops = {
> + .read = fsi_slave_read,
> + .write = fsi_slave_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void fsi_slave_init(Object *o)
> +{
> + FSISlaveState *s = FSI_SLAVE(o);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
> + s, TYPE_FSI_SLAVE, 0x400);
> +}
> +
> +static const TypeInfo fsi_slave_info = {
> + .name = TYPE_FSI_SLAVE,
> + .parent = TYPE_DEVICE,
> + .instance_init = fsi_slave_init,
> + .instance_size = sizeof(FSISlaveState),
> +};
> +
> +static void fsi_slave_register_types(void)
> +{
> + type_register_static(&fsi_slave_info);
> +}
> +
> +type_init(fsi_slave_register_types);
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> index f7c7fd1b28..8d712e77ed 100644
> --- a/hw/fsi/Kconfig
> +++ b/hw/fsi/Kconfig
> @@ -1,3 +1,12 @@
> +config FSI_CFAM
> + bool
> + select FSI
> + select FSI_SCRATCHPAD
> + select FSI_LBUS
> +
> +config FSI
> + bool
> +
> config FSI_SCRATCHPAD
> bool
> select FSI_LBUS
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index d45a98c223..a9e7cd4099 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -1,2 +1,4 @@
> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
> +system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index 97fd070354..752a5683a0 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -1,2 +1,9 @@
> scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +cfam_config_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> --
> 2.39.2
>
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI
2023-10-11 15:13 ` [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI Ninad Palsule
2023-10-19 7:44 ` Cédric Le Goater
@ 2023-10-19 8:28 ` Daniel P. Berrangé
2023-10-21 20:37 ` Ninad Palsule
1 sibling, 1 reply; 41+ messages in thread
From: Daniel P. Berrangé @ 2023-10-19 8:28 UTC (permalink / raw
To: Ninad Palsule
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
On Wed, Oct 11, 2023 at 10:13:33AM -0500, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> This commit models the FSI bus. CFAM is hanging out of FSI bus. The bus
> is model such a way that it is embedded inside the FSI master which is a
> bus controller.
>
> The FSI master: A controller in the platform service processor (e.g.
> BMC) driving CFAM engine accesses into the POWER chip. At the
> hardware level FSI is a bit-based protocol supporting synchronous and
> DMA-driven accesses of engines in a CFAM.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
> v2:
> - Incorporated review comments by Joel
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/fsi-master.h | 30 ++++++
> include/hw/fsi/fsi.h | 37 +++++++
> hw/fsi/cfam.c | 2 +-
> hw/fsi/fsi-master.c | 199 ++++++++++++++++++++++++++++++++++++
> hw/fsi/fsi.c | 54 ++++++++++
> hw/fsi/meson.build | 2 +-
> hw/fsi/trace-events | 2 +
> 7 files changed, 324 insertions(+), 2 deletions(-)
> create mode 100644 include/hw/fsi/fsi-master.h
> create mode 100644 include/hw/fsi/fsi.h
> create mode 100644 hw/fsi/fsi-master.c
> create mode 100644 hw/fsi/fsi.c
>
> +static void fsi_master_realize(DeviceState *dev, Error **errp)
> +{
> + FSIMasterState *s = FSI_MASTER(dev);
> + Error *err = NULL;
> +
> + qbus_init(&s->bus, sizeof(s->bus), TYPE_FSI_BUS, DEVICE(s), NULL);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_master_ops, s,
> + TYPE_FSI_MASTER, 0x10000000);
> + memory_region_init(&s->opb2fsi, OBJECT(s), "fsi.opb2fsi", 0x10000000);
> +
> + object_property_set_bool(OBJECT(&s->bus), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
Redundant Error object, just check return value of set_bool
> +
> + memory_region_add_subregion(&s->opb2fsi, 0, &s->bus.slave.mr);
> +}
> +static void fsi_bus_realize(BusState *bus, Error **errp)
> +{
> + FSIBus *s = FSI_BUS(bus);
> + Error *err = NULL;
> +
> + /* Note: Move it elsewhere when we add more CFAMs. */
> + object_property_set_bool(OBJECT(&s->slave), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + }
Likewise.
> +}
> +
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus
2023-10-11 15:13 ` [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus Ninad Palsule
2023-10-19 7:26 ` Cédric Le Goater
@ 2023-10-19 8:30 ` Daniel P. Berrangé
2023-10-21 20:42 ` Ninad Palsule
1 sibling, 1 reply; 41+ messages in thread
From: Daniel P. Berrangé @ 2023-10-19 8:30 UTC (permalink / raw
To: Ninad Palsule
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
On Wed, Oct 11, 2023 at 10:13:34AM -0500, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
> POWER processors. This now makes an appearance in the ASPEED SoC due
> to tight integration of the FSI master IP with the OPB, mainly the
> existence of an MMIO-mapping of the CFAM address straight onto a
> sub-region of the OPB address space.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> ---
> v2:
> - Incorporated review comment by Joel.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/opb.h | 43 ++++++++++
> hw/fsi/fsi-master.c | 3 +-
> hw/fsi/opb.c | 185 +++++++++++++++++++++++++++++++++++++++++++
> hw/fsi/Kconfig | 4 +
> hw/fsi/meson.build | 1 +
> hw/fsi/trace-events | 2 +
> 6 files changed, 236 insertions(+), 2 deletions(-)
> create mode 100644 include/hw/fsi/opb.h
> create mode 100644 hw/fsi/opb.c
>
> diff --git a/include/hw/fsi/opb.h b/include/hw/fsi/opb.h
> new file mode 100644
> index 0000000000..f8ce00383e
> --- /dev/null
> +++ b/include/hw/fsi/opb.h
> @@ -0,0 +1,43 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM On-Chip Peripheral Bus
> + */
> +#ifndef FSI_OPB_H
> +#define FSI_OPB_H
> +
> +#include "exec/memory.h"
> +#include "hw/fsi/fsi-master.h"
> +
> +#define TYPE_OP_BUS "opb"
> +OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
> +
> +typedef struct OPBus {
> + /*< private >*/
> + BusState bus;
> +
> + /*< public >*/
> + MemoryRegion mr;
> + AddressSpace as;
> +
> + /* Model OPB as dumb enough just to provide an address-space */
> + /* TODO: Maybe don't store device state in the bus? */
> + FSIMasterState fsi;
> +} OPBus;
> +
> +typedef struct OPBusClass {
> + BusClass parent_class;
> +} OPBusClass;
> +
> +uint8_t opb_read8(OPBus *opb, hwaddr addr);
> +uint16_t opb_read16(OPBus *opb, hwaddr addr);
> +uint32_t opb_read32(OPBus *opb, hwaddr addr);
> +void opb_write8(OPBus *opb, hwaddr addr, uint8_t data);
> +void opb_write16(OPBus *opb, hwaddr addr, uint16_t data);
> +void opb_write32(OPBus *opb, hwaddr addr, uint32_t data);
> +
> +void opb_fsi_master_address(OPBus *opb, hwaddr addr);
> +void opb_opb2fsi_address(OPBus *opb, hwaddr addr);
> +
> +#endif /* FSI_OPB_H */
> diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
> index 8f4ae641c7..ede1a58e98 100644
> --- a/hw/fsi/fsi-master.c
> +++ b/hw/fsi/fsi-master.c
> @@ -11,8 +11,7 @@
> #include "trace.h"
>
> #include "hw/fsi/fsi-master.h"
> -
> -#define TYPE_OP_BUS "opb"
> +#include "hw/fsi/opb.h"
>
> #define TO_REG(x) ((x) >> 2)
>
> diff --git a/hw/fsi/opb.c b/hw/fsi/opb.c
> new file mode 100644
> index 0000000000..7ffd7730f7
> --- /dev/null
> +++ b/hw/fsi/opb.c
> @@ -0,0 +1,185 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM On-chip Peripheral Bus
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/opb.h"
> +
> +static MemTxResult opb_read(OPBus *opb, hwaddr addr, void *data, size_t len)
> +{
> + MemTxResult tx;
> + tx = address_space_read(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
> + len);
> + if (tx) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: OPB read failed: 0x%"HWADDR_PRIx" for %lu\n",
> + __func__, addr, len);
> + }
> + return tx;
> +}
Use a tracepoint rather than an always-on log
> +
> +uint8_t opb_read8(OPBus *opb, hwaddr addr)
> +{
> + uint8_t data = -1;
> +
> + (void)opb_read(opb, addr, &data, sizeof(data));
> +
> + return data;
> +}
> +
> +uint16_t opb_read16(OPBus *opb, hwaddr addr)
> +{
> + uint16_t data = -1;
> +
> + (void)opb_read(opb, addr, &data, sizeof(data));
> +
> + return data;
> +}
> +
> +uint32_t opb_read32(OPBus *opb, hwaddr addr)
> +{
> + uint32_t data = -1;
> +
> + (void)opb_read(opb, addr, &data, sizeof(data));
> +
> + return data;
> +}
> +
> +static void opb_write(OPBus *opb, hwaddr addr, void *data, size_t len)
> +{
> + MemTxResult tx;
> + tx = address_space_write(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
> + len);
> + if (tx) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: OPB write failed: %"HWADDR_PRIx" for %lu\n",
> + __func__, addr, len);
> + }
> +}
Again tracepoint
> +static void opb_realize(BusState *bus, Error **errp)
> +{
> + OPBus *opb = OP_BUS(bus);
> + Error *err = NULL;
> +
> + memory_region_init_io(&opb->mr, OBJECT(opb), &opb_unimplemented_ops, opb,
> + NULL, UINT32_MAX);
> + address_space_init(&opb->as, &opb->mr, "opb");
> +
> + object_property_set_bool(OBJECT(&opb->fsi), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
Redundant local error object
> + memory_region_add_subregion(&opb->mr, 0x80000000, &opb->fsi.iomem);
> +
> + /* OPB2FSI region */
> + /*
> + * Avoid endianness issues by mapping each slave's memory region directly.
> + * Manually bridging multiple address-spaces causes endian swapping
> + * headaches as memory_region_dispatch_read() and
> + * memory_region_dispatch_write() correct the endianness based on the
> + * target machine endianness and not relative to the device endianness on
> + * either side of the bridge.
> + */
> + /*
> + * XXX: This is a bit hairy and will need to be fixed when I sort out the
> + * bus/slave relationship and any changes to the CFAM modelling (multiple
> + * slaves, LBUS)
> + */
> + memory_region_add_subregion(&opb->mr, 0xa0000000, &opb->fsi.opb2fsi);
> +}
> +
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index d7afef0460..ec9bab2fe8 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -9,3 +9,5 @@ fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
Please consistently use an 'fsi_' prefix for all trace points, as it
makes it possible to enable all tracing for this subsystem using a
wildcard match
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-19 8:14 ` Daniel P. Berrangé
@ 2023-10-19 15:34 ` Ninad Palsule
2023-10-19 16:09 ` Daniel P. Berrangé
0 siblings, 1 reply; 41+ messages in thread
From: Ninad Palsule @ 2023-10-19 15:34 UTC (permalink / raw
To: Daniel P. Berrangé
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
Hello Daniel,
On 10/19/23 03:14, Daniel P. Berrangé wrote:
> On Wed, Oct 11, 2023 at 10:13:30AM -0500, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The LBUS is modelled to maintain the qdev bus hierarchy and to take
>> advantage of the object model to automatically generate the CFAM
>> configuration block. The configuration block presents engines in the
>> order they are attached to the CFAM's LBUS. Engine implementations
>> should subclass the LBusDevice and set the 'config' member of
>> LBusDeviceClass to match the engine's type.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
>> include/qemu/bitops.h | 6 +++
>> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
>> hw/Kconfig | 1 +
>> hw/fsi/Kconfig | 2 +
>> hw/fsi/meson.build | 1 +
>> hw/meson.build | 1 +
>> 7 files changed, 149 insertions(+)
>> create mode 100644 include/hw/fsi/lbus.h
>> create mode 100644 hw/fsi/lbus.c
>> create mode 100644 hw/fsi/Kconfig
>> create mode 100644 hw/fsi/meson.build
>> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
>> +{
>> + DeviceState *dev;
>> + FSILBusNode *node;
>> + BusState *state = BUS(bus);
>> +
>> + dev = qdev_new(type);
>> + qdev_prop_set_uint8(dev, "address", addr);
>> + qdev_realize_and_unref(dev, state, &error_fatal);
>> +
>> + /* Move to post_load */
>> + node = g_malloc(sizeof(struct FSILBusNode));
> This allocation pattern is discouraged in favour of:
>
> node = g_new0(FSILBusNode, 1);
I am using g_malloc() because I want program to terminate. I don't think
g_new0 provide this functionality. Please let me know.
Thanks for the review!
~Ninad
>> + node->ldev = FSI_LBUS_DEVICE(dev);
>> + QLIST_INSERT_HEAD(&bus->devices, node, next);
>> +
>> + return dev;
>> +}
> With regards,
> Daniel
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-19 15:34 ` Ninad Palsule
@ 2023-10-19 16:09 ` Daniel P. Berrangé
2023-10-21 20:22 ` Ninad Palsule
0 siblings, 1 reply; 41+ messages in thread
From: Daniel P. Berrangé @ 2023-10-19 16:09 UTC (permalink / raw
To: Ninad Palsule
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
On Thu, Oct 19, 2023 at 10:34:52AM -0500, Ninad Palsule wrote:
> Hello Daniel,
>
> On 10/19/23 03:14, Daniel P. Berrangé wrote:
> > On Wed, Oct 11, 2023 at 10:13:30AM -0500, Ninad Palsule wrote:
> > > This is a part of patchset where IBM's Flexible Service Interface is
> > > introduced.
> > >
> > > The LBUS is modelled to maintain the qdev bus hierarchy and to take
> > > advantage of the object model to automatically generate the CFAM
> > > configuration block. The configuration block presents engines in the
> > > order they are attached to the CFAM's LBUS. Engine implementations
> > > should subclass the LBusDevice and set the 'config' member of
> > > LBusDeviceClass to match the engine's type.
> > >
> > > Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> > > Signed-off-by: Cédric Le Goater <clg@kaod.org>
> > > Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> > > ---
> > > v2:
> > > - Incorporated Joel's review comments.
> > > v5:
> > > - Incorporated review comments by Cedric.
> > > ---
> > > include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
> > > include/qemu/bitops.h | 6 +++
> > > hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
> > > hw/Kconfig | 1 +
> > > hw/fsi/Kconfig | 2 +
> > > hw/fsi/meson.build | 1 +
> > > hw/meson.build | 1 +
> > > 7 files changed, 149 insertions(+)
> > > create mode 100644 include/hw/fsi/lbus.h
> > > create mode 100644 hw/fsi/lbus.c
> > > create mode 100644 hw/fsi/Kconfig
> > > create mode 100644 hw/fsi/meson.build
> > > +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
> > > +{
> > > + DeviceState *dev;
> > > + FSILBusNode *node;
> > > + BusState *state = BUS(bus);
> > > +
> > > + dev = qdev_new(type);
> > > + qdev_prop_set_uint8(dev, "address", addr);
> > > + qdev_realize_and_unref(dev, state, &error_fatal);
> > > +
> > > + /* Move to post_load */
> > > + node = g_malloc(sizeof(struct FSILBusNode));
> > This allocation pattern is discouraged in favour of:
> >
> > node = g_new0(FSILBusNode, 1);
>
> I am using g_malloc() because I want program to terminate. I don't think
> g_new0 provide this functionality. Please let me know.
All the glib memory allocation functions terminate on OOM, except
for the ones with '_try_' in their name.
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-11 15:13 ` [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
2023-10-19 8:00 ` Cédric Le Goater
2023-10-19 8:26 ` Daniel P. Berrangé
@ 2023-10-19 17:28 ` Cédric Le Goater
2023-10-21 20:35 ` Ninad Palsule
2 siblings, 1 reply; 41+ messages in thread
From: Cédric Le Goater @ 2023-10-19 17:28 UTC (permalink / raw
To: Ninad Palsule, qemu-devel, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
On 10/11/23 17:13, Ninad Palsule wrote:
> This is a part of patchset where IBM's Flexible Service Interface is
> introduced.
>
> The Common FRU Access Macro (CFAM), an address space containing
> various "engines" that drive accesses on busses internal and external
> to the POWER chip. Examples include the SBEFIFO and I2C masters. The
> engines hang off of an internal Local Bus (LBUS) which is described
> by the CFAM configuration block.
>
> The FSI slave: The slave is the terminal point of the FSI bus for
> FSI symbols addressed to it. Slaves can be cascaded off of one
> another. The slave's configuration registers appear in address space
> of the CFAM to which it is attached.
>
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
> v2:
> - Incorporated Joel's review comments.
> v3:
> - Incorporated Thomas Huth's review comments.
> v5:
> - Incorporated review comments by Cedric.
> ---
> include/hw/fsi/cfam.h | 58 ++++++++++
> include/hw/fsi/fsi-slave.h | 29 +++++
> hw/fsi/cfam.c | 220 +++++++++++++++++++++++++++++++++++++
> hw/fsi/fsi-slave.c | 96 ++++++++++++++++
> hw/fsi/Kconfig | 9 ++
> hw/fsi/meson.build | 2 +
> hw/fsi/trace-events | 7 ++
> 7 files changed, 421 insertions(+)
> create mode 100644 include/hw/fsi/cfam.h
> create mode 100644 include/hw/fsi/fsi-slave.h
> create mode 100644 hw/fsi/cfam.c
> create mode 100644 hw/fsi/fsi-slave.c
>
> diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
> new file mode 100644
> index 0000000000..a828fd931e
> --- /dev/null
> +++ b/include/hw/fsi/cfam.h
> @@ -0,0 +1,58 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Common FRU Access Macro
> + */
> +#ifndef FSI_CFAM_H
> +#define FSI_CFAM_H
> +
> +#include "exec/memory.h"
> +
> +#include "hw/fsi/fsi-slave.h"
> +#include "hw/fsi/lbus.h"
> +
> +#define TYPE_CFAM "cfam"
> +#define CFAM(obj) OBJECT_CHECK(CFAMState, (obj), TYPE_CFAM)
> +
> +#define CFAM_NR_REGS ((0x2e0 >> 2) + 1)
> +
> +#define TYPE_CFAM_CONFIG "cfam.config"
> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMConfig, CFAM_CONFIG)
> +
> +/* P9-ism */
> +#define CFAM_CONFIG_NR_REGS 0x28
> +
> +typedef struct CFAMState CFAMState;
> +
> +/* TODO: Generalise this accommodate different CFAM configurations */
> +typedef struct CFAMConfig {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> +} CFAMConfig;
> +
> +#define TYPE_CFAM_PEEK "cfam.peek"
> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMPeek, CFAM_PEEK)
> +#define CFAM_PEEK_NR_REGS ((0x130 >> 2) + 1)
> +
> +typedef struct CFAMPeek {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> +} CFAMPeek;
Ninad,
I don't see the CFAMPeek model being used anywhere. Please drop.
Thanks,
C.
> +
> +struct CFAMState {
> + /* < private > */
> + FSISlaveState parent;
> +
> + MemoryRegion mr;
> + AddressSpace as;
> +
> + CFAMConfig config;
> + CFAMPeek peek;
> +
> + FSILBus lbus;
> +};
> +
> +#endif /* FSI_CFAM_H */
> diff --git a/include/hw/fsi/fsi-slave.h b/include/hw/fsi/fsi-slave.h
> new file mode 100644
> index 0000000000..f5f23f4457
> --- /dev/null
> +++ b/include/hw/fsi/fsi-slave.h
> @@ -0,0 +1,29 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface slave
> + */
> +#ifndef FSI_FSI_SLAVE_H
> +#define FSI_FSI_SLAVE_H
> +
> +#include "exec/memory.h"
> +#include "hw/qdev-core.h"
> +
> +#include "hw/fsi/lbus.h"
> +
> +#include <stdint.h>
> +
> +#define TYPE_FSI_SLAVE "fsi.slave"
> +OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
> +
> +#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
> +
> +typedef struct FSISlaveState {
> + DeviceState parent;
> +
> + MemoryRegion iomem;
> + uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
> +} FSISlaveState;
> +
> +#endif /* FSI_FSI_H */
> diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
> new file mode 100644
> index 0000000000..9044cc741b
> --- /dev/null
> +++ b/hw/fsi/cfam.c
> @@ -0,0 +1,220 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Common FRU Access Macro
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qapi/error.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/bits.h"
> +#include "hw/fsi/cfam.h"
> +#include "hw/fsi/engine-scratchpad.h"
> +
> +#include "hw/qdev-properties.h"
> +
> +#define TO_REG(x) ((x) >> 2)
> +
> +#define CFAM_ENGINE_CONFIG TO_REG(0x04)
> +
> +#define CFAM_CONFIG_CHIP_ID TO_REG(0x00)
> +#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
> +#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000
> +
> +static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + CFAMConfig *config;
> + CFAMState *cfam;
> + FSILBusNode *node;
> + int i;
> +
> + config = CFAM_CONFIG(opaque);
> + cfam = container_of(config, CFAMState, config);
> +
> + trace_cfam_config_read(addr, size);
> +
> + switch (addr) {
> + case 0x00:
> + return CFAM_CONFIG_CHIP_ID_P9;
> + case 0x04:
> + return ENGINE_CONFIG_NEXT
> + | 0x00010000 /* slots */
> + | 0x00001000 /* version */
> + | ENGINE_CONFIG_TYPE_PEEK /* type */
> + | 0x0000000c; /* crc */
> + case 0x08:
> + return ENGINE_CONFIG_NEXT
> + | 0x00010000 /* slots */
> + | 0x00005000 /* version */
> + | ENGINE_CONFIG_TYPE_FSI /* type */
> + | 0x0000000a; /* crc */
> + break;
> + default:
> + /* FIXME: Improve this */
> + i = 0xc;
> + QLIST_FOREACH(node, &cfam->lbus.devices, next) {
> + if (i == addr) {
> + return FSI_LBUS_DEVICE_GET_CLASS(node->ldev)->config;
> + }
> + i += size;
> + }
> +
> + if (i == addr) {
> + return 0;
> + }
> +
> + /*
> + * As per FSI specification, This is a magic value at address 0 of
> + * given FSI port. This causes FSI master to send BREAK command for
> + * initialization and recovery.
> + */
> + return CFAM_CONFIG_CHIP_ID_BREAK;
> + }
> +}
> +
> +static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + CFAMConfig *s = CFAM_CONFIG(opaque);
> +
> + trace_cfam_config_write(addr, size, data);
> +
> + switch (TO_REG(addr)) {
> + case CFAM_CONFIG_CHIP_ID:
> + case CFAM_CONFIG_CHIP_ID + 4:
> + if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
> + bus_cold_reset(qdev_get_parent_bus(DEVICE(s)));
> + }
> + break;
> + default:
> + trace_cfam_config_write_noaddr(addr, size, data);
> + }
> +}
> +
> +static const struct MemoryRegionOps cfam_config_ops = {
> + .read = cfam_config_read,
> + .write = cfam_config_write,
> + .valid.max_access_size = 4,
> + .valid.min_access_size = 4,
> + .impl.max_access_size = 4,
> + .impl.min_access_size = 4,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void cfam_config_realize(DeviceState *dev, Error **errp)
> +{
> + CFAMConfig *s = CFAM_CONFIG(dev);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &cfam_config_ops, s,
> + TYPE_CFAM_CONFIG, 0x400);
> +}
> +
> +static void cfam_config_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->bus_type = TYPE_FSI_LBUS;
> + dc->realize = cfam_config_realize;
> +}
> +
> +static const TypeInfo cfam_config_info = {
> + .name = TYPE_CFAM_CONFIG,
> + .parent = TYPE_DEVICE,
> + .instance_size = sizeof(CFAMConfig),
> + .class_init = cfam_config_class_init,
> +};
> +
> +static uint64_t cfam_unimplemented_read(void *opaque, hwaddr addr,
> + unsigned size)
> +{
> + trace_cfam_unimplemented_read(addr, size);
> +
> + return 0;
> +}
> +
> +static void cfam_unimplemented_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + trace_cfam_unimplemented_write(addr, size, data);
> +}
> +
> +static const struct MemoryRegionOps cfam_unimplemented_ops = {
> + .read = cfam_unimplemented_read,
> + .write = cfam_unimplemented_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void cfam_realize(DeviceState *dev, Error **errp)
> +{
> + CFAMState *cfam = CFAM(dev);
> + FSISlaveState *slave = FSI_SLAVE(dev);
> + Error *err = NULL;
> +
> + /* Each slave has a 2MiB address space */
> + memory_region_init_io(&cfam->mr, OBJECT(cfam), &cfam_unimplemented_ops,
> + cfam, TYPE_CFAM, 2 * 1024 * 1024);
> + address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
> +
> + qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
> + DEVICE(cfam), NULL);
> +
> + lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
> +
> + object_property_set_bool(OBJECT(&cfam->config), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> + qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus), &error_abort);
> +
> + object_property_set_bool(OBJECT(&cfam->lbus), "realized", true, &err);
> + if (err) {
> + error_propagate(errp, err);
> + return;
> + }
> +
> + memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
> + /* memory_region_add_subregion(&cfam->mr, 0x800, &cfam->lbus.peek.iomem); */
> + memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
> + memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
> +}
> +
> +static void cfam_init(Object *o)
> +{
> + CFAMState *s = CFAM(o);
> +
> + object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config, TYPE_CFAM_CONFIG);
> +}
> +
> +static void cfam_finalize(Object *o)
> +{
> + CFAMState *s = CFAM(o);
> +
> + address_space_destroy(&s->as);
> +}
> +
> +static void cfam_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + dc->bus_type = TYPE_FSI_BUS;
> + dc->realize = cfam_realize;
> +}
> +
> +static const TypeInfo cfam_info = {
> + .name = TYPE_CFAM,
> + .parent = TYPE_FSI_SLAVE,
> + .instance_init = cfam_init,
> + .instance_finalize = cfam_finalize,
> + .instance_size = sizeof(CFAMState),
> + .class_init = cfam_class_init,
> +};
> +
> +static void cfam_register_types(void)
> +{
> + type_register_static(&cfam_config_info);
> + type_register_static(&cfam_info);
> +}
> +
> +type_init(cfam_register_types);
> diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
> new file mode 100644
> index 0000000000..127fdd8a4f
> --- /dev/null
> +++ b/hw/fsi/fsi-slave.c
> @@ -0,0 +1,96 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Copyright (C) 2023 IBM Corp.
> + *
> + * IBM Flexible Service Interface slave
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qemu/bitops.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "trace.h"
> +
> +#include "hw/fsi/fsi-slave.h"
> +
> +#define TO_REG(x) ((x) >> 2)
> +
> +#define FSI_SMODE TO_REG(0x00)
> +#define FSI_SMODE_WSTART BE_BIT(0)
> +#define FSI_SMODE_AUX_EN BE_BIT(1)
> +#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
> +#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
> +#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
> +#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
> +#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
> +#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
> +
> +#define FSI_SDMA TO_REG(0x04)
> +#define FSI_SISC TO_REG(0x08)
> +#define FSI_SCISC TO_REG(0x08)
> +#define FSI_SISM TO_REG(0x0c)
> +#define FSI_SISS TO_REG(0x10)
> +#define FSI_SSISM TO_REG(0x10)
> +#define FSI_SCISM TO_REG(0x14)
> +
> +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + FSISlaveState *s = FSI_SLAVE(opaque);
> +
> + trace_fsi_slave_read(addr, size);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return 0;
> + }
> +
> + return s->regs[TO_REG(addr)];
> +}
> +
> +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
> + unsigned size)
> +{
> + FSISlaveState *s = FSI_SLAVE(opaque);
> +
> + trace_fsi_slave_write(addr, size, data);
> +
> + if (addr + size > sizeof(s->regs)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
> + __func__, addr, size);
> + return;
> + }
> +
> + s->regs[TO_REG(addr)] = data;
> +}
> +
> +static const struct MemoryRegionOps fsi_slave_ops = {
> + .read = fsi_slave_read,
> + .write = fsi_slave_write,
> + .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void fsi_slave_init(Object *o)
> +{
> + FSISlaveState *s = FSI_SLAVE(o);
> +
> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
> + s, TYPE_FSI_SLAVE, 0x400);
> +}
> +
> +static const TypeInfo fsi_slave_info = {
> + .name = TYPE_FSI_SLAVE,
> + .parent = TYPE_DEVICE,
> + .instance_init = fsi_slave_init,
> + .instance_size = sizeof(FSISlaveState),
> +};
> +
> +static void fsi_slave_register_types(void)
> +{
> + type_register_static(&fsi_slave_info);
> +}
> +
> +type_init(fsi_slave_register_types);
> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
> index f7c7fd1b28..8d712e77ed 100644
> --- a/hw/fsi/Kconfig
> +++ b/hw/fsi/Kconfig
> @@ -1,3 +1,12 @@
> +config FSI_CFAM
> + bool
> + select FSI
> + select FSI_SCRATCHPAD
> + select FSI_LBUS
> +
> +config FSI
> + bool
> +
> config FSI_SCRATCHPAD
> bool
> select FSI_LBUS
> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
> index d45a98c223..a9e7cd4099 100644
> --- a/hw/fsi/meson.build
> +++ b/hw/fsi/meson.build
> @@ -1,2 +1,4 @@
> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
> +system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
> index 97fd070354..752a5683a0 100644
> --- a/hw/fsi/trace-events
> +++ b/hw/fsi/trace-events
> @@ -1,2 +1,9 @@
> scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +cfam_config_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
> +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-19 8:03 ` Cédric Le Goater
@ 2023-10-21 20:20 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:20 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 03:03, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The LBUS is modelled to maintain the qdev bus hierarchy and to take
>> advantage of the object model to automatically generate the CFAM
>> configuration block. The configuration block presents engines in the
>> order they are attached to the CFAM's LBUS. Engine implementations
>> should subclass the LBusDevice and set the 'config' member of
>> LBusDeviceClass to match the engine's type.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
>> include/qemu/bitops.h | 6 +++
>> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
>> hw/Kconfig | 1 +
>> hw/fsi/Kconfig | 2 +
>> hw/fsi/meson.build | 1 +
>> hw/meson.build | 1 +
>> 7 files changed, 149 insertions(+)
>> create mode 100644 include/hw/fsi/lbus.h
>> create mode 100644 hw/fsi/lbus.c
>> create mode 100644 hw/fsi/Kconfig
>> create mode 100644 hw/fsi/meson.build
>>
>> diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
>> new file mode 100644
>> index 0000000000..408fe25831
>> --- /dev/null
>> +++ b/include/hw/fsi/lbus.h
>> @@ -0,0 +1,51 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Local bus and connected device structures.
>> + */
>> +#ifndef FSI_LBUS_H
>> +#define FSI_LBUS_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/qdev-core.h"
>> +
>> +#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
>> +OBJECT_DECLARE_TYPE(FSILBusDevice, FSILBusDeviceClass, FSI_LBUS_DEVICE)
>> +
>> +#define FSI_LBUS_MEM_REGION_SIZE (2 * 1024 * 1024)
>> +#define FSI_LBUSDEV_IOMEM_SIZE 0x400
>> +
>> +typedef struct FSILBusDevice {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> + uint32_t address;
>> +} FSILBusDevice;
>> +
>> +typedef struct FSILBusDeviceClass {
>> + DeviceClass parent;
>> +
>> + uint32_t config;
>> +} FSILBusDeviceClass;
>> +
>> +typedef struct FSILBusNode {
>> + FSILBusDevice *ldev;
>> +
>> + QLIST_ENTRY(FSILBusNode) next;
>> +} FSILBusNode;
>> +
>> +#define TYPE_FSI_LBUS "fsi.lbus"
>> +OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
>> +
>> +typedef struct FSILBus {
>> + BusState bus;
>> +
>> + MemoryRegion mr;
>> +
>> + QLIST_HEAD(, FSILBusNode) devices;
>> +} FSILBus;
>> +
>> +DeviceState *lbus_create_device(FSILBus *bus, const char *type,
>> uint32_t addr);
>> +int lbus_add_device(FSILBus *bus, FSILBusDevice *dev);
>> +#endif /* FSI_LBUS_H */
>> diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
>> index cb3526d1f4..e12496f619 100644
>> --- a/include/qemu/bitops.h
>> +++ b/include/qemu/bitops.h
>> @@ -618,4 +618,10 @@ static inline uint64_t half_unshuffle64(uint64_t x)
>> return x;
>> }
>> +/* Bitwise operations at the word level. */
>> +#define BE_BIT(x) BIT(31 - (x))
>> +#define GENMASK(t, b) \
>> + (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
>> +#define BE_GENMASK(t, b) GENMASK(BE_BIT(t),
>> BE_BIT(b))
>> +
>> #endif
>> diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
>> new file mode 100644
>> index 0000000000..d7117d1299
>> --- /dev/null
>> +++ b/hw/fsi/lbus.c
>> @@ -0,0 +1,87 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Local bus where FSI slaves are connected
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "hw/fsi/lbus.h"
>> +
>> +#include "hw/qdev-properties.h"
>> +
>> +static void lbus_realize(BusState *bus, Error **errp)
>> +{
>> + FSILBusNode *node;
>> + FSILBus *lbus = FSI_LBUS(bus);
>> +
>> + memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_FSI_LBUS,
>> + FSI_LBUS_MEM_REGION_SIZE -
>> FSI_LBUSDEV_IOMEM_SIZE);
>
> the region init should be done in an init handler (this to avoid the
> realize
> of the bus)
Fixed.
>
>> +
>> + QLIST_FOREACH(node, &lbus->devices, next) {
>> + memory_region_add_subregion(&lbus->mr, node->ldev->address,
>> + &node->ldev->iomem);
>
> This is redudant with what is done in cfam_realize() and please
> remove this list, also redudant with the bus list.
Removed the list and used the children. Removed the lbus_realize() function.
Thanks for the review.
~Ninad
>
> Thanks,
>
> C.
>
>> + }
>> +}
>> +
>> +static void lbus_class_init(ObjectClass *klass, void *data)
>> +{
>> + BusClass *k = BUS_CLASS(klass);
>> + k->realize = lbus_realize;
>> +}
>> +
>> +static const TypeInfo lbus_info = {
>> + .name = TYPE_FSI_LBUS,
>> + .parent = TYPE_BUS,
>> + .instance_size = sizeof(FSILBus),
>> + .class_init = lbus_class_init,
>> +};
>> +
>> +static Property lbus_device_props[] = {
>> + DEFINE_PROP_UINT32("address", FSILBusDevice, address, 0),
>> + DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +DeviceState *lbus_create_device(FSILBus *bus, const char *type,
>> uint32_t addr)
>> +{
>> + DeviceState *dev;
>> + FSILBusNode *node;
>> + BusState *state = BUS(bus);
>> +
>> + dev = qdev_new(type);
>> + qdev_prop_set_uint8(dev, "address", addr);
>> + qdev_realize_and_unref(dev, state, &error_fatal);
>> +
>> + /* Move to post_load */
>> + node = g_malloc(sizeof(struct FSILBusNode));
>> + node->ldev = FSI_LBUS_DEVICE(dev);
>> + QLIST_INSERT_HEAD(&bus->devices, node, next);
>> +
>> + return dev;
>> +}
>> +
>> +static void lbus_device_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> + dc->bus_type = TYPE_FSI_LBUS;
>> + device_class_set_props(dc, lbus_device_props);
>> +}
>> +
>> +static const TypeInfo lbus_device_type_info = {
>> + .name = TYPE_FSI_LBUS_DEVICE,
>> + .parent = TYPE_DEVICE,
>> + .instance_size = sizeof(FSILBusDevice),
>> + .abstract = true,
>> + .class_init = lbus_device_class_init,
>> + .class_size = sizeof(FSILBusDeviceClass),
>> +};
>> +
>> +static void lbus_register_types(void)
>> +{
>> + type_register_static(&lbus_info);
>> + type_register_static(&lbus_device_type_info);
>> +}
>> +
>> +type_init(lbus_register_types);
>> diff --git a/hw/Kconfig b/hw/Kconfig
>> index ba62ff6417..2ccb73add5 100644
>> --- a/hw/Kconfig
>> +++ b/hw/Kconfig
>> @@ -9,6 +9,7 @@ source core/Kconfig
>> source cxl/Kconfig
>> source display/Kconfig
>> source dma/Kconfig
>> +source fsi/Kconfig
>> source gpio/Kconfig
>> source hyperv/Kconfig
>> source i2c/Kconfig
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> new file mode 100644
>> index 0000000000..e650c660f0
>> --- /dev/null
>> +++ b/hw/fsi/Kconfig
>> @@ -0,0 +1,2 @@
>> +config FSI_LBUS
>> + bool
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> new file mode 100644
>> index 0000000000..4074d3a7d2
>> --- /dev/null
>> +++ b/hw/fsi/meson.build
>> @@ -0,0 +1 @@
>> +system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> diff --git a/hw/meson.build b/hw/meson.build
>> index c7ac7d3d75..6c71ee9cfa 100644
>> --- a/hw/meson.build
>> +++ b/hw/meson.build
>> @@ -43,6 +43,7 @@ subdir('virtio')
>> subdir('watchdog')
>> subdir('xen')
>> subdir('xenpv')
>> +subdir('fsi')
>> subdir('alpha')
>> subdir('arm')
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-19 8:08 ` Cédric Le Goater
@ 2023-10-21 20:21 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:21 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 03:08, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The LBUS is modelled to maintain the qdev bus hierarchy and to take
>> advantage of the object model to automatically generate the CFAM
>> configuration block. The configuration block presents engines in the
>> order they are attached to the CFAM's LBUS. Engine implementations
>> should subclass the LBusDevice and set the 'config' member of
>> LBusDeviceClass to match the engine's type.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
>> include/qemu/bitops.h | 6 +++
>> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
>> hw/Kconfig | 1 +
>> hw/fsi/Kconfig | 2 +
>> hw/fsi/meson.build | 1 +
>> hw/meson.build | 1 +
>> 7 files changed, 149 insertions(+)
>> create mode 100644 include/hw/fsi/lbus.h
>> create mode 100644 hw/fsi/lbus.c
>> create mode 100644 hw/fsi/Kconfig
>> create mode 100644 hw/fsi/meson.build
>>
>> diff --git a/include/hw/fsi/lbus.h b/include/hw/fsi/lbus.h
>> new file mode 100644
>> index 0000000000..408fe25831
>> --- /dev/null
>> +++ b/include/hw/fsi/lbus.h
>> @@ -0,0 +1,51 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Local bus and connected device structures.
>> + */
>> +#ifndef FSI_LBUS_H
>> +#define FSI_LBUS_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/qdev-core.h"
>> +
>> +#define TYPE_FSI_LBUS_DEVICE "fsi.lbus.device"
>> +OBJECT_DECLARE_TYPE(FSILBusDevice, FSILBusDeviceClass, FSI_LBUS_DEVICE)
>> +
>> +#define FSI_LBUS_MEM_REGION_SIZE (2 * 1024 * 1024)
>> +#define FSI_LBUSDEV_IOMEM_SIZE 0x400
>> +
>> +typedef struct FSILBusDevice {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> + uint32_t address;
>> +} FSILBusDevice;
>> +
>> +typedef struct FSILBusDeviceClass {
>> + DeviceClass parent;
>> +
>> + uint32_t config;
>> +} FSILBusDeviceClass;
>> +
>> +typedef struct FSILBusNode {
>> + FSILBusDevice *ldev;
>> +
>> + QLIST_ENTRY(FSILBusNode) next;
>> +} FSILBusNode;
>> +
>> +#define TYPE_FSI_LBUS "fsi.lbus"
>> +OBJECT_DECLARE_SIMPLE_TYPE(FSILBus, FSI_LBUS)
>> +
>> +typedef struct FSILBus {
>> + BusState bus;
>> +
>> + MemoryRegion mr;
>> +
>> + QLIST_HEAD(, FSILBusNode) devices;
>> +} FSILBus;
>> +
>> +DeviceState *lbus_create_device(FSILBus *bus, const char *type,
>> uint32_t addr);
>> +int lbus_add_device(FSILBus *bus, FSILBusDevice *dev);
>> +#endif /* FSI_LBUS_H */
>> diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
>> index cb3526d1f4..e12496f619 100644
>> --- a/include/qemu/bitops.h
>> +++ b/include/qemu/bitops.h
>> @@ -618,4 +618,10 @@ static inline uint64_t half_unshuffle64(uint64_t x)
>> return x;
>> }
>> +/* Bitwise operations at the word level. */
>> +#define BE_BIT(x) BIT(31 - (x))
>> +#define GENMASK(t, b) \
>> + (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
>> +#define BE_GENMASK(t, b) GENMASK(BE_BIT(t),
>> BE_BIT(b))
>> +
>> #endif
>
> Oh I forgot. please remove this change above.
Fixed. Sorry I should have fixed it last patch.
Thanks for the review.
~Ninad
>
> Thanks,
>
> C.
>
>
>> diff --git a/hw/fsi/lbus.c b/hw/fsi/lbus.c
>> new file mode 100644
>> index 0000000000..d7117d1299
>> --- /dev/null
>> +++ b/hw/fsi/lbus.c
>> @@ -0,0 +1,87 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Local bus where FSI slaves are connected
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "hw/fsi/lbus.h"
>> +
>> +#include "hw/qdev-properties.h"
>> +
>> +static void lbus_realize(BusState *bus, Error **errp)
>> +{
>> + FSILBusNode *node;
>> + FSILBus *lbus = FSI_LBUS(bus);
>> +
>> + memory_region_init(&lbus->mr, OBJECT(lbus), TYPE_FSI_LBUS,
>> + FSI_LBUS_MEM_REGION_SIZE -
>> FSI_LBUSDEV_IOMEM_SIZE);
>> +
>> + QLIST_FOREACH(node, &lbus->devices, next) {
>> + memory_region_add_subregion(&lbus->mr, node->ldev->address,
>> + &node->ldev->iomem);
>> + }
>> +}
>> +
>> +static void lbus_class_init(ObjectClass *klass, void *data)
>> +{
>> + BusClass *k = BUS_CLASS(klass);
>> + k->realize = lbus_realize;
>> +}
>> +
>> +static const TypeInfo lbus_info = {
>> + .name = TYPE_FSI_LBUS,
>> + .parent = TYPE_BUS,
>> + .instance_size = sizeof(FSILBus),
>> + .class_init = lbus_class_init,
>> +};
>> +
>> +static Property lbus_device_props[] = {
>> + DEFINE_PROP_UINT32("address", FSILBusDevice, address, 0),
>> + DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +DeviceState *lbus_create_device(FSILBus *bus, const char *type,
>> uint32_t addr)
>> +{
>> + DeviceState *dev;
>> + FSILBusNode *node;
>> + BusState *state = BUS(bus);
>> +
>> + dev = qdev_new(type);
>> + qdev_prop_set_uint8(dev, "address", addr);
>> + qdev_realize_and_unref(dev, state, &error_fatal);
>> +
>> + /* Move to post_load */
>> + node = g_malloc(sizeof(struct FSILBusNode));
>> + node->ldev = FSI_LBUS_DEVICE(dev);
>> + QLIST_INSERT_HEAD(&bus->devices, node, next);
>> +
>> + return dev;
>> +}
>> +
>> +static void lbus_device_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> + dc->bus_type = TYPE_FSI_LBUS;
>> + device_class_set_props(dc, lbus_device_props);
>> +}
>> +
>> +static const TypeInfo lbus_device_type_info = {
>> + .name = TYPE_FSI_LBUS_DEVICE,
>> + .parent = TYPE_DEVICE,
>> + .instance_size = sizeof(FSILBusDevice),
>> + .abstract = true,
>> + .class_init = lbus_device_class_init,
>> + .class_size = sizeof(FSILBusDeviceClass),
>> +};
>> +
>> +static void lbus_register_types(void)
>> +{
>> + type_register_static(&lbus_info);
>> + type_register_static(&lbus_device_type_info);
>> +}
>> +
>> +type_init(lbus_register_types);
>> diff --git a/hw/Kconfig b/hw/Kconfig
>> index ba62ff6417..2ccb73add5 100644
>> --- a/hw/Kconfig
>> +++ b/hw/Kconfig
>> @@ -9,6 +9,7 @@ source core/Kconfig
>> source cxl/Kconfig
>> source display/Kconfig
>> source dma/Kconfig
>> +source fsi/Kconfig
>> source gpio/Kconfig
>> source hyperv/Kconfig
>> source i2c/Kconfig
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> new file mode 100644
>> index 0000000000..e650c660f0
>> --- /dev/null
>> +++ b/hw/fsi/Kconfig
>> @@ -0,0 +1,2 @@
>> +config FSI_LBUS
>> + bool
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> new file mode 100644
>> index 0000000000..4074d3a7d2
>> --- /dev/null
>> +++ b/hw/fsi/meson.build
>> @@ -0,0 +1 @@
>> +system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> diff --git a/hw/meson.build b/hw/meson.build
>> index c7ac7d3d75..6c71ee9cfa 100644
>> --- a/hw/meson.build
>> +++ b/hw/meson.build
>> @@ -43,6 +43,7 @@ subdir('virtio')
>> subdir('watchdog')
>> subdir('xen')
>> subdir('xenpv')
>> +subdir('fsi')
>> subdir('alpha')
>> subdir('arm')
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus
2023-10-19 16:09 ` Daniel P. Berrangé
@ 2023-10-21 20:22 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:22 UTC (permalink / raw
To: Daniel P. Berrangé
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
Hello Daniel,
On 10/19/23 11:09, Daniel P. Berrangé wrote:
> On Thu, Oct 19, 2023 at 10:34:52AM -0500, Ninad Palsule wrote:
>> Hello Daniel,
>>
>> On 10/19/23 03:14, Daniel P. Berrangé wrote:
>>> On Wed, Oct 11, 2023 at 10:13:30AM -0500, Ninad Palsule wrote:
>>>> This is a part of patchset where IBM's Flexible Service Interface is
>>>> introduced.
>>>>
>>>> The LBUS is modelled to maintain the qdev bus hierarchy and to take
>>>> advantage of the object model to automatically generate the CFAM
>>>> configuration block. The configuration block presents engines in the
>>>> order they are attached to the CFAM's LBUS. Engine implementations
>>>> should subclass the LBusDevice and set the 'config' member of
>>>> LBusDeviceClass to match the engine's type.
>>>>
>>>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>>>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>>>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>>>> ---
>>>> v2:
>>>> - Incorporated Joel's review comments.
>>>> v5:
>>>> - Incorporated review comments by Cedric.
>>>> ---
>>>> include/hw/fsi/lbus.h | 51 +++++++++++++++++++++++++
>>>> include/qemu/bitops.h | 6 +++
>>>> hw/fsi/lbus.c | 87 +++++++++++++++++++++++++++++++++++++++++++
>>>> hw/Kconfig | 1 +
>>>> hw/fsi/Kconfig | 2 +
>>>> hw/fsi/meson.build | 1 +
>>>> hw/meson.build | 1 +
>>>> 7 files changed, 149 insertions(+)
>>>> create mode 100644 include/hw/fsi/lbus.h
>>>> create mode 100644 hw/fsi/lbus.c
>>>> create mode 100644 hw/fsi/Kconfig
>>>> create mode 100644 hw/fsi/meson.build
>>>> +DeviceState *lbus_create_device(FSILBus *bus, const char *type, uint32_t addr)
>>>> +{
>>>> + DeviceState *dev;
>>>> + FSILBusNode *node;
>>>> + BusState *state = BUS(bus);
>>>> +
>>>> + dev = qdev_new(type);
>>>> + qdev_prop_set_uint8(dev, "address", addr);
>>>> + qdev_realize_and_unref(dev, state, &error_fatal);
>>>> +
>>>> + /* Move to post_load */
>>>> + node = g_malloc(sizeof(struct FSILBusNode));
>>> This allocation pattern is discouraged in favour of:
>>>
>>> node = g_new0(FSILBusNode, 1);
>> I am using g_malloc() because I want program to terminate. I don't think
>> g_new0 provide this functionality. Please let me know.
> All the glib memory allocation functions terminate on OOM, except
> for the ones with '_try_' in their name.
Sorry, you are right. I have removed this function as per Cedric's comment.
Thanks for the review.
Regards,
Ninad
>
> With regards,
> Daniel
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad
2023-10-19 8:20 ` Daniel P. Berrangé
@ 2023-10-21 20:27 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:27 UTC (permalink / raw
To: Daniel P. Berrangé
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
Hello Daniel,
On 10/19/23 03:20, Daniel P. Berrangé wrote:
> On Wed, Oct 11, 2023 at 10:13:31AM -0500, Ninad Palsule wrote:
>> This is a part of patchset where scratchpad is introduced.
>>
>> The scratchpad provides a set of non-functional registers. The firmware
>> is free to use them, hardware does not support any special management
>> support. The scratchpad registers can be read or written from LBUS
>> slave.
>>
>> In this model, The LBUS device is parent for the scratchpad.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/engine-scratchpad.h | 33 ++++++++++
>> hw/fsi/engine-scratchpad.c | 99 ++++++++++++++++++++++++++++++
>> hw/fsi/Kconfig | 4 ++
>> hw/fsi/meson.build | 1 +
>> hw/fsi/trace-events | 2 +
>> 5 files changed, 139 insertions(+)
>> create mode 100644 include/hw/fsi/engine-scratchpad.h
>> create mode 100644 hw/fsi/engine-scratchpad.c
>> create mode 100644 hw/fsi/trace-events
>>
>> diff --git a/include/hw/fsi/engine-scratchpad.h b/include/hw/fsi/engine-scratchpad.h
>> new file mode 100644
>> index 0000000000..17e9570c5c
>> --- /dev/null
>> +++ b/include/hw/fsi/engine-scratchpad.h
>> @@ -0,0 +1,33 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM scratchpad engne
>> + */
>> +#ifndef FSI_ENGINE_SCRATCHPAD_H
>> +#define FSI_ENGINE_SCRATCHPAD_H
>> +
>> +#include "qemu/bitops.h"
>> +
>> +#include "hw/fsi/lbus.h"
>> +
>> +#define ENGINE_CONFIG_NEXT BE_BIT(0)
>> +#define ENGINE_CONFIG_VPD BE_BIT(1)
>> +#define ENGINE_CONFIG_SLOTS BE_GENMASK(8, 15)
>> +#define ENGINE_CONFIG_VERSION BE_GENMASK(16, 19)
>> +#define ENGINE_CONFIG_TYPE BE_GENMASK(20, 27)
>> +#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4)
>> +#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4)
>> +#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4)
>> +#define ENGINE_CONFIG_CRC BE_GENMASK(28, 31)
>> +
>> +#define TYPE_SCRATCHPAD "scratchpad"
>> +#define SCRATCHPAD(obj) OBJECT_CHECK(ScratchPad, (obj), TYPE_SCRATCHPAD)
>> +
>> +typedef struct ScratchPad {
>> + FSILBusDevice parent;
>> +
>> + uint32_t reg;
>> +} ScratchPad;
>> +
>> +#endif /* FSI_ENGINE_SCRATCHPAD_H */
>> diff --git a/hw/fsi/engine-scratchpad.c b/hw/fsi/engine-scratchpad.c
>> new file mode 100644
>> index 0000000000..60f678eec4
>> --- /dev/null
>> +++ b/hw/fsi/engine-scratchpad.c
>> @@ -0,0 +1,99 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM scratchpad engine
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/engine-scratchpad.h"
>> +
>> +static uint64_t scratchpad_read(void *opaque, hwaddr addr, unsigned size)
>> +{
>> + ScratchPad *s = SCRATCHPAD(opaque);
>> +
>> + trace_scratchpad_read(addr, size);
>> +
>> + if (addr) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
>> + __func__, addr, size);
> We already have a trace point in the line above. I don't think we should
> be unconditionally logging errors like this, as this becomes a guest
> triggerable denial of service on the host log collector for the guest.
> eg it could flood the logfile connected to stderr with unlimited data
> by repeatedly doing bad reads/writes.
Make sense. We can catch it using the existing traces. I have removed it
from read and write function.
>
>> + return 0;
>> + }
>> +
>> + return s->reg;
>> +}
>> +
>> +static void scratchpad_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + ScratchPad *s = SCRATCHPAD(opaque);
>> +
>> + trace_scratchpad_write(addr, size, data);
>> +
>> + if (addr) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
>> + __func__, addr, size);
>> + return;
>> + }
>> +
>> + s->reg = data;
>> +}
>> +
>> +static const struct MemoryRegionOps scratchpad_ops = {
>> + .read = scratchpad_read,
>> + .write = scratchpad_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void scratchpad_realize(DeviceState *dev, Error **errp)
>> +{
>> + FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev);
>> +
>> + memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops,
>> + ldev, TYPE_SCRATCHPAD, 0x400);
>> +}
>> +
>> +static void scratchpad_reset(DeviceState *dev)
>> +{
>> + ScratchPad *s = SCRATCHPAD(dev);
>> +
>> + s->reg = 0;
>> +}
>> +
>> +static void scratchpad_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + FSILBusDeviceClass *ldc = FSI_LBUS_DEVICE_CLASS(klass);
>> +
>> + dc->realize = scratchpad_realize;
>> + dc->reset = scratchpad_reset;
>> +
>> + ldc->config =
>> + ENGINE_CONFIG_NEXT /* valid */
>> + | 0x00010000 /* slots */
>> + | 0x00001000 /* version */
>> + | ENGINE_CONFIG_TYPE_SCRATCHPAD /* type */
>> + | 0x00000007; /* crc */
> More common QEMU style would be for the "|" to be on the end
> of line rather than start.
>
> End of line:
>
> $ git grep '.*\s|\s*$' "*.c" | wc -l
> 5381
>
> Start of line:
>
> $ git grep '^\s*|\s.*' "*.c" | wc -l
> 581
Fixed as per you suggestion.
Thanks for the review.
Regards,
Ninad
>
>> +}
>> +
>> +static const TypeInfo scratchpad_info = {
>> + .name = TYPE_SCRATCHPAD,
>> + .parent = TYPE_FSI_LBUS_DEVICE,
>> + .instance_size = sizeof(ScratchPad),
>> + .class_init = scratchpad_class_init,
>> + .class_size = sizeof(FSILBusDeviceClass),
>> +};
>> +
>> +static void scratchpad_register_types(void)
>> +{
>> + type_register_static(&scratchpad_info);
>> +}
>> +
>> +type_init(scratchpad_register_types);
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> index e650c660f0..f7c7fd1b28 100644
>> --- a/hw/fsi/Kconfig
>> +++ b/hw/fsi/Kconfig
>> @@ -1,2 +1,6 @@
>> +config FSI_SCRATCHPAD
>> + bool
>> + select FSI_LBUS
>> +
>> config FSI_LBUS
>> bool
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index 4074d3a7d2..d45a98c223 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -1 +1,2 @@
>> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> +system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> new file mode 100644
>> index 0000000000..97fd070354
>> --- /dev/null
>> +++ b/hw/fsi/trace-events
>> @@ -0,0 +1,2 @@
>> +scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> --
>> 2.39.2
>>
> With regards,
> Daniel
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-19 8:00 ` Cédric Le Goater
@ 2023-10-21 20:33 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:33 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 03:00, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The Common FRU Access Macro (CFAM), an address space containing
>> various "engines" that drive accesses on busses internal and external
>> to the POWER chip. Examples include the SBEFIFO and I2C masters. The
>> engines hang off of an internal Local Bus (LBUS) which is described
>> by the CFAM configuration block.
>>
>> The FSI slave: The slave is the terminal point of the FSI bus for
>> FSI symbols addressed to it. Slaves can be cascaded off of one
>> another. The slave's configuration registers appear in address space
>> of the CFAM to which it is attached.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v3:
>> - Incorporated Thomas Huth's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/cfam.h | 58 ++++++++++
>> include/hw/fsi/fsi-slave.h | 29 +++++
>> hw/fsi/cfam.c | 220 +++++++++++++++++++++++++++++++++++++
>> hw/fsi/fsi-slave.c | 96 ++++++++++++++++
>> hw/fsi/Kconfig | 9 ++
>> hw/fsi/meson.build | 2 +
>> hw/fsi/trace-events | 7 ++
>> 7 files changed, 421 insertions(+)
>> create mode 100644 include/hw/fsi/cfam.h
>> create mode 100644 include/hw/fsi/fsi-slave.h
>> create mode 100644 hw/fsi/cfam.c
>> create mode 100644 hw/fsi/fsi-slave.c
>>
>> diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
>> new file mode 100644
>> index 0000000000..a828fd931e
>> --- /dev/null
>> +++ b/include/hw/fsi/cfam.h
>> @@ -0,0 +1,58 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Common FRU Access Macro
>> + */
>> +#ifndef FSI_CFAM_H
>> +#define FSI_CFAM_H
>> +
>> +#include "exec/memory.h"
>> +
>> +#include "hw/fsi/fsi-slave.h"
>> +#include "hw/fsi/lbus.h"
>> +
>> +#define TYPE_CFAM "cfam"
>> +#define CFAM(obj) OBJECT_CHECK(CFAMState, (obj), TYPE_CFAM)
>> +
>> +#define CFAM_NR_REGS ((0x2e0 >> 2) + 1)
>> +
>> +#define TYPE_CFAM_CONFIG "cfam.config"
>> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMConfig, CFAM_CONFIG)
>> +
>> +/* P9-ism */
>> +#define CFAM_CONFIG_NR_REGS 0x28
>> +
>> +typedef struct CFAMState CFAMState;
>> +
>> +/* TODO: Generalise this accommodate different CFAM configurations */
>> +typedef struct CFAMConfig {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> +} CFAMConfig;
>> +
>> +#define TYPE_CFAM_PEEK "cfam.peek"
>> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMPeek, CFAM_PEEK)
>> +#define CFAM_PEEK_NR_REGS ((0x130 >> 2) + 1)
>> +
>> +typedef struct CFAMPeek {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> +} CFAMPeek;
>> +
>> +struct CFAMState {
>> + /* < private > */
>> + FSISlaveState parent;
>> +
>> + MemoryRegion mr;
>> + AddressSpace as;
>> +
>> + CFAMConfig config;
>> + CFAMPeek peek;
>> +
>> + FSILBus lbus;
>> +};
>> +
>> +#endif /* FSI_CFAM_H */
>> diff --git a/include/hw/fsi/fsi-slave.h b/include/hw/fsi/fsi-slave.h
>> new file mode 100644
>> index 0000000000..f5f23f4457
>> --- /dev/null
>> +++ b/include/hw/fsi/fsi-slave.h
>> @@ -0,0 +1,29 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface slave
>> + */
>> +#ifndef FSI_FSI_SLAVE_H
>> +#define FSI_FSI_SLAVE_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/qdev-core.h"
>> +
>> +#include "hw/fsi/lbus.h"
>> +
>> +#include <stdint.h>
>> +
>> +#define TYPE_FSI_SLAVE "fsi.slave"
>> +OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
>> +
>> +#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
>> +
>> +typedef struct FSISlaveState {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> + uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
>> +} FSISlaveState;
>> +
>> +#endif /* FSI_FSI_H */
>> diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
>> new file mode 100644
>> index 0000000000..9044cc741b
>> --- /dev/null
>> +++ b/hw/fsi/cfam.c
>> @@ -0,0 +1,220 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Common FRU Access Macro
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qapi/error.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/bits.h"
>> +#include "hw/fsi/cfam.h"
>> +#include "hw/fsi/engine-scratchpad.h"
>> +
>> +#include "hw/qdev-properties.h"
>> +
>> +#define TO_REG(x) ((x) >> 2)
>> +
>> +#define CFAM_ENGINE_CONFIG TO_REG(0x04)
>> +
>> +#define CFAM_CONFIG_CHIP_ID TO_REG(0x00)
>> +#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
>> +#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000
>> +
>> +static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned
>> size)
>> +{
>> + CFAMConfig *config;
>> + CFAMState *cfam;
>> + FSILBusNode *node;
>> + int i;
>> +
>> + config = CFAM_CONFIG(opaque);
>> + cfam = container_of(config, CFAMState, config);
>> +
>> + trace_cfam_config_read(addr, size);
>> +
>> + switch (addr) {
>> + case 0x00:
>> + return CFAM_CONFIG_CHIP_ID_P9;
>> + case 0x04:
>> + return ENGINE_CONFIG_NEXT
>> + | 0x00010000 /* slots */
>> + | 0x00001000 /* version */
>> + | ENGINE_CONFIG_TYPE_PEEK /* type */
>> + | 0x0000000c; /* crc */
>> + case 0x08:
>> + return ENGINE_CONFIG_NEXT
>> + | 0x00010000 /* slots */
>> + | 0x00005000 /* version */
>> + | ENGINE_CONFIG_TYPE_FSI /* type */
>> + | 0x0000000a; /* crc */
>> + break;
>> + default:
>> + /* FIXME: Improve this */
>> + i = 0xc;
>> + QLIST_FOREACH(node, &cfam->lbus.devices, next) {
>> + if (i == addr) {
>> + return FSI_LBUS_DEVICE_GET_CLASS(node->ldev)->config;
>> + }
>> + i += size;
>> + }
>
> Please use qbus_walk_children() and drop the devices list.
Yes, removed the list and using children list of the BusState.
>
>> + if (i == addr) {
>> + return 0;
>> + }
>> +
>> + /*
>> + * As per FSI specification, This is a magic value at
>> address 0 of
>> + * given FSI port. This causes FSI master to send BREAK
>> command for
>> + * initialization and recovery.
>> + */
>> + return CFAM_CONFIG_CHIP_ID_BREAK;
>> + }
>> +}
>> +
>> +static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + CFAMConfig *s = CFAM_CONFIG(opaque);
>> +
>> + trace_cfam_config_write(addr, size, data);
>> +
>> + switch (TO_REG(addr)) {
>> + case CFAM_CONFIG_CHIP_ID:
>> + case CFAM_CONFIG_CHIP_ID + 4:
>> + if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
>> + bus_cold_reset(qdev_get_parent_bus(DEVICE(s)));
>> + }
>> + break;
>> + default:
>> + trace_cfam_config_write_noaddr(addr, size, data);
>> + }
>> +}
>> +
>> +static const struct MemoryRegionOps cfam_config_ops = {
>> + .read = cfam_config_read,
>> + .write = cfam_config_write,
>> + .valid.max_access_size = 4,
>> + .valid.min_access_size = 4,
>> + .impl.max_access_size = 4,
>> + .impl.min_access_size = 4,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void cfam_config_realize(DeviceState *dev, Error **errp)
>> +{
>> + CFAMConfig *s = CFAM_CONFIG(dev);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &cfam_config_ops, s,
>> + TYPE_CFAM_CONFIG, 0x400);
>> +}
>> +
>> +static void cfam_config_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + dc->bus_type = TYPE_FSI_LBUS;
>> + dc->realize = cfam_config_realize;
>> +}
>> +
>> +static const TypeInfo cfam_config_info = {
>> + .name = TYPE_CFAM_CONFIG,
>> + .parent = TYPE_DEVICE,
>> + .instance_size = sizeof(CFAMConfig),
>> + .class_init = cfam_config_class_init,
>> +};
>
> Please drop the TYPE_CFAM_CONFIG object and move the config MMIO
> under the CFAM object. It will simplify the model.
Good suggestion. Fixed as per your suggestion.
>
>> +
>> +static uint64_t cfam_unimplemented_read(void *opaque, hwaddr addr,
>> + unsigned size)
>> +{
>> + trace_cfam_unimplemented_read(addr, size);
>> +
>> + return 0;
>> +}
>> +
>> +static void cfam_unimplemented_write(void *opaque, hwaddr addr,
>> uint64_t data,
>> + unsigned size)
>> +{
>> + trace_cfam_unimplemented_write(addr, size, data);
>> +}
>> +
>> +static const struct MemoryRegionOps cfam_unimplemented_ops = {
>> + .read = cfam_unimplemented_read,
>> + .write = cfam_unimplemented_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>
> Is it possible to use create_unimplemented_device() ?
I don't think as this is used for the mmio.
>
>> +static void cfam_realize(DeviceState *dev, Error **errp)
>> +{
>> + CFAMState *cfam = CFAM(dev);
>> + FSISlaveState *slave = FSI_SLAVE(dev);
>> + Error *err = NULL;
>> +
>> + /* Each slave has a 2MiB address space */
>> + memory_region_init_io(&cfam->mr, OBJECT(cfam),
>> &cfam_unimplemented_ops,
>> + cfam, TYPE_CFAM, 2 * 1024 * 1024);
>> + address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
>> +
>> + qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
>> + DEVICE(cfam), NULL);
>> +
>> + lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
>> +
>> + object_property_set_bool(OBJECT(&cfam->config), "realized",
>> true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> + qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus),
>> &error_abort);
>> +
>> + object_property_set_bool(OBJECT(&cfam->lbus), "realized", true,
>> &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
>> + /* memory_region_add_subregion(&cfam->mr, 0x800,
>> &cfam->lbus.peek.iomem); */
>> + memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
>> + memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
>> +}
>> +
>> +static void cfam_init(Object *o)
>> +{
>> + CFAMState *s = CFAM(o);
>> +
>> + object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config,
>> TYPE_CFAM_CONFIG);
>> +}
>> +
>> +static void cfam_finalize(Object *o)
>> +{
>> + CFAMState *s = CFAM(o);
>> +
>> + address_space_destroy(&s->as);
>> +}
>
> finalize only really needed for hotpluggable devices.
Removed.
Thanks for the review.
Regards,
Ninad
>
>> +
>> +static void cfam_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + dc->bus_type = TYPE_FSI_BUS;
>> + dc->realize = cfam_realize;
>> +}
>> +
>> +static const TypeInfo cfam_info = {
>> + .name = TYPE_CFAM,
>> + .parent = TYPE_FSI_SLAVE,
>> + .instance_init = cfam_init,
>> + .instance_finalize = cfam_finalize,
>> + .instance_size = sizeof(CFAMState),
>> + .class_init = cfam_class_init,
>> +};
>> +
>> +static void cfam_register_types(void)
>> +{
>> + type_register_static(&cfam_config_info);
>> + type_register_static(&cfam_info);
>> +}
>> +
>> +type_init(cfam_register_types);
>> diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
>> new file mode 100644
>> index 0000000000..127fdd8a4f
>> --- /dev/null
>> +++ b/hw/fsi/fsi-slave.c
>> @@ -0,0 +1,96 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface slave
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qemu/bitops.h"
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/fsi-slave.h"
>> +
>> +#define TO_REG(x) ((x) >> 2)
>> +
>> +#define FSI_SMODE TO_REG(0x00)
>> +#define FSI_SMODE_WSTART BE_BIT(0)
>> +#define FSI_SMODE_AUX_EN BE_BIT(1)
>> +#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
>> +#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
>> +#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
>> +#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
>> +#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
>> +#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
>> +
>> +#define FSI_SDMA TO_REG(0x04)
>> +#define FSI_SISC TO_REG(0x08)
>> +#define FSI_SCISC TO_REG(0x08)
>> +#define FSI_SISM TO_REG(0x0c)
>> +#define FSI_SISS TO_REG(0x10)
>> +#define FSI_SSISM TO_REG(0x10)
>> +#define FSI_SCISM TO_REG(0x14)
>> +
>> +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned
>> size)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(opaque);
>> +
>> + trace_fsi_slave_read(addr, size);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return 0;
>> + }
>> +
>> + return s->regs[TO_REG(addr)];
>> +}
>> +
>> +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(opaque);
>> +
>> + trace_fsi_slave_write(addr, size, data);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return;
>> + }
>> +
>> + s->regs[TO_REG(addr)] = data;
>> +}
>> +
>> +static const struct MemoryRegionOps fsi_slave_ops = {
>> + .read = fsi_slave_read,
>> + .write = fsi_slave_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void fsi_slave_init(Object *o)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(o);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
>> + s, TYPE_FSI_SLAVE, 0x400);
>> +}
>> +
>> +static const TypeInfo fsi_slave_info = {
>> + .name = TYPE_FSI_SLAVE,
>> + .parent = TYPE_DEVICE,
>> + .instance_init = fsi_slave_init,
>> + .instance_size = sizeof(FSISlaveState),
>> +};
>> +
>> +static void fsi_slave_register_types(void)
>> +{
>> + type_register_static(&fsi_slave_info);
>> +}
>> +
>> +type_init(fsi_slave_register_types);
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> index f7c7fd1b28..8d712e77ed 100644
>> --- a/hw/fsi/Kconfig
>> +++ b/hw/fsi/Kconfig
>> @@ -1,3 +1,12 @@
>> +config FSI_CFAM
>> + bool
>> + select FSI
>> + select FSI_SCRATCHPAD
>> + select FSI_LBUS
>> +
>> +config FSI
>> + bool
>> +
>> config FSI_SCRATCHPAD
>> bool
>> select FSI_LBUS
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index d45a98c223..a9e7cd4099 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -1,2 +1,4 @@
>> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true:
>> files('engine-scratchpad.c'))
>> +system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
>> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index 97fd070354..752a5683a0 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -1,2 +1,9 @@
>> scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> scratchpad_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +cfam_config_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64
>> " size=%d"
>> +cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t
>> data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t
>> data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
>> PRIx64 " size=%d value=0x%"PRIx64
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-19 8:26 ` Daniel P. Berrangé
@ 2023-10-21 20:34 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:34 UTC (permalink / raw
To: Daniel P. Berrangé
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
Hello Daniel,
On 10/19/23 03:26, Daniel P. Berrangé wrote:
> On Wed, Oct 11, 2023 at 10:13:32AM -0500, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The Common FRU Access Macro (CFAM), an address space containing
>> various "engines" that drive accesses on busses internal and external
>> to the POWER chip. Examples include the SBEFIFO and I2C masters. The
>> engines hang off of an internal Local Bus (LBUS) which is described
>> by the CFAM configuration block.
>>
>> The FSI slave: The slave is the terminal point of the FSI bus for
>> FSI symbols addressed to it. Slaves can be cascaded off of one
>> another. The slave's configuration registers appear in address space
>> of the CFAM to which it is attached.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v3:
>> - Incorporated Thomas Huth's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>
>> +static void cfam_realize(DeviceState *dev, Error **errp)
>> +{
>> + CFAMState *cfam = CFAM(dev);
>> + FSISlaveState *slave = FSI_SLAVE(dev);
>> + Error *err = NULL;
>> +
>> + /* Each slave has a 2MiB address space */
>> + memory_region_init_io(&cfam->mr, OBJECT(cfam), &cfam_unimplemented_ops,
>> + cfam, TYPE_CFAM, 2 * 1024 * 1024);
>> + address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
>> +
>> + qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
>> + DEVICE(cfam), NULL);
>> +
>> + lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
>> +
>> + object_property_set_bool(OBJECT(&cfam->config), "realized", true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
> object_property_set_bool returns false on error so this use of a local
> Error object is redundant.
>
> if (!object_property_set_bool(..., &errp)) {
> return;
> }
>
>
> If a local Error had been required though, this code should have instead
> been using ERRP_GUARD - see include/qapi/error.h docs for illustration
> for future work.
Fixed as per your suggestion.
>
>> + qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus), &error_abort);
>> +
>> + object_property_set_bool(OBJECT(&cfam->lbus), "realized", true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
> Likewise
Fixed.
Thanks for the review.
Regards,
Ninad
>
>> +
>> + memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
>> + /* memory_region_add_subregion(&cfam->mr, 0x800, &cfam->lbus.peek.iomem); */
>> + memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
>> + memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
>> +}
>> +
>> +static void cfam_init(Object *o)
>> +{
>> + CFAMState *s = CFAM(o);
>> +
>> + object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config, TYPE_CFAM_CONFIG);
>> +}
>> +
>> +static void cfam_finalize(Object *o)
>> +{
>> + CFAMState *s = CFAM(o);
>> +
>> + address_space_destroy(&s->as);
>> +}
>> +
>> +static void cfam_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + dc->bus_type = TYPE_FSI_BUS;
>> + dc->realize = cfam_realize;
>> +}
>> +
>> +static const TypeInfo cfam_info = {
>> + .name = TYPE_CFAM,
>> + .parent = TYPE_FSI_SLAVE,
>> + .instance_init = cfam_init,
>> + .instance_finalize = cfam_finalize,
>> + .instance_size = sizeof(CFAMState),
>> + .class_init = cfam_class_init,
>> +};
>> +
>> +static void cfam_register_types(void)
>> +{
>> + type_register_static(&cfam_config_info);
>> + type_register_static(&cfam_info);
>> +}
>> +
>> +type_init(cfam_register_types);
>> diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
>> new file mode 100644
>> index 0000000000..127fdd8a4f
>> --- /dev/null
>> +++ b/hw/fsi/fsi-slave.c
>> @@ -0,0 +1,96 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface slave
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qemu/bitops.h"
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/fsi-slave.h"
>> +
>> +#define TO_REG(x) ((x) >> 2)
>> +
>> +#define FSI_SMODE TO_REG(0x00)
>> +#define FSI_SMODE_WSTART BE_BIT(0)
>> +#define FSI_SMODE_AUX_EN BE_BIT(1)
>> +#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
>> +#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
>> +#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
>> +#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
>> +#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
>> +#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
>> +
>> +#define FSI_SDMA TO_REG(0x04)
>> +#define FSI_SISC TO_REG(0x08)
>> +#define FSI_SCISC TO_REG(0x08)
>> +#define FSI_SISM TO_REG(0x0c)
>> +#define FSI_SISS TO_REG(0x10)
>> +#define FSI_SSISM TO_REG(0x10)
>> +#define FSI_SCISM TO_REG(0x14)
>> +
>> +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned size)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(opaque);
>> +
>> + trace_fsi_slave_read(addr, size);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n",
>> + __func__, addr, size);
>> + return 0;
>> + }
>> +
>> + return s->regs[TO_REG(addr)];
>> +}
>> +
>> +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(opaque);
>> +
>> + trace_fsi_slave_write(addr, size, data);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n",
>> + __func__, addr, size);
>> + return;
>> + }
>> +
>> + s->regs[TO_REG(addr)] = data;
>> +}
>> +
>> +static const struct MemoryRegionOps fsi_slave_ops = {
>> + .read = fsi_slave_read,
>> + .write = fsi_slave_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void fsi_slave_init(Object *o)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(o);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
>> + s, TYPE_FSI_SLAVE, 0x400);
>> +}
>> +
>> +static const TypeInfo fsi_slave_info = {
>> + .name = TYPE_FSI_SLAVE,
>> + .parent = TYPE_DEVICE,
>> + .instance_init = fsi_slave_init,
>> + .instance_size = sizeof(FSISlaveState),
>> +};
>> +
>> +static void fsi_slave_register_types(void)
>> +{
>> + type_register_static(&fsi_slave_info);
>> +}
>> +
>> +type_init(fsi_slave_register_types);
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> index f7c7fd1b28..8d712e77ed 100644
>> --- a/hw/fsi/Kconfig
>> +++ b/hw/fsi/Kconfig
>> @@ -1,3 +1,12 @@
>> +config FSI_CFAM
>> + bool
>> + select FSI
>> + select FSI_SCRATCHPAD
>> + select FSI_LBUS
>> +
>> +config FSI
>> + bool
>> +
>> config FSI_SCRATCHPAD
>> bool
>> select FSI_LBUS
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index d45a98c223..a9e7cd4099 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -1,2 +1,4 @@
>> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true: files('engine-scratchpad.c'))
>> +system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
>> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index 97fd070354..752a5683a0 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -1,2 +1,9 @@
>> scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> scratchpad_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +cfam_config_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> --
>> 2.39.2
>>
> With regards,
> Daniel
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
2023-10-19 17:28 ` Cédric Le Goater
@ 2023-10-21 20:35 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:35 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 12:28, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The Common FRU Access Macro (CFAM), an address space containing
>> various "engines" that drive accesses on busses internal and external
>> to the POWER chip. Examples include the SBEFIFO and I2C masters. The
>> engines hang off of an internal Local Bus (LBUS) which is described
>> by the CFAM configuration block.
>>
>> The FSI slave: The slave is the terminal point of the FSI bus for
>> FSI symbols addressed to it. Slaves can be cascaded off of one
>> another. The slave's configuration registers appear in address space
>> of the CFAM to which it is attached.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated Joel's review comments.
>> v3:
>> - Incorporated Thomas Huth's review comments.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/cfam.h | 58 ++++++++++
>> include/hw/fsi/fsi-slave.h | 29 +++++
>> hw/fsi/cfam.c | 220 +++++++++++++++++++++++++++++++++++++
>> hw/fsi/fsi-slave.c | 96 ++++++++++++++++
>> hw/fsi/Kconfig | 9 ++
>> hw/fsi/meson.build | 2 +
>> hw/fsi/trace-events | 7 ++
>> 7 files changed, 421 insertions(+)
>> create mode 100644 include/hw/fsi/cfam.h
>> create mode 100644 include/hw/fsi/fsi-slave.h
>> create mode 100644 hw/fsi/cfam.c
>> create mode 100644 hw/fsi/fsi-slave.c
>>
>> diff --git a/include/hw/fsi/cfam.h b/include/hw/fsi/cfam.h
>> new file mode 100644
>> index 0000000000..a828fd931e
>> --- /dev/null
>> +++ b/include/hw/fsi/cfam.h
>> @@ -0,0 +1,58 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Common FRU Access Macro
>> + */
>> +#ifndef FSI_CFAM_H
>> +#define FSI_CFAM_H
>> +
>> +#include "exec/memory.h"
>> +
>> +#include "hw/fsi/fsi-slave.h"
>> +#include "hw/fsi/lbus.h"
>> +
>> +#define TYPE_CFAM "cfam"
>> +#define CFAM(obj) OBJECT_CHECK(CFAMState, (obj), TYPE_CFAM)
>> +
>> +#define CFAM_NR_REGS ((0x2e0 >> 2) + 1)
>> +
>> +#define TYPE_CFAM_CONFIG "cfam.config"
>> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMConfig, CFAM_CONFIG)
>> +
>> +/* P9-ism */
>> +#define CFAM_CONFIG_NR_REGS 0x28
>> +
>> +typedef struct CFAMState CFAMState;
>> +
>> +/* TODO: Generalise this accommodate different CFAM configurations */
>> +typedef struct CFAMConfig {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> +} CFAMConfig;
>> +
>> +#define TYPE_CFAM_PEEK "cfam.peek"
>> +OBJECT_DECLARE_SIMPLE_TYPE(CFAMPeek, CFAM_PEEK)
>> +#define CFAM_PEEK_NR_REGS ((0x130 >> 2) + 1)
>> +
>> +typedef struct CFAMPeek {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> +} CFAMPeek;
>
>
> Ninad,
>
> I don't see the CFAMPeek model being used anywhere. Please drop.
Removed.
Thanks for the review.
Regards,
Ninad
>
> Thanks,
>
> C.
>
>
>> +
>> +struct CFAMState {
>> + /* < private > */
>> + FSISlaveState parent;
>> +
>> + MemoryRegion mr;
>> + AddressSpace as;
>> +
>> + CFAMConfig config;
>> + CFAMPeek peek;
>> +
>> + FSILBus lbus;
>> +};
>> +
>> +#endif /* FSI_CFAM_H */
>> diff --git a/include/hw/fsi/fsi-slave.h b/include/hw/fsi/fsi-slave.h
>> new file mode 100644
>> index 0000000000..f5f23f4457
>> --- /dev/null
>> +++ b/include/hw/fsi/fsi-slave.h
>> @@ -0,0 +1,29 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface slave
>> + */
>> +#ifndef FSI_FSI_SLAVE_H
>> +#define FSI_FSI_SLAVE_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/qdev-core.h"
>> +
>> +#include "hw/fsi/lbus.h"
>> +
>> +#include <stdint.h>
>> +
>> +#define TYPE_FSI_SLAVE "fsi.slave"
>> +OBJECT_DECLARE_SIMPLE_TYPE(FSISlaveState, FSI_SLAVE)
>> +
>> +#define FSI_SLAVE_CONTROL_NR_REGS ((0x40 >> 2) + 1)
>> +
>> +typedef struct FSISlaveState {
>> + DeviceState parent;
>> +
>> + MemoryRegion iomem;
>> + uint32_t regs[FSI_SLAVE_CONTROL_NR_REGS];
>> +} FSISlaveState;
>> +
>> +#endif /* FSI_FSI_H */
>> diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
>> new file mode 100644
>> index 0000000000..9044cc741b
>> --- /dev/null
>> +++ b/hw/fsi/cfam.c
>> @@ -0,0 +1,220 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Common FRU Access Macro
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qapi/error.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/bits.h"
>> +#include "hw/fsi/cfam.h"
>> +#include "hw/fsi/engine-scratchpad.h"
>> +
>> +#include "hw/qdev-properties.h"
>> +
>> +#define TO_REG(x) ((x) >> 2)
>> +
>> +#define CFAM_ENGINE_CONFIG TO_REG(0x04)
>> +
>> +#define CFAM_CONFIG_CHIP_ID TO_REG(0x00)
>> +#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
>> +#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000
>> +
>> +static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned
>> size)
>> +{
>> + CFAMConfig *config;
>> + CFAMState *cfam;
>> + FSILBusNode *node;
>> + int i;
>> +
>> + config = CFAM_CONFIG(opaque);
>> + cfam = container_of(config, CFAMState, config);
>> +
>> + trace_cfam_config_read(addr, size);
>> +
>> + switch (addr) {
>> + case 0x00:
>> + return CFAM_CONFIG_CHIP_ID_P9;
>> + case 0x04:
>> + return ENGINE_CONFIG_NEXT
>> + | 0x00010000 /* slots */
>> + | 0x00001000 /* version */
>> + | ENGINE_CONFIG_TYPE_PEEK /* type */
>> + | 0x0000000c; /* crc */
>> + case 0x08:
>> + return ENGINE_CONFIG_NEXT
>> + | 0x00010000 /* slots */
>> + | 0x00005000 /* version */
>> + | ENGINE_CONFIG_TYPE_FSI /* type */
>> + | 0x0000000a; /* crc */
>> + break;
>> + default:
>> + /* FIXME: Improve this */
>> + i = 0xc;
>> + QLIST_FOREACH(node, &cfam->lbus.devices, next) {
>> + if (i == addr) {
>> + return FSI_LBUS_DEVICE_GET_CLASS(node->ldev)->config;
>> + }
>> + i += size;
>> + }
>> +
>> + if (i == addr) {
>> + return 0;
>> + }
>> +
>> + /*
>> + * As per FSI specification, This is a magic value at
>> address 0 of
>> + * given FSI port. This causes FSI master to send BREAK
>> command for
>> + * initialization and recovery.
>> + */
>> + return CFAM_CONFIG_CHIP_ID_BREAK;
>> + }
>> +}
>> +
>> +static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + CFAMConfig *s = CFAM_CONFIG(opaque);
>> +
>> + trace_cfam_config_write(addr, size, data);
>> +
>> + switch (TO_REG(addr)) {
>> + case CFAM_CONFIG_CHIP_ID:
>> + case CFAM_CONFIG_CHIP_ID + 4:
>> + if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
>> + bus_cold_reset(qdev_get_parent_bus(DEVICE(s)));
>> + }
>> + break;
>> + default:
>> + trace_cfam_config_write_noaddr(addr, size, data);
>> + }
>> +}
>> +
>> +static const struct MemoryRegionOps cfam_config_ops = {
>> + .read = cfam_config_read,
>> + .write = cfam_config_write,
>> + .valid.max_access_size = 4,
>> + .valid.min_access_size = 4,
>> + .impl.max_access_size = 4,
>> + .impl.min_access_size = 4,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void cfam_config_realize(DeviceState *dev, Error **errp)
>> +{
>> + CFAMConfig *s = CFAM_CONFIG(dev);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &cfam_config_ops, s,
>> + TYPE_CFAM_CONFIG, 0x400);
>> +}
>> +
>> +static void cfam_config_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + dc->bus_type = TYPE_FSI_LBUS;
>> + dc->realize = cfam_config_realize;
>> +}
>> +
>> +static const TypeInfo cfam_config_info = {
>> + .name = TYPE_CFAM_CONFIG,
>> + .parent = TYPE_DEVICE,
>> + .instance_size = sizeof(CFAMConfig),
>> + .class_init = cfam_config_class_init,
>> +};
>> +
>> +static uint64_t cfam_unimplemented_read(void *opaque, hwaddr addr,
>> + unsigned size)
>> +{
>> + trace_cfam_unimplemented_read(addr, size);
>> +
>> + return 0;
>> +}
>> +
>> +static void cfam_unimplemented_write(void *opaque, hwaddr addr,
>> uint64_t data,
>> + unsigned size)
>> +{
>> + trace_cfam_unimplemented_write(addr, size, data);
>> +}
>> +
>> +static const struct MemoryRegionOps cfam_unimplemented_ops = {
>> + .read = cfam_unimplemented_read,
>> + .write = cfam_unimplemented_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void cfam_realize(DeviceState *dev, Error **errp)
>> +{
>> + CFAMState *cfam = CFAM(dev);
>> + FSISlaveState *slave = FSI_SLAVE(dev);
>> + Error *err = NULL;
>> +
>> + /* Each slave has a 2MiB address space */
>> + memory_region_init_io(&cfam->mr, OBJECT(cfam),
>> &cfam_unimplemented_ops,
>> + cfam, TYPE_CFAM, 2 * 1024 * 1024);
>> + address_space_init(&cfam->as, &cfam->mr, TYPE_CFAM);
>> +
>> + qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS,
>> + DEVICE(cfam), NULL);
>> +
>> + lbus_create_device(&cfam->lbus, TYPE_SCRATCHPAD, 0);
>> +
>> + object_property_set_bool(OBJECT(&cfam->config), "realized",
>> true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> + qdev_set_parent_bus(DEVICE(&cfam->config), BUS(&cfam->lbus),
>> &error_abort);
>> +
>> + object_property_set_bool(OBJECT(&cfam->lbus), "realized", true,
>> &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + memory_region_add_subregion(&cfam->mr, 0, &cfam->config.iomem);
>> + /* memory_region_add_subregion(&cfam->mr, 0x800,
>> &cfam->lbus.peek.iomem); */
>> + memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
>> + memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
>> +}
>> +
>> +static void cfam_init(Object *o)
>> +{
>> + CFAMState *s = CFAM(o);
>> +
>> + object_initialize_child(o, TYPE_CFAM_CONFIG, &s->config,
>> TYPE_CFAM_CONFIG);
>> +}
>> +
>> +static void cfam_finalize(Object *o)
>> +{
>> + CFAMState *s = CFAM(o);
>> +
>> + address_space_destroy(&s->as);
>> +}
>> +
>> +static void cfam_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> + dc->bus_type = TYPE_FSI_BUS;
>> + dc->realize = cfam_realize;
>> +}
>> +
>> +static const TypeInfo cfam_info = {
>> + .name = TYPE_CFAM,
>> + .parent = TYPE_FSI_SLAVE,
>> + .instance_init = cfam_init,
>> + .instance_finalize = cfam_finalize,
>> + .instance_size = sizeof(CFAMState),
>> + .class_init = cfam_class_init,
>> +};
>> +
>> +static void cfam_register_types(void)
>> +{
>> + type_register_static(&cfam_config_info);
>> + type_register_static(&cfam_info);
>> +}
>> +
>> +type_init(cfam_register_types);
>> diff --git a/hw/fsi/fsi-slave.c b/hw/fsi/fsi-slave.c
>> new file mode 100644
>> index 0000000000..127fdd8a4f
>> --- /dev/null
>> +++ b/hw/fsi/fsi-slave.c
>> @@ -0,0 +1,96 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface slave
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qemu/bitops.h"
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/fsi-slave.h"
>> +
>> +#define TO_REG(x) ((x) >> 2)
>> +
>> +#define FSI_SMODE TO_REG(0x00)
>> +#define FSI_SMODE_WSTART BE_BIT(0)
>> +#define FSI_SMODE_AUX_EN BE_BIT(1)
>> +#define FSI_SMODE_SLAVE_ID BE_GENMASK(6, 7)
>> +#define FSI_SMODE_ECHO_DELAY BE_GENMASK(8, 11)
>> +#define FSI_SMODE_SEND_DELAY BE_GENMASK(12, 15)
>> +#define FSI_SMODE_LBUS_DIV BE_GENMASK(20, 23)
>> +#define FSI_SMODE_BRIEF_LEFT BE_GENMASK(24, 27)
>> +#define FSI_SMODE_BRIEF_RIGHT BE_GENMASK(28, 31)
>> +
>> +#define FSI_SDMA TO_REG(0x04)
>> +#define FSI_SISC TO_REG(0x08)
>> +#define FSI_SCISC TO_REG(0x08)
>> +#define FSI_SISM TO_REG(0x0c)
>> +#define FSI_SISS TO_REG(0x10)
>> +#define FSI_SSISM TO_REG(0x10)
>> +#define FSI_SCISM TO_REG(0x14)
>> +
>> +static uint64_t fsi_slave_read(void *opaque, hwaddr addr, unsigned
>> size)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(opaque);
>> +
>> + trace_fsi_slave_read(addr, size);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return 0;
>> + }
>> +
>> + return s->regs[TO_REG(addr)];
>> +}
>> +
>> +static void fsi_slave_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(opaque);
>> +
>> + trace_fsi_slave_write(addr, size, data);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return;
>> + }
>> +
>> + s->regs[TO_REG(addr)] = data;
>> +}
>> +
>> +static const struct MemoryRegionOps fsi_slave_ops = {
>> + .read = fsi_slave_read,
>> + .write = fsi_slave_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void fsi_slave_init(Object *o)
>> +{
>> + FSISlaveState *s = FSI_SLAVE(o);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_slave_ops,
>> + s, TYPE_FSI_SLAVE, 0x400);
>> +}
>> +
>> +static const TypeInfo fsi_slave_info = {
>> + .name = TYPE_FSI_SLAVE,
>> + .parent = TYPE_DEVICE,
>> + .instance_init = fsi_slave_init,
>> + .instance_size = sizeof(FSISlaveState),
>> +};
>> +
>> +static void fsi_slave_register_types(void)
>> +{
>> + type_register_static(&fsi_slave_info);
>> +}
>> +
>> +type_init(fsi_slave_register_types);
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> index f7c7fd1b28..8d712e77ed 100644
>> --- a/hw/fsi/Kconfig
>> +++ b/hw/fsi/Kconfig
>> @@ -1,3 +1,12 @@
>> +config FSI_CFAM
>> + bool
>> + select FSI
>> + select FSI_SCRATCHPAD
>> + select FSI_LBUS
>> +
>> +config FSI
>> + bool
>> +
>> config FSI_SCRATCHPAD
>> bool
>> select FSI_LBUS
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index d45a98c223..a9e7cd4099 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -1,2 +1,4 @@
>> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true:
>> files('engine-scratchpad.c'))
>> +system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
>> +system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index 97fd070354..752a5683a0 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -1,2 +1,9 @@
>> scratchpad_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> scratchpad_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_config_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +cfam_config_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64
>> " size=%d"
>> +cfam_unimplemented_write(uint64_t addr, uint32_t size, uint64_t
>> data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t
>> data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
>> PRIx64 " size=%d value=0x%"PRIx64
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI
2023-10-19 7:44 ` Cédric Le Goater
@ 2023-10-21 20:36 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:36 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 02:44, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> This commit models the FSI bus. CFAM is hanging out of FSI bus. The bus
>> is model such a way that it is embedded inside the FSI master which is a
>> bus controller.
>>
>> The FSI master: A controller in the platform service processor (e.g.
>> BMC) driving CFAM engine accesses into the POWER chip. At the
>> hardware level FSI is a bit-based protocol supporting synchronous and
>> DMA-driven accesses of engines in a CFAM.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> Reviewed-by: Joel Stanley <joel@jms.id.au>
>> ---
>> v2:
>> - Incorporated review comments by Joel
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/fsi-master.h | 30 ++++++
>> include/hw/fsi/fsi.h | 37 +++++++
>> hw/fsi/cfam.c | 2 +-
>> hw/fsi/fsi-master.c | 199 ++++++++++++++++++++++++++++++++++++
>> hw/fsi/fsi.c | 54 ++++++++++
>> hw/fsi/meson.build | 2 +-
>> hw/fsi/trace-events | 2 +
>> 7 files changed, 324 insertions(+), 2 deletions(-)
>> create mode 100644 include/hw/fsi/fsi-master.h
>> create mode 100644 include/hw/fsi/fsi.h
>> create mode 100644 hw/fsi/fsi-master.c
>> create mode 100644 hw/fsi/fsi.c
>>
>> diff --git a/include/hw/fsi/fsi-master.h b/include/hw/fsi/fsi-master.h
>> new file mode 100644
>> index 0000000000..847078919c
>> --- /dev/null
>> +++ b/include/hw/fsi/fsi-master.h
>> @@ -0,0 +1,30 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2019 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface Master
>> + */
>> +#ifndef FSI_FSI_MASTER_H
>> +#define FSI_FSI_MASTER_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/qdev-core.h"
>> +#include "hw/fsi/fsi.h"
>> +
>> +#define TYPE_FSI_MASTER "fsi.master"
>> +OBJECT_DECLARE_SIMPLE_TYPE(FSIMasterState, FSI_MASTER)
>> +
>> +#define FSI_MASTER_NR_REGS ((0x2e0 >> 2) + 1)
>> +
>> +typedef struct FSIMasterState {
>> + DeviceState parent;
>> + MemoryRegion iomem;
>> + MemoryRegion opb2fsi;
>> +
>> + FSIBus bus;
>> +
>> + uint32_t regs[FSI_MASTER_NR_REGS];
>> +} FSIMasterState;
>> +
>> +
>> +#endif /* FSI_FSI_H */
>> diff --git a/include/hw/fsi/fsi.h b/include/hw/fsi/fsi.h
>> new file mode 100644
>> index 0000000000..cf97645abf
>> --- /dev/null
>> +++ b/include/hw/fsi/fsi.h
>> @@ -0,0 +1,37 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface
>> + */
>> +#ifndef FSI_FSI_H
>> +#define FSI_FSI_H
>> +
>> +#include "hw/qdev-core.h"
>> +
>> +/*
>> + * TODO: Maybe unwind this dependency with const links? Store a
>> + * pointer in FSIBus?
>> + */
>> +#include "hw/fsi/cfam.h"
>> +
>> +/* Bitwise operations at the word level. */
>> +#define BE_BIT(x) BIT(31 - (x))
>> +#define GENMASK(t, b) \
>> + (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) - 1))
>> +#define BE_GENMASK(t, b) GENMASK(BE_BIT(t),
>> BE_BIT(b))
>> +
>> +#define TYPE_FSI_BUS "fsi.bus"
>> +OBJECT_DECLARE_SIMPLE_TYPE(FSIBus, FSI_BUS)
>> +
>> +/* TODO: Figure out what's best with a point-to-point bus */
>> +typedef struct FSISlaveState FSISlaveState;
>> +
>> +typedef struct FSIBus {
>> + BusState bus;
>> +
>> + /* XXX: It's point-to-point, just instantiate the slave directly
>> for now */
>> + CFAMState slave;
>> +} FSIBus;
>> +
>> +#endif
>> diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c
>> index 9044cc741b..74a10f9f4b 100644
>> --- a/hw/fsi/cfam.c
>> +++ b/hw/fsi/cfam.c
>> @@ -10,8 +10,8 @@
>> #include "qapi/error.h"
>> #include "trace.h"
>> -#include "hw/fsi/bits.h"
>> #include "hw/fsi/cfam.h"
>> +#include "hw/fsi/fsi.h"
>> #include "hw/fsi/engine-scratchpad.h"
>> #include "hw/qdev-properties.h"
>> diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
>> new file mode 100644
>> index 0000000000..8f4ae641c7
>> --- /dev/null
>> +++ b/hw/fsi/fsi-master.c
>> @@ -0,0 +1,199 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface master
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/fsi-master.h"
>> +
>> +#define TYPE_OP_BUS "opb"
>> +
>> +#define TO_REG(x) ((x) >> 2)
>> +
>> +#define FSI_MMODE TO_REG(0x000)
>> +#define FSI_MMODE_IPOLL_DMA_EN BE_BIT(0)
>> +#define FSI_MMODE_HW_ERROR_RECOVERY_EN BE_BIT(1)
>> +#define FSI_MMODE_RELATIVE_ADDRESS_EN BE_BIT(2)
>> +#define FSI_MMODE_PARITY_CHECK_EN BE_BIT(3)
>> +#define FSI_MMODE_CLOCK_DIVIDER_0 BE_GENMASK(4, 13)
>> +#define FSI_MMODE_CLOCK_DIVIDER_1 BE_GENMASK(14, 23)
>> +#define FSI_MMODE_DEBUG_EN BE_BIT(24)
>> +
>> +#define FSI_MDELAY TO_REG(0x004)
>> +#define FSI_MDELAY_ECHO_0 BE_GENMASK(0, 3)
>> +#define FSI_MDELAY_SEND_0 BE_GENMASK(4, 7)
>> +#define FSI_MDELAY_ECHO_1 BE_GENMASK(8, 11)
>> +#define FSI_MDELAY_SEND_1 BE_GENMASK(12, 15)
>> +
>> +#define FSI_MENP0 TO_REG(0x010)
>> +#define FSI_MENP32 TO_REG(0x014)
>> +#define FSI_MSENP0 TO_REG(0x018)
>> +#define FSI_MLEVP0 TO_REG(0x018)
>> +#define FSI_MSENP32 TO_REG(0x01c)
>> +#define FSI_MLEVP32 TO_REG(0x01c)
>> +#define FSI_MCENP0 TO_REG(0x020)
>> +#define FSI_MREFP0 TO_REG(0x020)
>> +#define FSI_MCENP32 TO_REG(0x024)
>> +#define FSI_MREFP32 TO_REG(0x024)
>> +
>> +#define FSI_MAEB TO_REG(0x070)
>> +#define FSI_MAEB_ANY_CPU_ERROR BE_BIT(0)
>> +#define FSI_MAEB_ANY_DMA_ERROR BE_GENMASK(1, 16)
>> +#define FSI_MAEB_ANY_PARITY_ERROR BE_BIT(17)
>> +
>> +#define FSI_MVER TO_REG(0x074)
>> +#define FSI_MVER_VERSION BE_GENMASK(0, 7)
>> +#define FSI_MVER_BRIDGES BE_GENMASK(8, 15)
>> +#define FSI_MVER_PORTS BE_GENMASK(16, 23)
>> +
>> +#define FSI_MRESP0 TO_REG(0x0d0)
>> +#define FSI_MRESP0_RESET_PORT_GENERAL BE_BIT(0)
>> +#define FSI_MRESP0_RESET_PORT_ERROR BE_BIT(1)
>> +#define FSI_MRESP0_RESET_ALL_BRIDGES_GENERAL BE_BIT(2)
>> +#define FSI_MRESP0_RESET_ALL_PORTS_GENERAL BE_BIT(3)
>> +#define FSI_MRESP0_RESET_MASTER BE_BIT(4)
>> +#define FSI_MRESP0_RESET_PARITY_ERROR_LATCH BE_BIT(5)
>> +
>> +#define FSI_MRESB0 TO_REG(0x1d0)
>> +#define FSI_MRESB0_RESET_GENERAL BE_BIT(0)
>> +#define FSI_MRESB0_RESET_ERROR BE_BIT(1)
>> +#define FSI_MRESB0_SET_DMA_SUSPEND BE_BIT(5)
>> +#define FSI_MRESB0_CLEAR_DMA_SUSPEND BE_BIT(6)
>> +#define FSI_MRESB0_SET_DELAY_MEASURE BE_BIT(7)
>> +
>> +#define FSI_MECTRL TO_REG(0x2e0)
>> +#define FSI_MECTRL_TEST_PULSE BE_GENMASK(0, 7)
>> +#define FSI_MECTRL_INHIBIT_PARITY_ERROR BE_GENMASK(8, 15)
>> +#define FSI_MECTRL_ENABLE_OPB_ERR_ACK BE_BIT(16)
>> +#define FSI_MECTRL_AUTO_TERMINATE BE_BIT(17)
>> +#define FSI_MECTRL_PORT_ERROR_FREEZE BE_BIT(18)
>> +
>> +static uint64_t fsi_master_read(void *opaque, hwaddr addr, unsigned
>> size)
>> +{
>> + FSIMasterState *s = FSI_MASTER(opaque);
>> +
>> + trace_fsi_master_read(addr, size);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return 0;
>> + }
>> +
>> + return s->regs[TO_REG(addr)];
>> +}
>> +
>> +static void fsi_master_write(void *opaque, hwaddr addr, uint64_t data,
>> + unsigned size)
>> +{
>> + FSIMasterState *s = FSI_MASTER(opaque);
>> +
>> + trace_fsi_master_write(addr, size, data);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds write: %"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return;
>> + }
>> +
>> + switch (TO_REG(addr)) {
>> + case FSI_MENP0:
>> + s->regs[FSI_MENP0] = data;
>> + break;
>> + case FSI_MENP32:
>> + s->regs[FSI_MENP32] = data;
>> + break;
>> + case FSI_MSENP0:
>> + s->regs[FSI_MENP0] |= data;
>> + break;
>> + case FSI_MSENP32:
>> + s->regs[FSI_MENP32] |= data;
>> + break;
>> + case FSI_MCENP0:
>> + s->regs[FSI_MENP0] &= ~data;
>> + break;
>> + case FSI_MCENP32:
>> + s->regs[FSI_MENP32] &= ~data;
>> + break;
>> + case FSI_MRESP0:
>> + /* Perform necessary resets leave register 0 to indicate no
>> errors */
>> + break;
>> + case FSI_MRESB0:
>> + if (data & FSI_MRESB0_RESET_GENERAL) {
>> + device_cold_reset(DEVICE(opaque));
>> + }
>> + if (data & FSI_MRESB0_RESET_ERROR) {
>> + /* FIXME: this seems dubious */
>> + device_cold_reset(DEVICE(opaque));
>> + }
>> + break;
>> + default:
>> + s->regs[TO_REG(addr)] = data;
>> + }
>> +}
>> +
>> +static const struct MemoryRegionOps fsi_master_ops = {
>> + .read = fsi_master_read,
>> + .write = fsi_master_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>> +
>> +static void fsi_master_realize(DeviceState *dev, Error **errp)
>> +{
>> + FSIMasterState *s = FSI_MASTER(dev);
>> + Error *err = NULL;
>> +
>> + qbus_init(&s->bus, sizeof(s->bus), TYPE_FSI_BUS, DEVICE(s), NULL);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_master_ops, s,
>> + TYPE_FSI_MASTER, 0x10000000);
>> + memory_region_init(&s->opb2fsi, OBJECT(s), "fsi.opb2fsi",
>> 0x10000000);
>> +
>> + object_property_set_bool(OBJECT(&s->bus), "realized", true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> +
>> + memory_region_add_subregion(&s->opb2fsi, 0, &s->bus.slave.mr);
>> +}
>> +
>> +static void fsi_master_reset(DeviceState *dev)
>> +{
>> + FSIMasterState *s = FSI_MASTER(dev);
>> +
>> + /* ASPEED default */
>> + s->regs[FSI_MVER] = 0xe0050101;
>> +}
>> +
>> +static void fsi_master_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> + dc->bus_type = TYPE_OP_BUS;
>> + dc->desc = "FSI Master";
>> + dc->realize = fsi_master_realize;
>> + dc->reset = fsi_master_reset;
>> +}
>> +
>> +static const TypeInfo fsi_master_info = {
>> + .name = TYPE_FSI_MASTER,
>> + .parent = TYPE_DEVICE,
>> + .instance_size = sizeof(FSIMasterState),
>> + .class_init = fsi_master_class_init,
>> +};
>> +
>> +static void fsi_register_types(void)
>> +{
>> + type_register_static(&fsi_master_info);
>> +}
>> +
>> +type_init(fsi_register_types);
>> diff --git a/hw/fsi/fsi.c b/hw/fsi/fsi.c
>> new file mode 100644
>> index 0000000000..fbfb28a6fc
>> --- /dev/null
>> +++ b/hw/fsi/fsi.c
>> @@ -0,0 +1,54 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM Flexible Service Interface
>> + */
>> +#include "qemu/osdep.h"
>> +
>> +#include "qapi/error.h"
>> +
>> +#include "hw/fsi/fsi.h"
>> +#include "hw/fsi/cfam.h"
>> +
>> +static void fsi_bus_realize(BusState *bus, Error **errp)
>> +{
>> + FSIBus *s = FSI_BUS(bus);
>> + Error *err = NULL;
>> +
>> + /* Note: Move it elsewhere when we add more CFAMs. */
>> + object_property_set_bool(OBJECT(&s->slave), "realized", true,
>> &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + }
>> +}
>> +
>> +static void fsi_bus_init(Object *o)
>> +{
>> + FSIBus *s = FSI_BUS(o);
>> +
>> + /* Note: Move it elsewhere when we add more CFAMs. */
>> + object_initialize_child(o, TYPE_CFAM, &s->slave, TYPE_CFAM);
>> + qdev_set_parent_bus(DEVICE(&s->slave), BUS(o), &error_abort);
>
> This should be moved elsewhere, in fsi_master_realize() I beleive.
Moved to fsi_master.
Thanks for the review.
Regards,
Ninad
>
> Thanks,
>
> C.
>
>
>> +}
>> +
>> +static void fsi_bus_class_init(ObjectClass *klass, void *data)
>> +{
>> + BusClass *bc = BUS_CLASS(klass);
>> + bc->realize = fsi_bus_realize;
>> +}
>> +
>> +static const TypeInfo fsi_bus_info = {
>> + .name = TYPE_FSI_BUS,
>> + .parent = TYPE_BUS,
>> + .instance_init = fsi_bus_init,
>> + .instance_size = sizeof(FSIBus),
>> + .class_init = fsi_bus_class_init,
>> +};
>> +
>> +static void fsi_bus_register_types(void)
>> +{
>> + type_register_static(&fsi_bus_info);
>> +}
>> +
>> +type_init(fsi_bus_register_types);
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index a9e7cd4099..f617943b4a 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -1,4 +1,4 @@
>> system_ss.add(when: 'CONFIG_FSI_LBUS', if_true: files('lbus.c'))
>> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true:
>> files('engine-scratchpad.c'))
>> system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
>> -system_ss.add(when: 'CONFIG_FSI', if_true: files('fsi-slave.c'))
>> +system_ss.add(when: 'CONFIG_FSI', if_true:
>> files('fsi.c','fsi-master.c','fsi-slave.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index 752a5683a0..d7afef0460 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -7,3 +7,5 @@ cfam_unimplemented_write(uint64_t addr, uint32_t
>> size, uint64_t data) "@0x%" PRI
>> cfam_config_write_noaddr(uint64_t addr, uint32_t size, uint64_t
>> data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
>> PRIx64 " size=%d value=0x%"PRIx64
>> +fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
>> PRIx64 " size=%d value=0x%"PRIx64
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI
2023-10-19 8:28 ` Daniel P. Berrangé
@ 2023-10-21 20:37 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:37 UTC (permalink / raw
To: Daniel P. Berrangé
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
Hello Daniel,
On 10/19/23 03:28, Daniel P. Berrangé wrote:
> On Wed, Oct 11, 2023 at 10:13:33AM -0500, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> This commit models the FSI bus. CFAM is hanging out of FSI bus. The bus
>> is model such a way that it is embedded inside the FSI master which is a
>> bus controller.
>>
>> The FSI master: A controller in the platform service processor (e.g.
>> BMC) driving CFAM engine accesses into the POWER chip. At the
>> hardware level FSI is a bit-based protocol supporting synchronous and
>> DMA-driven accesses of engines in a CFAM.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> Reviewed-by: Joel Stanley <joel@jms.id.au>
>> ---
>> v2:
>> - Incorporated review comments by Joel
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/fsi-master.h | 30 ++++++
>> include/hw/fsi/fsi.h | 37 +++++++
>> hw/fsi/cfam.c | 2 +-
>> hw/fsi/fsi-master.c | 199 ++++++++++++++++++++++++++++++++++++
>> hw/fsi/fsi.c | 54 ++++++++++
>> hw/fsi/meson.build | 2 +-
>> hw/fsi/trace-events | 2 +
>> 7 files changed, 324 insertions(+), 2 deletions(-)
>> create mode 100644 include/hw/fsi/fsi-master.h
>> create mode 100644 include/hw/fsi/fsi.h
>> create mode 100644 hw/fsi/fsi-master.c
>> create mode 100644 hw/fsi/fsi.c
>>
>> +static void fsi_master_realize(DeviceState *dev, Error **errp)
>> +{
>> + FSIMasterState *s = FSI_MASTER(dev);
>> + Error *err = NULL;
>> +
>> + qbus_init(&s->bus, sizeof(s->bus), TYPE_FSI_BUS, DEVICE(s), NULL);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &fsi_master_ops, s,
>> + TYPE_FSI_MASTER, 0x10000000);
>> + memory_region_init(&s->opb2fsi, OBJECT(s), "fsi.opb2fsi", 0x10000000);
>> +
>> + object_property_set_bool(OBJECT(&s->bus), "realized", true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
> Redundant Error object, just check return value of set_bool
Fixed.
>
>> +
>> + memory_region_add_subregion(&s->opb2fsi, 0, &s->bus.slave.mr);
>> +}
>> +static void fsi_bus_realize(BusState *bus, Error **errp)
>> +{
>> + FSIBus *s = FSI_BUS(bus);
>> + Error *err = NULL;
>> +
>> + /* Note: Move it elsewhere when we add more CFAMs. */
>> + object_property_set_bool(OBJECT(&s->slave), "realized", true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + }
> Likewise.
Fixed.
Thanks for the review.
Regards,
Ninad
>> +}
>> +
> With regards,
> Daniel
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus
2023-10-19 7:26 ` Cédric Le Goater
@ 2023-10-21 20:40 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:40 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 02:26, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
>> POWER processors. This now makes an appearance in the ASPEED SoC due
>> to tight integration of the FSI master IP with the OPB, mainly the
>> existence of an MMIO-mapping of the CFAM address straight onto a
>> sub-region of the OPB address space.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> Reviewed-by: Joel Stanley <joel@jms.id.au>
>> ---
>> v2:
>> - Incorporated review comment by Joel.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/opb.h | 43 ++++++++++
>> hw/fsi/fsi-master.c | 3 +-
>> hw/fsi/opb.c | 185 +++++++++++++++++++++++++++++++++++++++++++
>> hw/fsi/Kconfig | 4 +
>> hw/fsi/meson.build | 1 +
>> hw/fsi/trace-events | 2 +
>> 6 files changed, 236 insertions(+), 2 deletions(-)
>> create mode 100644 include/hw/fsi/opb.h
>> create mode 100644 hw/fsi/opb.c
>>
>> diff --git a/include/hw/fsi/opb.h b/include/hw/fsi/opb.h
>> new file mode 100644
>> index 0000000000..f8ce00383e
>> --- /dev/null
>> +++ b/include/hw/fsi/opb.h
>> @@ -0,0 +1,43 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM On-Chip Peripheral Bus
>> + */
>> +#ifndef FSI_OPB_H
>> +#define FSI_OPB_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/fsi/fsi-master.h"
>> +
>> +#define TYPE_OP_BUS "opb"
>> +OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
>> +
>> +typedef struct OPBus {
>> + /*< private >*/
>> + BusState bus;
>> +
>> + /*< public >*/
>> + MemoryRegion mr;
>> + AddressSpace as;
>> +
>> + /* Model OPB as dumb enough just to provide an address-space */
>> + /* TODO: Maybe don't store device state in the bus? */
>> + FSIMasterState fsi;
>> +} OPBus;
>> +
>> +typedef struct OPBusClass {
>> + BusClass parent_class;
>> +} OPBusClass;
>> +
>> +uint8_t opb_read8(OPBus *opb, hwaddr addr);
>> +uint16_t opb_read16(OPBus *opb, hwaddr addr);
>> +uint32_t opb_read32(OPBus *opb, hwaddr addr);
>> +void opb_write8(OPBus *opb, hwaddr addr, uint8_t data);
>> +void opb_write16(OPBus *opb, hwaddr addr, uint16_t data);
>> +void opb_write32(OPBus *opb, hwaddr addr, uint32_t data);
>> +
>> +void opb_fsi_master_address(OPBus *opb, hwaddr addr);
>> +void opb_opb2fsi_address(OPBus *opb, hwaddr addr);
>> +
>> +#endif /* FSI_OPB_H */
>> diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
>> index 8f4ae641c7..ede1a58e98 100644
>> --- a/hw/fsi/fsi-master.c
>> +++ b/hw/fsi/fsi-master.c
>> @@ -11,8 +11,7 @@
>> #include "trace.h"
>> #include "hw/fsi/fsi-master.h"
>> -
>> -#define TYPE_OP_BUS "opb"
>> +#include "hw/fsi/opb.h"
>> #define TO_REG(x) ((x) >> 2)
>> diff --git a/hw/fsi/opb.c b/hw/fsi/opb.c
>> new file mode 100644
>> index 0000000000..7ffd7730f7
>> --- /dev/null
>> +++ b/hw/fsi/opb.c
>> @@ -0,0 +1,185 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM On-chip Peripheral Bus
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/opb.h"
>> +
>> +static MemTxResult opb_read(OPBus *opb, hwaddr addr, void *data,
>> size_t len)
>> +{
>> + MemTxResult tx;
>> + tx = address_space_read(&opb->as, addr, MEMTXATTRS_UNSPECIFIED,
>> data,
>> + len);
>> + if (tx) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: OPB read failed: 0x%"HWADDR_PRIx" for
>> %lu\n",
>> + __func__, addr, len);
>> + }
>> + return tx;
>> +}
>> +
>> +uint8_t opb_read8(OPBus *opb, hwaddr addr)
>> +{
>> + uint8_t data = -1;
>> +
>> + (void)opb_read(opb, addr, &data, sizeof(data));
>> +
>> + return data;
>> +}
>> +
>> +uint16_t opb_read16(OPBus *opb, hwaddr addr)
>> +{
>> + uint16_t data = -1;
>> +
>> + (void)opb_read(opb, addr, &data, sizeof(data));
>> +
>> + return data;
>> +}
>> +
>> +uint32_t opb_read32(OPBus *opb, hwaddr addr)
>> +{
>> + uint32_t data = -1;
>> +
>> + (void)opb_read(opb, addr, &data, sizeof(data));
>> +
>> + return data;
>> +}
>> +
>> +static void opb_write(OPBus *opb, hwaddr addr, void *data, size_t len)
>> +{
>> + MemTxResult tx;
>> + tx = address_space_write(&opb->as, addr, MEMTXATTRS_UNSPECIFIED,
>> data,
>> + len);
>> + if (tx) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: OPB write failed: %"HWADDR_PRIx" for %lu\n",
>> + __func__, addr, len);
>> + }
>> +}
>> +
>> +void opb_write8(OPBus *opb, hwaddr addr, uint8_t data)
>> +{
>> + opb_write(opb, addr, &data, sizeof(data));
>> +}
>> +
>> +void opb_write16(OPBus *opb, hwaddr addr, uint16_t data)
>> +{
>> + opb_write(opb, addr, &data, sizeof(data));
>> +}
>> +
>> +void opb_write32(OPBus *opb, hwaddr addr, uint32_t data)
>> +{
>> + opb_write(opb, addr, &data, sizeof(data));
>> +}
>
> Please remove all the above opb_* helpers and replace them with
> address_space_rw() where they are use. Previous patch.
Fixed.
>
>
>> +void opb_fsi_master_address(OPBus *opb, hwaddr addr)
>> +{
>> + memory_region_transaction_begin();
>> + memory_region_set_address(&opb->fsi.iomem, addr);
>> + memory_region_transaction_commit();
>> +}
>> +
>> +void opb_opb2fsi_address(OPBus *opb, hwaddr addr)
>> +{
>> + memory_region_transaction_begin();
>> + memory_region_set_address(&opb->fsi.opb2fsi, addr);
>> + memory_region_transaction_commit();
>> +}
>
>
> These opb_opb2fs_* routines belong to PATCH 6.
Actually these are created in this same patch.
>
>> +static uint64_t opb_unimplemented_read(void *opaque, hwaddr addr,
>> unsigned size)
>> +{
>> + trace_opb_unimplemented_read(addr, size);
>> +
>> + return 0;
>> +}
>> +
>> +static void opb_unimplemented_write(void *opaque, hwaddr addr,
>> uint64_t data,
>> + unsigned size)
>> +{
>> + trace_opb_unimplemented_write(addr, size, data);
>> +}
>> +
>> +static const struct MemoryRegionOps opb_unimplemented_ops = {
>> + .read = opb_unimplemented_read,
>> + .write = opb_unimplemented_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> +};
>
>
> have you checked if create_unimplemented_device() could be used ?
No we can not use this function but at this time I have removed it. I
will add it later.
>
>
>> +static void opb_realize(BusState *bus, Error **errp)
>> +{
>> + OPBus *opb = OP_BUS(bus);
>> + Error *err = NULL;
>> +
>> + memory_region_init_io(&opb->mr, OBJECT(opb),
>> &opb_unimplemented_ops, opb,
>> + NULL, UINT32_MAX);
>> + address_space_init(&opb->as, &opb->mr, "opb");
>> +
>> + object_property_set_bool(OBJECT(&opb->fsi), "realized", true,
>> &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
>> + memory_region_add_subregion(&opb->mr, 0x80000000, &opb->fsi.iomem);
>> +
>> + /* OPB2FSI region */
>> + /*
>> + * Avoid endianness issues by mapping each slave's memory region
>> directly.
>> + * Manually bridging multiple address-spaces causes endian swapping
>> + * headaches as memory_region_dispatch_read() and
>> + * memory_region_dispatch_write() correct the endianness based
>> on the
>> + * target machine endianness and not relative to the device
>> endianness on
>> + * either side of the bridge.
>> + */
>> + /*
>> + * XXX: This is a bit hairy and will need to be fixed when I
>> sort out the
>> + * bus/slave relationship and any changes to the CFAM modelling
>> (multiple
>> + * slaves, LBUS)
>> + */
>> + memory_region_add_subregion(&opb->mr, 0xa0000000,
>> &opb->fsi.opb2fsi);
>> +}
>> +
>> +static void opb_init(Object *o)
>> +{
>> + OPBus *opb = OP_BUS(o);
>> +
>> + object_initialize_child(o, "fsi-master", &opb->fsi,
>> TYPE_FSI_MASTER);
>> + qdev_set_parent_bus(DEVICE(&opb->fsi), BUS(o), &error_abort);
>
>
> This fsi object should be a child of TYPE_ASPEED_APB2OPB and created
> with qdev_realize_and_unref() in aspeed_apb2opb_realize().
No, Actually master is connect to opb bus. So this is at the correct
location.
>
>
>> +}
>> +
>> +static void opb_finalize(Object *o)
>> +{
>> + OPBus *opb = OP_BUS(o);
>> +
>> + address_space_destroy(&opb->as);
>> +}
>
> The finalize op is not strictly necessary.
Removed.
Thanks for the review.
Regards,
Ninad
>
> Thanks,
>
> C.
>
>
>> +static void opb_class_init(ObjectClass *klass, void *data)
>> +{
>> + BusClass *bc = BUS_CLASS(klass);
>> + bc->realize = opb_realize;
>> +}
>> +
>> +static const TypeInfo opb_info = {
>> + .name = TYPE_OP_BUS,
>> + .parent = TYPE_BUS,
>> + .instance_init = opb_init,
>> + .instance_finalize = opb_finalize,
>> + .instance_size = sizeof(OPBus),
>> + .class_init = opb_class_init,
>> + .class_size = sizeof(OPBusClass),
>> +};
>> +
>> +static void opb_register_types(void)
>> +{
>> + type_register_static(&opb_info);
>> +}
>> +
>> +type_init(opb_register_types);
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> index 8d712e77ed..0f6e6d331a 100644
>> --- a/hw/fsi/Kconfig
>> +++ b/hw/fsi/Kconfig
>> @@ -1,3 +1,7 @@
>> +config FSI_OPB
>> + bool
>> + select FSI_CFAM
>> +
>> config FSI_CFAM
>> bool
>> select FSI
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index f617943b4a..407b8c2775 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -2,3 +2,4 @@ system_ss.add(when: 'CONFIG_FSI_LBUS', if_true:
>> files('lbus.c'))
>> system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true:
>> files('engine-scratchpad.c'))
>> system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
>> system_ss.add(when: 'CONFIG_FSI', if_true:
>> files('fsi.c','fsi-master.c','fsi-slave.c'))
>> +system_ss.add(when: 'CONFIG_FSI_OPB', if_true: files('opb.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index d7afef0460..ec9bab2fe8 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -9,3 +9,5 @@ fsi_slave_read(uint64_t addr, uint32_t size) "@0x%"
>> PRIx64 " size=%d"
>> fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%"
>> PRIx64 " size=%d value=0x%"PRIx64
>> fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> fsi_master_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 "
>> size=%d"
>> +opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus
2023-10-19 8:30 ` Daniel P. Berrangé
@ 2023-10-21 20:42 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:42 UTC (permalink / raw
To: Daniel P. Berrangé
Cc: qemu-devel, clg, peter.maydell, andrew, joel, pbonzini,
marcandre.lureau, thuth, philmd, lvivier, qemu-arm
Hello Daniel,
On 10/19/23 03:30, Daniel P. Berrangé wrote:
> On Wed, Oct 11, 2023 at 10:13:34AM -0500, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> The On-Chip Peripheral Bus (OPB): A low-speed bus typically found in
>> POWER processors. This now makes an appearance in the ASPEED SoC due
>> to tight integration of the FSI master IP with the OPB, mainly the
>> existence of an MMIO-mapping of the CFAM address straight onto a
>> sub-region of the OPB address space.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> Reviewed-by: Joel Stanley <joel@jms.id.au>
>> ---
>> v2:
>> - Incorporated review comment by Joel.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> include/hw/fsi/opb.h | 43 ++++++++++
>> hw/fsi/fsi-master.c | 3 +-
>> hw/fsi/opb.c | 185 +++++++++++++++++++++++++++++++++++++++++++
>> hw/fsi/Kconfig | 4 +
>> hw/fsi/meson.build | 1 +
>> hw/fsi/trace-events | 2 +
>> 6 files changed, 236 insertions(+), 2 deletions(-)
>> create mode 100644 include/hw/fsi/opb.h
>> create mode 100644 hw/fsi/opb.c
>>
>> diff --git a/include/hw/fsi/opb.h b/include/hw/fsi/opb.h
>> new file mode 100644
>> index 0000000000..f8ce00383e
>> --- /dev/null
>> +++ b/include/hw/fsi/opb.h
>> @@ -0,0 +1,43 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM On-Chip Peripheral Bus
>> + */
>> +#ifndef FSI_OPB_H
>> +#define FSI_OPB_H
>> +
>> +#include "exec/memory.h"
>> +#include "hw/fsi/fsi-master.h"
>> +
>> +#define TYPE_OP_BUS "opb"
>> +OBJECT_DECLARE_SIMPLE_TYPE(OPBus, OP_BUS)
>> +
>> +typedef struct OPBus {
>> + /*< private >*/
>> + BusState bus;
>> +
>> + /*< public >*/
>> + MemoryRegion mr;
>> + AddressSpace as;
>> +
>> + /* Model OPB as dumb enough just to provide an address-space */
>> + /* TODO: Maybe don't store device state in the bus? */
>> + FSIMasterState fsi;
>> +} OPBus;
>> +
>> +typedef struct OPBusClass {
>> + BusClass parent_class;
>> +} OPBusClass;
>> +
>> +uint8_t opb_read8(OPBus *opb, hwaddr addr);
>> +uint16_t opb_read16(OPBus *opb, hwaddr addr);
>> +uint32_t opb_read32(OPBus *opb, hwaddr addr);
>> +void opb_write8(OPBus *opb, hwaddr addr, uint8_t data);
>> +void opb_write16(OPBus *opb, hwaddr addr, uint16_t data);
>> +void opb_write32(OPBus *opb, hwaddr addr, uint32_t data);
>> +
>> +void opb_fsi_master_address(OPBus *opb, hwaddr addr);
>> +void opb_opb2fsi_address(OPBus *opb, hwaddr addr);
>> +
>> +#endif /* FSI_OPB_H */
>> diff --git a/hw/fsi/fsi-master.c b/hw/fsi/fsi-master.c
>> index 8f4ae641c7..ede1a58e98 100644
>> --- a/hw/fsi/fsi-master.c
>> +++ b/hw/fsi/fsi-master.c
>> @@ -11,8 +11,7 @@
>> #include "trace.h"
>>
>> #include "hw/fsi/fsi-master.h"
>> -
>> -#define TYPE_OP_BUS "opb"
>> +#include "hw/fsi/opb.h"
>>
>> #define TO_REG(x) ((x) >> 2)
>>
>> diff --git a/hw/fsi/opb.c b/hw/fsi/opb.c
>> new file mode 100644
>> index 0000000000..7ffd7730f7
>> --- /dev/null
>> +++ b/hw/fsi/opb.c
>> @@ -0,0 +1,185 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * IBM On-chip Peripheral Bus
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qapi/error.h"
>> +#include "qemu/log.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/opb.h"
>> +
>> +static MemTxResult opb_read(OPBus *opb, hwaddr addr, void *data, size_t len)
>> +{
>> + MemTxResult tx;
>> + tx = address_space_read(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
>> + len);
>> + if (tx) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: OPB read failed: 0x%"HWADDR_PRIx" for %lu\n",
>> + __func__, addr, len);
>> + }
>> + return tx;
>> +}
> Use a tracepoint rather than an always-on log
Done.
>> +
>> +uint8_t opb_read8(OPBus *opb, hwaddr addr)
>> +{
>> + uint8_t data = -1;
>> +
>> + (void)opb_read(opb, addr, &data, sizeof(data));
>> +
>> + return data;
>> +}
>> +
>> +uint16_t opb_read16(OPBus *opb, hwaddr addr)
>> +{
>> + uint16_t data = -1;
>> +
>> + (void)opb_read(opb, addr, &data, sizeof(data));
>> +
>> + return data;
>> +}
>> +
>> +uint32_t opb_read32(OPBus *opb, hwaddr addr)
>> +{
>> + uint32_t data = -1;
>> +
>> + (void)opb_read(opb, addr, &data, sizeof(data));
>> +
>> + return data;
>> +}
>> +
>> +static void opb_write(OPBus *opb, hwaddr addr, void *data, size_t len)
>> +{
>> + MemTxResult tx;
>> + tx = address_space_write(&opb->as, addr, MEMTXATTRS_UNSPECIFIED, data,
>> + len);
>> + if (tx) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: OPB write failed: %"HWADDR_PRIx" for %lu\n",
>> + __func__, addr, len);
>> + }
>> +}
> Again tracepoint
Done
>
>
>> +static void opb_realize(BusState *bus, Error **errp)
>> +{
>> + OPBus *opb = OP_BUS(bus);
>> + Error *err = NULL;
>> +
>> + memory_region_init_io(&opb->mr, OBJECT(opb), &opb_unimplemented_ops, opb,
>> + NULL, UINT32_MAX);
>> + address_space_init(&opb->as, &opb->mr, "opb");
>> +
>> + object_property_set_bool(OBJECT(&opb->fsi), "realized", true, &err);
>> + if (err) {
>> + error_propagate(errp, err);
>> + return;
>> + }
> Redundant local error object
Fixed.
>
>> + memory_region_add_subregion(&opb->mr, 0x80000000, &opb->fsi.iomem);
>> +
>> + /* OPB2FSI region */
>> + /*
>> + * Avoid endianness issues by mapping each slave's memory region directly.
>> + * Manually bridging multiple address-spaces causes endian swapping
>> + * headaches as memory_region_dispatch_read() and
>> + * memory_region_dispatch_write() correct the endianness based on the
>> + * target machine endianness and not relative to the device endianness on
>> + * either side of the bridge.
>> + */
>> + /*
>> + * XXX: This is a bit hairy and will need to be fixed when I sort out the
>> + * bus/slave relationship and any changes to the CFAM modelling (multiple
>> + * slaves, LBUS)
>> + */
>> + memory_region_add_subregion(&opb->mr, 0xa0000000, &opb->fsi.opb2fsi);
>> +}
>> +
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index d7afef0460..ec9bab2fe8 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -9,3 +9,5 @@ fsi_slave_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> fsi_slave_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> fsi_master_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> fsi_master_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
>> +opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
> Please consistently use an 'fsi_' prefix for all trace points, as it
> makes it possible to enable all tracing for this subsystem using a
> wildcard match
Good suggestion. Fixed it.
Thanks for the review.
Regards,
Ninad
>
>
> With regards,
> Daniel
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface
2023-10-19 7:16 ` Cédric Le Goater
@ 2023-10-21 20:43 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:43 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 02:16, Cédric Le Goater wrote:
> On 10/11/23 17:13, Ninad Palsule wrote:
>> This is a part of patchset where IBM's Flexible Service Interface is
>> introduced.
>>
>> An APB-to-OPB bridge enabling access to the OPB from the ARM core in
>> the AST2600. Hardware limitations prevent the OPB from being directly
>> mapped into APB, so all accesses are indirect through the bridge.
>>
>> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
>> Signed-off-by: Cédric Le Goater <clg@kaod.org>
>> Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
>> ---
>> v2:
>> - Incorporated review comments by Joel
>> v3:
>> - Incorporated review comments by Thomas Huth
>> v4:
>> - Compile FSI with ASPEED_SOC only.
>> v5:
>> - Incorporated review comments by Cedric.
>> ---
>> meson.build | 1 +
>> hw/fsi/trace.h | 1 +
>> include/hw/fsi/aspeed-apb2opb.h | 33 +++
>> hw/fsi/aspeed-apb2opb.c | 350 ++++++++++++++++++++++++++++++++
>> hw/arm/Kconfig | 1 +
>> hw/fsi/Kconfig | 4 +
>> hw/fsi/meson.build | 1 +
>> hw/fsi/trace-events | 2 +
>> 8 files changed, 393 insertions(+)
>> create mode 100644 hw/fsi/trace.h
>> create mode 100644 include/hw/fsi/aspeed-apb2opb.h
>> create mode 100644 hw/fsi/aspeed-apb2opb.c
>>
>> diff --git a/meson.build b/meson.build
>> index 98e68ef0b1..1a722693a6 100644
>> --- a/meson.build
>> +++ b/meson.build
>> @@ -3244,6 +3244,7 @@ if have_system
>> 'hw/char',
>> 'hw/display',
>> 'hw/dma',
>> + 'hw/fsi',
>> 'hw/hyperv',
>> 'hw/i2c',
>> 'hw/i386',
>> diff --git a/hw/fsi/trace.h b/hw/fsi/trace.h
>> new file mode 100644
>> index 0000000000..ee67c7fb04
>> --- /dev/null
>> +++ b/hw/fsi/trace.h
>> @@ -0,0 +1 @@
>> +#include "trace/trace-hw_fsi.h"
>> diff --git a/include/hw/fsi/aspeed-apb2opb.h
>> b/include/hw/fsi/aspeed-apb2opb.h
>> new file mode 100644
>> index 0000000000..a81ae67023
>> --- /dev/null
>> +++ b/include/hw/fsi/aspeed-apb2opb.h
>> @@ -0,0 +1,33 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * ASPEED APB2OPB Bridge
>> + */
>> +#ifndef FSI_ASPEED_APB2OPB_H
>> +#define FSI_ASPEED_APB2OPB_H
>> +
>> +#include "hw/sysbus.h"
>> +#include "hw/fsi/opb.h"
>> +
>> +#define TYPE_ASPEED_APB2OPB "aspeed.apb2opb"
>> +OBJECT_DECLARE_SIMPLE_TYPE(AspeedAPB2OPBState, ASPEED_APB2OPB)
>> +
>> +#define ASPEED_APB2OPB_NR_REGS ((0xe8 >> 2) + 1)
>> +
>> +#define ASPEED_FSI_NUM 2
>> +
>> +typedef struct AspeedAPB2OPBState {
>> + /*< private >*/
>> + SysBusDevice parent_obj;
>> +
>> + /*< public >*/
>> + MemoryRegion iomem;
>> +
>> + uint32_t regs[ASPEED_APB2OPB_NR_REGS];
>> + qemu_irq irq;
>> +
>> + OPBus opb[ASPEED_FSI_NUM];
>> +} AspeedAPB2OPBState;
>> +
>> +#endif /* FSI_ASPEED_APB2OPB_H */
>> diff --git a/hw/fsi/aspeed-apb2opb.c b/hw/fsi/aspeed-apb2opb.c
>> new file mode 100644
>> index 0000000000..e4efc08778
>> --- /dev/null
>> +++ b/hw/fsi/aspeed-apb2opb.c
>> @@ -0,0 +1,350 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + * Copyright (C) 2023 IBM Corp.
>> + *
>> + * ASPEED APB-OPB FSI interface
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qemu/log.h"
>> +#include "qom/object.h"
>> +#include "qapi/error.h"
>> +#include "trace.h"
>> +
>> +#include "hw/fsi/aspeed-apb2opb.h"
>> +#include "hw/qdev-core.h"
>> +
>> +#define TO_REG(x) (x >> 2)
>> +#define GENMASK(t, b) (((1ULL << ((t) + 1)) - 1) & ~((1ULL << (b)) -
>> 1))
>> +
>> +#define APB2OPB_VERSION TO_REG(0x00)
>> +#define APB2OPB_VERSION_VER GENMASK(7, 0)
>> +
>> +#define APB2OPB_TRIGGER TO_REG(0x04)
>> +#define APB2OPB_TRIGGER_EN BIT(0)
>> +
>> +#define APB2OPB_CONTROL TO_REG(0x08)
>> +#define APB2OPB_CONTROL_OFF GENMASK(31, 13)
>> +
>> +#define APB2OPB_OPB2FSI TO_REG(0x0c)
>> +#define APB2OPB_OPB2FSI_OFF GENMASK(31, 22)
>> +
>> +#define APB2OPB_OPB0_SEL TO_REG(0x10)
>> +#define APB2OPB_OPB1_SEL TO_REG(0x28)
>> +#define APB2OPB_OPB_SEL_EN BIT(0)
>> +
>> +#define APB2OPB_OPB0_MODE TO_REG(0x14)
>> +#define APB2OPB_OPB1_MODE TO_REG(0x2c)
>> +#define APB2OPB_OPB_MODE_RD BIT(0)
>> +
>> +#define APB2OPB_OPB0_XFER TO_REG(0x18)
>> +#define APB2OPB_OPB1_XFER TO_REG(0x30)
>> +#define APB2OPB_OPB_XFER_FULL BIT(1)
>> +#define APB2OPB_OPB_XFER_HALF BIT(0)
>> +
>> +#define APB2OPB_OPB0_ADDR TO_REG(0x1c)
>> +#define APB2OPB_OPB0_WRITE_DATA TO_REG(0x20)
>> +
>> +#define APB2OPB_OPB1_DMA_EN TO_REG(0x24)
>> +#define APB2OPB_OPB1_DMA_EN_3 BIT(3)
>> +#define APB2OPB_OPB1_DMA_EN_2 BIT(2)
>> +#define APB2OPB_OPB1_DMA_EN_1 BIT(1)
>> +#define APB2OPB_OPB1_DMA_EN_0 BIT(0)
>> +
>> +#define APB2OPB_OPB1_ADDR TO_REG(0x34)
>> +#define APB2OPB_OPB1_WRITE_DATA TO_REG(0x38)
>> +
>> +#define APB2OPB_OPB_CLK TO_REG(0x3c)
>> +#define APB2OPB_OPB_CLK_SYNC BIT(0)
>> +
>> +#define APB2OPB_IRQ_CLEAR TO_REG(0x40)
>> +#define APB2OPB_IRQ_CLEAR_EN BIT(0)
>> +
>> +#define APB2OPB_IRQ_MASK TO_REG(0x44)
>> +#define APB2OPB_IRQ_MASK_OPB1_TX_ACK BIT(17)
>> +#define APB2OPB_IRQ_MASK_OPB0_TX_ACK BIT(16)
>> +#define APB2OPB_IRQ_MASK_CH3_TCONT BIT(15)
>> +#define APB2OPB_IRQ_MASK_CH2_TCONT BIT(14)
>> +#define APB2OPB_IRQ_MASK_CH1_TCONT BIT(13)
>> +#define APB2OPB_IRQ_MASK_CH0_TCONT BIT(12)
>> +#define APB2OPB_IRQ_MASK_CH3_FIFO_EMPTY BIT(11)
>> +#define APB2OPB_IRQ_MASK_CH2_FIFO_EMPTY BIT(10)
>> +#define APB2OPB_IRQ_MASK_CH1_FIFO_EMPTY BIT(9)
>> +#define APB2OPB_IRQ_MASK_CH0_FIFO_EMPTY BIT(8)
>> +#define APB2OPB_IRQ_MASK_CH3_FIFO_FULL BIT(7)
>> +#define APB2OPB_IRQ_MASK_CH2_FIFO_FULL BIT(6)
>> +#define APB2OPB_IRQ_MASK_CH1_FIFO_FULL BIT(5)
>> +#define APB2OPB_IRQ_MASK_CH0_FIFO_FULL BIT(4)
>> +#define APB2OPB_IRQ_MASK_CH3_DMA_EOT BIT(3)
>> +#define APB2OPB_IRQ_MASK_CH2_DMA_EOT BIT(2)
>> +#define APB2OPB_IRQ_MASK_CH1_DMA_EOT BIT(1)
>> +#define APB2OPB_IRQ_MASK_CH0_DMA_EOT BIT(0)
>> +
>> +#define APB2OPB_IRQ_STS TO_REG(0x48)
>> +#define APB2OPB_IRQ_STS_MASTER_ERROR BIT(28)
>> +#define APB2OPB_IRQ_STS_PORT_ERROR BIT(27)
>> +#define APB2OPB_IRQ_STS_HOTPLUG BIT(26)
>> +#define APB2OPB_IRQ_STS_SLAVE_7 BIT(25)
>> +#define APB2OPB_IRQ_STS_SLAVE_6 BIT(24)
>> +#define APB2OPB_IRQ_STS_SLAVE_5 BIT(23)
>> +#define APB2OPB_IRQ_STS_SLAVE_4 BIT(22)
>> +#define APB2OPB_IRQ_STS_SLAVE_3 BIT(21)
>> +#define APB2OPB_IRQ_STS_SLAVE_2 BIT(20)
>> +#define APB2OPB_IRQ_STS_SLAVE_1 BIT(19)
>> +#define APB2OPB_IRQ_STS_SLAVE_0 BIT(18)
>> +#define APB2OPB_IRQ_STS_OPB1_TX_ACK BIT(17)
>> +#define APB2OPB_IRQ_STS_OPB0_TX_ACK BIT(16)
>> +#define APB2OPB_IRQ_STS_CH3_TCONT BIT(15)
>> +#define APB2OPB_IRQ_STS_CH2_TCONT BIT(14)
>> +#define APB2OPB_IRQ_STS_CH1_TCONT BIT(13)
>> +#define APB2OPB_IRQ_STS_CH0_TCONT BIT(12)
>> +#define APB2OPB_IRQ_STS_CH3_FIFO_EMPTY BIT(11)
>> +#define APB2OPB_IRQ_STS_CH2_FIFO_EMPTY BIT(10)
>> +#define APB2OPB_IRQ_STS_CH1_FIFO_EMPTY BIT(9)
>> +#define APB2OPB_IRQ_STS_CH0_FIFO_EMPTY BIT(8)
>> +#define APB2OPB_IRQ_STS_CH3_FIFO_FULL BIT(7)
>> +#define APB2OPB_IRQ_STS_CH2_FIFO_FULL BIT(6)
>> +#define APB2OPB_IRQ_STS_CH1_FIFO_FULL BIT(5)
>> +#define APB2OPB_IRQ_STS_CH0_FIFO_FULL BIT(4)
>> +#define APB2OPB_IRQ_STS_CH3_DMA_EOT BIT(3)
>> +#define APB2OPB_IRQ_STS_CH2_DMA_EOT BIT(2)
>> +#define APB2OPB_IRQ_STS_CH1_DMA_EOT BIT(1)
>> +#define APB2OPB_IRQ_STS_CH0_DMA_EOT BIT(0)
>> +
>> +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN TO_REG(0x4c)
>> +#define APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE 0x0011101b
>> +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN TO_REG(0x50)
>> +#define APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE 0x0c330f3f
>> +#define APB2OPB_OPB1_WRITE_WORD_ENDIAN TO_REG(0x54)
>> +#define APB2OPB_OPB1_WRITE_BYTE_ENDIAN TO_REG(0x58)
>> +#define APB2OPB_OPB0_READ_BYTE_ENDIAN TO_REG(0x5c)
>> +#define APB2OPB_OPB0_READ_WORD_ENDIAN_BE 0x00030b1b
>> +#define APB2OPB_OPB1_READ_BYTE_ENDIAN TO_REG(0x60)
>> +
>> +#define APB2OPB_RETRY TO_REG(0x64)
>> +#define APB2OPB_RETRY_COUNTER GENMASK(15, 0)
>> +
>> +#define APB2OPB_OPB0_STATUS TO_REG(0x80)
>> +#define APB2OPB_OPB1_STATUS TO_REG(0x8c)
>> +#define APB2OPB_OPB_STATUS_TIMEOUT BIT(4)
>> +#define APB2OPB_OPB_STATUS_RETRY BIT(3)
>> +#define APB2OPB_OPB_STATUS_ERROR_ACK BIT(2)
>> +#define APB2OPB_OPB_STATUS_FW_ACK BIT(1)
>> +#define APB2OPB_OPB_STATUS_HW_ACK BIT(0)
>> +
>> +#define APB2OPB_OPB0_READ_DATA TO_REG(0x84)
>> +
>> +#define APB2OPB_OPB1_DMA_STATUS TO_REG(0x88)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH3_EOT BIT(7)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH2_EOT BIT(6)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH1_EOT BIT(5)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH0_EOT BIT(4)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH3_REQ BIT(3)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH2_REQ BIT(2)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH1_REQ BIT(1)
>> +#define APB2OPB_OPB1_DMA_STATUS_CH0_REQ BIT(0)
>> +
>> +#define APB2OPB_OPB1_READ_DATA TO_REG(0x90)
>
> I think you can reduce this list of define to the minimum and
> re-introduce
> the definitions when they are needed.
Removed which are not required.
>
>> +
>> +static uint64_t aspeed_apb2opb_read(void *opaque, hwaddr addr,
>> unsigned size)
>> +{
>> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
>> +
>> + trace_aspeed_apb2opb_read(addr, size);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return 0;
>> + }
>> +
>> + return s->regs[TO_REG(addr)];
>> +}
>> +
>> +static void aspeed_apb2opb_write(void *opaque, hwaddr addr, uint64_t
>> data,
>> + unsigned size)
>> +{
>> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(opaque);
>> +
>> + trace_aspeed_apb2opb_write(addr, size, data);
>> +
>> + if (addr + size > sizeof(s->regs)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Out of bounds write: %"HWADDR_PRIx" for
>> %u\n",
>> + __func__, addr, size);
>> + return;
>> + }
>> +
>> + switch (TO_REG(addr)) {
>> + case APB2OPB_CONTROL:
>> + opb_fsi_master_address(&s->opb[0], data & APB2OPB_CONTROL_OFF);
>> + break;
>> + case APB2OPB_OPB2FSI:
>> + opb_opb2fsi_address(&s->opb[0], data & APB2OPB_OPB2FSI_OFF);
>> + break;
>> + case APB2OPB_OPB0_WRITE_WORD_ENDIAN:
>> + if (data != APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Bridge needs to be driven as BE
>> (0x%x)\n",
>> + __func__, APB2OPB_OPB0_WRITE_WORD_ENDIAN_BE);
>> + }
>> + break;
>> + case APB2OPB_OPB0_WRITE_BYTE_ENDIAN:
>> + if (data != APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Bridge needs to be driven as BE
>> (0x%x)\n",
>> + __func__, APB2OPB_OPB0_WRITE_BYTE_ENDIAN_BE);
>> + }
>> + break;
>> + case APB2OPB_OPB0_READ_BYTE_ENDIAN:
>> + if (data != APB2OPB_OPB0_READ_WORD_ENDIAN_BE) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "%s: Bridge needs to be driven as BE
>> (0x%x)\n",
>> + __func__, APB2OPB_OPB0_READ_WORD_ENDIAN_BE);
>> + }
>> + break;
>> + case APB2OPB_TRIGGER:
>> + {
>> + uint32_t opb, op_mode, op_size, op_addr, op_data;
>> +
>> + assert((s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) ^
>> + (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN));
>> +
>> + if (s->regs[APB2OPB_OPB0_SEL] & APB2OPB_OPB_SEL_EN) {
>> + opb = 0;
>> + op_mode = s->regs[APB2OPB_OPB0_MODE];
>> + op_size = s->regs[APB2OPB_OPB0_XFER];
>> + op_addr = s->regs[APB2OPB_OPB0_ADDR];
>> + op_data = s->regs[APB2OPB_OPB0_WRITE_DATA];
>> + } else if (s->regs[APB2OPB_OPB1_SEL] & APB2OPB_OPB_SEL_EN) {
>> + opb = 1;
>> + op_mode = s->regs[APB2OPB_OPB1_MODE];
>> + op_size = s->regs[APB2OPB_OPB1_XFER];
>> + op_addr = s->regs[APB2OPB_OPB1_ADDR];
>> + op_data = s->regs[APB2OPB_OPB1_WRITE_DATA];
>> + } else {
>> + g_assert_not_reached();
>
> This makes the memop quite fatal. A LOG_GUEST_ERROR would be more
> appropriate.
Fixed.
>
>> + }
>> +
>> + if (op_size & ~(APB2OPB_OPB_XFER_HALF |
>> APB2OPB_OPB_XFER_FULL)) {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "OPB transaction failed: Unrecognised
>> access width: %d\n",
>> + op_size);
>> + return;
>> + }
>> +
>> + op_size += 1;
>> +
>> + if (op_mode & APB2OPB_OPB_MODE_RD) {
>> + int index = opb ? APB2OPB_OPB1_READ_DATA
>> + : APB2OPB_OPB0_READ_DATA;
>> +
>> + switch (op_size) {
>> + case 1:
>> + s->regs[index] = opb_read8(&s->opb[opb], op_addr);
>> + break;
>> + case 2:
>> + s->regs[index] = opb_read16(&s->opb[opb], op_addr);
>> + break;
>> + case 4:
>> + s->regs[index] = opb_read32(&s->opb[opb], op_addr);
>> + break;
>> + default:
>> + g_assert_not_reached(); /* should have bailed above */
>> + }
>> + } else {
>> + /* FIXME: Endian swizzling */
>> + switch (op_size) {
>> + case 1:
>> + opb_write8(&s->opb[opb], op_addr, op_data);
>> + break;
>> + case 2:
>> + opb_write16(&s->opb[opb], op_addr, op_data);
>> + break;
>> + case 4:
>> + opb_write32(&s->opb[opb], op_addr, op_data);
>> + break;
>> + default:
>> + g_assert_not_reached(); /* should have bailed above */
>> + }
>> + }
>> + s->regs[APB2OPB_IRQ_STS] |= opb ? APB2OPB_IRQ_STS_OPB1_TX_ACK
>> + : APB2OPB_IRQ_STS_OPB0_TX_ACK;
>> + break;
>> + }
>> + }
>> +
>> + s->regs[TO_REG(addr)] = data;
>> +}
>> +
>> +static const struct MemoryRegionOps aspeed_apb2opb_ops = {
>> + .read = aspeed_apb2opb_read,
>> + .write = aspeed_apb2opb_write,
>> + .valid.max_access_size = 4,
>> + .valid.min_access_size = 4,
>> + .impl.max_access_size = 4,
>> + .impl.min_access_size = 4,
>> + .endianness = DEVICE_LITTLE_ENDIAN,
>> +};
>> +
>> +static void aspeed_apb2opb_realize(DeviceState *dev, Error **errp)
>> +{
>> + SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev);
>> +
>> + qbus_init(&s->opb[0], sizeof(s->opb[0]), TYPE_OP_BUS,
>> + DEVICE(s), NULL);
>> + qbus_init(&s->opb[1], sizeof(s->opb[1]), TYPE_OP_BUS,
>> + DEVICE(s), NULL);
>> +
>> + sysbus_init_irq(sbd, &s->irq);
>> +
>> + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_apb2opb_ops, s,
>> + TYPE_ASPEED_APB2OPB, 0x1000);
>> + sysbus_init_mmio(sbd, &s->iomem);
>> +}
>> +
>> +static void aspeed_apb2opb_reset(DeviceState *dev)
>> +{
>> + AspeedAPB2OPBState *s = ASPEED_APB2OPB(dev);
>> +
>> + memset(s->regs, 0, sizeof(s->regs));
>> +
>> + s->regs[APB2OPB_VERSION] = 0x000000a1;
>> +
>> + /*
>> + * The following magic values came from AST2600 data sheet
>> + * The register values are defined under section "FSI controller"
>> + * as initial values.
>> + */
>> + s->regs[APB2OPB_OPB0_WRITE_WORD_ENDIAN] = 0x0044eee4;
>> + s->regs[APB2OPB_OPB0_WRITE_BYTE_ENDIAN] = 0x0055aaff;
>> + s->regs[APB2OPB_OPB1_WRITE_WORD_ENDIAN] = 0x00117717;
>> + s->regs[APB2OPB_OPB1_WRITE_BYTE_ENDIAN] = 0xffaa5500;
>> + s->regs[APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x0044eee4;
>> + s->regs[APB2OPB_OPB0_READ_BYTE_ENDIAN] = 0x00117717;
>
> You could use a reset array to set the values. See SCU.
Added reset array.
Thanks for the review.
Regards,
Ninad
>
>
> The reset looks good.
>
> Thanks,
>
> C.
>
>
>> +}
>> +
>> +static void aspeed_apb2opb_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> + dc->desc = "ASPEED APB2OPB Bridge";
>> + dc->realize = aspeed_apb2opb_realize;
>> + dc->reset = aspeed_apb2opb_reset;
>> +}
>> +
>> +static const TypeInfo aspeed_apb2opb_info = {
>> + .name = TYPE_ASPEED_APB2OPB,
>> + .parent = TYPE_SYS_BUS_DEVICE,
>> + .instance_size = sizeof(AspeedAPB2OPBState),
>> + .class_init = aspeed_apb2opb_class_init,
>> +};
>> +
>> +static void aspeed_apb2opb_register_types(void)
>> +{
>> + type_register_static(&aspeed_apb2opb_info);
>> +}
>> +
>> +type_init(aspeed_apb2opb_register_types);
>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>> index 7e68348440..d963de74c9 100644
>> --- a/hw/arm/Kconfig
>> +++ b/hw/arm/Kconfig
>> @@ -555,6 +555,7 @@ config ASPEED_SOC
>> select LED
>> select PMBUS
>> select MAX31785
>> + select FSI_APB2OPB_ASPEED
>> config MPS2
>> bool
>> diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig
>> index 0f6e6d331a..6bbcb8f6ca 100644
>> --- a/hw/fsi/Kconfig
>> +++ b/hw/fsi/Kconfig
>> @@ -1,3 +1,7 @@
>> +config FSI_APB2OPB_ASPEED
>> + bool
>> + select FSI_OPB
>> +
>> config FSI_OPB
>> bool
>> select FSI_CFAM
>> diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build
>> index 407b8c2775..1bc6bb63cc 100644
>> --- a/hw/fsi/meson.build
>> +++ b/hw/fsi/meson.build
>> @@ -3,3 +3,4 @@ system_ss.add(when: 'CONFIG_FSI_SCRATCHPAD', if_true:
>> files('engine-scratchpad.c
>> system_ss.add(when: 'CONFIG_FSI_CFAM', if_true: files('cfam.c'))
>> system_ss.add(when: 'CONFIG_FSI', if_true:
>> files('fsi.c','fsi-master.c','fsi-slave.c'))
>> system_ss.add(when: 'CONFIG_FSI_OPB', if_true: files('opb.c'))
>> +system_ss.add(when: 'CONFIG_FSI_APB2OPB_ASPEED', if_true:
>> files('aspeed-apb2opb.c'))
>> diff --git a/hw/fsi/trace-events b/hw/fsi/trace-events
>> index ec9bab2fe8..4d4eb47c0b 100644
>> --- a/hw/fsi/trace-events
>> +++ b/hw/fsi/trace-events
>> @@ -11,3 +11,5 @@ fsi_master_read(uint64_t addr, uint32_t size)
>> "@0x%" PRIx64 " size=%d"
>> fsi_master_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> opb_unimplemented_read(uint64_t addr, uint32_t size) "@0x%" PRIx64
>> " size=%d"
>> opb_unimplemented_write(uint64_t addr, uint32_t size, uint64_t
>> data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>> +aspeed_apb2opb_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 "
>> size=%d"
>> +aspeed_apb2opb_write(uint64_t addr, uint32_t size, uint64_t data)
>> "@0x%" PRIx64 " size=%d value=0x%"PRIx64
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v5 00/10] Introduce model for IBM's FSI
2023-10-19 8:16 ` [PATCH v5 00/10] Introduce model for IBM's FSI Cédric Le Goater
@ 2023-10-21 20:45 ` Ninad Palsule
0 siblings, 0 replies; 41+ messages in thread
From: Ninad Palsule @ 2023-10-21 20:45 UTC (permalink / raw
To: Cédric Le Goater, qemu-devel, peter.maydell, andrew, joel,
pbonzini, marcandre.lureau, berrange, thuth, philmd, lvivier
Cc: qemu-arm
Hello Cedric,
On 10/19/23 03:16, Cédric Le Goater wrote:
> Hello Ninad,
>
>
> On 10/11/23 17:13, Ninad Palsule wrote:
>> Hello,
>>
>> Please review the patch-set version 5.
>> I have incorporated review comments from Cedric.
>>
>> Ninad Palsule (10):
>> hw/fsi: Introduce IBM's Local bus
>> hw/fsi: Introduce IBM's scratchpad
>> hw/fsi: Introduce IBM's cfam,fsi-slave
>> hw/fsi: Introduce IBM's FSI
>> hw/fsi: IBM's On-chip Peripheral Bus
>> hw/fsi: Aspeed APB2OPB interface
>> hw/arm: Hook up FSI module in AST2600
>> hw/fsi: Added qtest
>> hw/fsi: Added FSI documentation
>> hw/fsi: Update MAINTAINER list
>
> I made some comments, mostly on the bus models which need to be reworked.
> This is code reshuffling and it should simplify the models. Please
> consider
> reducing the amount of files.
I have incorporated most of your comments but couldn't reduce the files
as there is a file per bus or device.
>
> Also, could please remove my Sob ? I didn't write any of this, only did
> quick fixes over the years because I kept the series in my aspeed tree.
> And this would help me to add a Rb :)
Removed your name from signed off by.
>
> I expect one or two respins before merge. 8.2 freeze window is in less
> than 3 weeks. It could make it, else the next. No big issue since I think
> we have been dragging these models for at least 5/6 years.
I am hoping to get it in 8.2
Thanks for the review.
Regards,
Ninad
>
> Thanks,
>
> C.
>
>
>>
>> MAINTAINERS | 8 +
>> docs/specs/fsi.rst | 141 ++++++++++++
>> meson.build | 1 +
>> hw/fsi/trace.h | 1 +
>> include/hw/arm/aspeed_soc.h | 4 +
>> include/hw/fsi/aspeed-apb2opb.h | 33 +++
>> include/hw/fsi/cfam.h | 58 +++++
>> include/hw/fsi/engine-scratchpad.h | 33 +++
>> include/hw/fsi/fsi-master.h | 30 +++
>> include/hw/fsi/fsi-slave.h | 29 +++
>> include/hw/fsi/fsi.h | 37 +++
>> include/hw/fsi/lbus.h | 51 +++++
>> include/hw/fsi/opb.h | 43 ++++
>> include/qemu/bitops.h | 6 +
>> hw/arm/aspeed_ast2600.c | 19 ++
>> hw/fsi/aspeed-apb2opb.c | 350 +++++++++++++++++++++++++++++
>> hw/fsi/cfam.c | 220 ++++++++++++++++++
>> hw/fsi/engine-scratchpad.c | 99 ++++++++
>> hw/fsi/fsi-master.c | 198 ++++++++++++++++
>> hw/fsi/fsi-slave.c | 96 ++++++++
>> hw/fsi/fsi.c | 54 +++++
>> hw/fsi/lbus.c | 87 +++++++
>> hw/fsi/opb.c | 185 +++++++++++++++
>> tests/qtest/fsi-test.c | 210 +++++++++++++++++
>> hw/Kconfig | 1 +
>> hw/arm/Kconfig | 1 +
>> hw/fsi/Kconfig | 23 ++
>> hw/fsi/meson.build | 6 +
>> hw/fsi/trace-events | 15 ++
>> hw/meson.build | 1 +
>> tests/qtest/meson.build | 2 +
>> 31 files changed, 2042 insertions(+)
>> create mode 100644 docs/specs/fsi.rst
>> create mode 100644 hw/fsi/trace.h
>> create mode 100644 include/hw/fsi/aspeed-apb2opb.h
>> create mode 100644 include/hw/fsi/cfam.h
>> create mode 100644 include/hw/fsi/engine-scratchpad.h
>> create mode 100644 include/hw/fsi/fsi-master.h
>> create mode 100644 include/hw/fsi/fsi-slave.h
>> create mode 100644 include/hw/fsi/fsi.h
>> create mode 100644 include/hw/fsi/lbus.h
>> create mode 100644 include/hw/fsi/opb.h
>> create mode 100644 hw/fsi/aspeed-apb2opb.c
>> create mode 100644 hw/fsi/cfam.c
>> create mode 100644 hw/fsi/engine-scratchpad.c
>> create mode 100644 hw/fsi/fsi-master.c
>> create mode 100644 hw/fsi/fsi-slave.c
>> create mode 100644 hw/fsi/fsi.c
>> create mode 100644 hw/fsi/lbus.c
>> create mode 100644 hw/fsi/opb.c
>> create mode 100644 tests/qtest/fsi-test.c
>> create mode 100644 hw/fsi/Kconfig
>> create mode 100644 hw/fsi/meson.build
>> create mode 100644 hw/fsi/trace-events
>>
>
^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2023-10-21 20:46 UTC | newest]
Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-11 15:13 [PATCH v5 00/10] Introduce model for IBM's FSI Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 01/10] hw/fsi: Introduce IBM's Local bus Ninad Palsule
2023-10-19 8:03 ` Cédric Le Goater
2023-10-21 20:20 ` Ninad Palsule
2023-10-19 8:08 ` Cédric Le Goater
2023-10-21 20:21 ` Ninad Palsule
2023-10-19 8:14 ` Daniel P. Berrangé
2023-10-19 15:34 ` Ninad Palsule
2023-10-19 16:09 ` Daniel P. Berrangé
2023-10-21 20:22 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 02/10] hw/fsi: Introduce IBM's scratchpad Ninad Palsule
2023-10-19 8:20 ` Daniel P. Berrangé
2023-10-21 20:27 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave Ninad Palsule
2023-10-19 8:00 ` Cédric Le Goater
2023-10-21 20:33 ` Ninad Palsule
2023-10-19 8:26 ` Daniel P. Berrangé
2023-10-21 20:34 ` Ninad Palsule
2023-10-19 17:28 ` Cédric Le Goater
2023-10-21 20:35 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 04/10] hw/fsi: Introduce IBM's FSI Ninad Palsule
2023-10-19 7:44 ` Cédric Le Goater
2023-10-21 20:36 ` Ninad Palsule
2023-10-19 8:28 ` Daniel P. Berrangé
2023-10-21 20:37 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 05/10] hw/fsi: IBM's On-chip Peripheral Bus Ninad Palsule
2023-10-19 7:26 ` Cédric Le Goater
2023-10-21 20:40 ` Ninad Palsule
2023-10-19 8:30 ` Daniel P. Berrangé
2023-10-21 20:42 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 06/10] hw/fsi: Aspeed APB2OPB interface Ninad Palsule
2023-10-19 7:16 ` Cédric Le Goater
2023-10-21 20:43 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 07/10] hw/arm: Hook up FSI module in AST2600 Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 08/10] hw/fsi: Added qtest Ninad Palsule
2023-10-11 15:35 ` Thomas Huth
2023-10-11 16:54 ` Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 09/10] hw/fsi: Added FSI documentation Ninad Palsule
2023-10-11 15:13 ` [PATCH v5 10/10] hw/fsi: Update MAINTAINER list Ninad Palsule
2023-10-19 8:16 ` [PATCH v5 00/10] Introduce model for IBM's FSI Cédric Le Goater
2023-10-21 20:45 ` Ninad Palsule
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.