From: Bin Meng <bin.meng@processmission.com>
To: QEMU <qemu-devel@nongnu.org>
Cc: qemu-arm@nongnu.org
Subject: [PATCH v2 08/32] hw/misc: Add Phytium E2000 DDR controller
Date: Tue, 8 Sep 2026 18:41:17 +0800 [thread overview]
Message-ID: <20260908104159.1621764-9-bin.meng@processmission.com> (raw)
In-Reply-To: <20260908104159.1621764-1-bin.meng@processmission.com>
Model the E2000 DDR initialization and training compatibility window.
Keep ordinary aligned registers as persistent storage and implement
the indirect selector/value interface used by the vendor PBF.
Return the expected initialization, PHY training, update, and BIST
results, including the training-error range. This models the firmware
contract without attempting a timing-accurate DDR PHY.
Signed-off-by: Bin Meng <bin.meng@processmission.com>
---
(no changes since v1)
include/hw/misc/phytium_e2000_ddr.h | 23 ++++
hw/misc/phytium_e2000_ddr.c | 197 ++++++++++++++++++++++++++++
hw/misc/meson.build | 1 +
3 files changed, 221 insertions(+)
create mode 100644 include/hw/misc/phytium_e2000_ddr.h
create mode 100644 hw/misc/phytium_e2000_ddr.c
diff --git a/include/hw/misc/phytium_e2000_ddr.h b/include/hw/misc/phytium_e2000_ddr.h
new file mode 100644
index 0000000000..91dc661106
--- /dev/null
+++ b/include/hw/misc/phytium_e2000_ddr.h
@@ -0,0 +1,23 @@
+/*
+ * Phytium E2000 DDR training status
+ *
+ * Copyright (c) 2026 Process Mission
+ *
+ * Author:
+ * Bin Meng <bin.meng@processmission.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_MISC_PHYTIUM_E2000_DDR_H
+#define HW_MISC_PHYTIUM_E2000_DDR_H
+
+#include "hw/core/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_PHYTIUM_E2000_DDR "phytium-e2000-ddr"
+OBJECT_DECLARE_SIMPLE_TYPE(PhytiumE2000DDRState, PHYTIUM_E2000_DDR)
+
+#define PHYTIUM_E2000_DDR_MMIO_SIZE 0x400
+
+#endif
diff --git a/hw/misc/phytium_e2000_ddr.c b/hw/misc/phytium_e2000_ddr.c
new file mode 100644
index 0000000000..ab46a46961
--- /dev/null
+++ b/hw/misc/phytium_e2000_ddr.c
@@ -0,0 +1,197 @@
+/*
+ * Phytium E2000 DDR training status
+ *
+ * The vendor firmware accesses controller and PHY state through an indexed
+ * selector/value window. This functional model reproduces the completion and
+ * error predicates used during boot; it does not simulate analog DDR training
+ * or generate physical calibration results.
+ *
+ * Copyright (c) 2026 Process Mission
+ *
+ * Author:
+ * Bin Meng <bin.meng@processmission.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/phytium_e2000_ddr.h"
+
+#include "hw/core/register.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+
+REG32(SELECTOR, 0x80)
+REG32(VALUE, 0x84)
+
+#define PHYTIUM_E2000_DDR_R_MAX \
+ (PHYTIUM_E2000_DDR_MMIO_SIZE / sizeof(uint32_t))
+/*
+ * Selectors encode a register index as a byte offset. PBF uses separate
+ * direct, indirect, and training banks distinguished by 0x800 and 0x1000
+ * index biases.
+ */
+#define PHYTIUM_E2000_DDR_SELECTOR(reg) ((reg) * 4)
+#define PHYTIUM_E2000_DDR_INDIRECT_SELECTOR(reg) (((reg) + 0x800) * 4)
+#define PHYTIUM_E2000_DDR_TRAINING_SELECTOR(reg) (((reg) + 0x1000) * 4)
+#define PHYTIUM_E2000_DDR_TRAINING_ERR_FIRST 0xc72
+#define PHYTIUM_E2000_DDR_TRAINING_ERR_LAST 0xc79
+
+struct PhytiumE2000DDRState {
+ SysBusDevice parent_obj;
+
+ uint32_t regs[PHYTIUM_E2000_DDR_R_MAX];
+ RegisterInfo regs_info[PHYTIUM_E2000_DDR_R_MAX];
+ RegisterAccessInfo regs_access_info[PHYTIUM_E2000_DDR_R_MAX];
+};
+
+static uint64_t phytium_e2000_ddr_value_post_read(RegisterInfo *reg,
+ uint64_t value)
+{
+ PhytiumE2000DDRState *s = PHYTIUM_E2000_DDR(reg->opaque);
+ uint32_t selector = s->regs[R_SELECTOR];
+
+ /*
+ * These fixed selectors are controller/PHY polls observed in the tested
+ * firmware. Return only the ready and completion bits that its loops
+ * require, without assigning behavior to the surrounding register bank.
+ */
+ switch (selector) {
+ case PHYTIUM_E2000_DDR_INDIRECT_SELECTOR(0xdc):
+ return BIT(0);
+ case PHYTIUM_E2000_DDR_SELECTOR(0x256):
+ return BIT(0) | BIT(25);
+ case PHYTIUM_E2000_DDR_INDIRECT_SELECTOR(0x76):
+ return BIT(0) | BIT(14) | BIT(27);
+ case PHYTIUM_E2000_DDR_SELECTOR(0x10f):
+ return 0x40U << 24;
+ case PHYTIUM_E2000_DDR_SELECTOR(0x229):
+ return BIT(0);
+ case PHYTIUM_E2000_DDR_SELECTOR(0x257):
+ return BIT(3);
+ case PHYTIUM_E2000_DDR_SELECTOR(0x255):
+ return BIT(16);
+ case PHYTIUM_E2000_DDR_SELECTOR(0x1d5):
+ return BIT(16) | BIT(24) | BIT(25);
+ default:
+ /*
+ * The training bank is read repeatedly for lane state and error
+ * summaries. Error selectors report no failure; the remaining values
+ * are deterministic so repeated sweeps see stable lane data.
+ */
+ if (selector >= PHYTIUM_E2000_DDR_TRAINING_SELECTOR(0) &&
+ selector < PHYTIUM_E2000_DDR_TRAINING_SELECTOR(0x1000)) {
+ uint32_t index = selector / sizeof(uint32_t) - 0x1000;
+
+ if (index >= PHYTIUM_E2000_DDR_TRAINING_ERR_FIRST &&
+ index <= PHYTIUM_E2000_DDR_TRAINING_ERR_LAST) {
+ return 0;
+ }
+ /*
+ * Preserve the masks and flag combinations checked by the PBF
+ * training algorithm for these recurring low-byte selectors.
+ */
+ if ((index & 0xff) == 0x34) {
+ return 0x00000fff;
+ }
+ if ((index & 0xff) == 0x38) {
+ return BIT(4) | BIT(5);
+ }
+ if ((index & 0xff) == 0x83) {
+ return 0;
+ }
+ if ((index & 0xff) == 0x3b) {
+ return 0x01234567U | BIT(26) | BIT(27);
+ }
+ return 0x01234567U;
+ }
+ /*
+ * Unclassified offsets retain ordinary register storage. This keeps
+ * setup writes readable without pretending they affect DDR timing.
+ */
+ return value;
+ }
+}
+
+static const MemoryRegionOps phytium_e2000_ddr_ops = {
+ .read = register_read_memory,
+ .write = register_write_memory,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void phytium_e2000_ddr_reset(DeviceState *dev)
+{
+ PhytiumE2000DDRState *s = PHYTIUM_E2000_DDR(dev);
+ int i;
+
+ for (i = 0; i < PHYTIUM_E2000_DDR_R_MAX; i++) {
+ register_reset(&s->regs_info[i]);
+ }
+}
+
+static void phytium_e2000_ddr_init(Object *obj)
+{
+ PhytiumE2000DDRState *s = PHYTIUM_E2000_DDR(obj);
+ RegisterInfoArray *reg_array;
+ int i;
+
+ /*
+ * Firmware may touch any word in this compact window before selecting a
+ * status source, so create registerinfo metadata for the full aperture and
+ * specialize only SELECTOR and VALUE.
+ */
+ for (i = 0; i < PHYTIUM_E2000_DDR_R_MAX; i++) {
+ s->regs_access_info[i].name = "DDR_STATUS";
+ s->regs_access_info[i].addr = i * sizeof(uint32_t);
+ }
+ s->regs_access_info[R_SELECTOR].name = "SELECTOR";
+ s->regs_access_info[R_VALUE].name = "VALUE";
+ s->regs_access_info[R_VALUE].ro = UINT32_MAX;
+ s->regs_access_info[R_VALUE].post_read =
+ phytium_e2000_ddr_value_post_read;
+
+ reg_array = register_init_block32(
+ DEVICE(obj), s->regs_access_info, PHYTIUM_E2000_DDR_R_MAX,
+ s->regs_info, s->regs, &phytium_e2000_ddr_ops, false,
+ PHYTIUM_E2000_DDR_MMIO_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), ®_array->mem);
+}
+
+static const VMStateDescription phytium_e2000_ddr_vmsd = {
+ .name = TYPE_PHYTIUM_E2000_DDR,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, PhytiumE2000DDRState,
+ PHYTIUM_E2000_DDR_R_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void phytium_e2000_ddr_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &phytium_e2000_ddr_vmsd;
+ device_class_set_legacy_reset(dc, phytium_e2000_ddr_reset);
+}
+
+static const TypeInfo phytium_e2000_ddr_info = {
+ .name = TYPE_PHYTIUM_E2000_DDR,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PhytiumE2000DDRState),
+ .instance_init = phytium_e2000_ddr_init,
+ .class_init = phytium_e2000_ddr_class_init,
+};
+
+static void phytium_e2000_ddr_register_types(void)
+{
+ type_register_static(&phytium_e2000_ddr_info);
+}
+
+type_init(phytium_e2000_ddr_register_types)
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 9790afa104..dca5f67ca9 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -16,6 +16,7 @@ system_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c'))
system_ss.add(when: 'CONFIG_INTEGRATOR_DEBUG', if_true: files('arm_integrator_debug.c'))
system_ss.add(when: 'CONFIG_A9SCU', if_true: files('a9scu.c'))
system_ss.add(when: 'CONFIG_ARM11SCU', if_true: files('arm11scu.c'))
+system_ss.add(when: 'CONFIG_PHYTIUM_E2000', if_true: files('phytium_e2000_ddr.c'))
system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_ras.c'))
--
2.53.0
next prev parent reply other threads:[~2026-09-08 10:44 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 10:41 [PATCH v2 00/32] hw/arm: Add Phytium E2000Q SoC and board support Bin Meng
2026-09-08 10:41 ` [PATCH v2 01/32] hw/arm: Add Phytium E2000 SoC and Phytium Pi machine Bin Meng
2026-09-08 10:41 ` [PATCH v2 02/32] hw/arm: phytium: Add Phytium E2000 PCIe host Bin Meng
2026-09-08 10:41 ` [PATCH v2 03/32] hw/sd: Add Synopsys DesignWare MCI controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 04/32] hw/sd: Add Phytium E2000 " Bin Meng
2026-09-08 10:41 ` [PATCH v2 05/32] hw/arm: phytium: Connect Phytium E2000 MCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 06/32] tests/qtest: Add Synopsys DesignWare MCI coverage Bin Meng
2026-09-08 10:41 ` [PATCH v2 07/32] hw/arm: phytium: Connect Phytium E2000 GEM controllers Bin Meng
2026-09-08 10:41 ` Bin Meng [this message]
2026-09-08 10:41 ` [PATCH v2 09/32] hw/arm: phytium: Connect the Phytium E2000 DDR controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 10/32] hw/misc: Add Phytium E2000 MHU doorbell Bin Meng
2026-09-08 10:41 ` [PATCH v2 11/32] hw/arm: phytium: Connect the Phytium E2000 MHU Bin Meng
2026-09-08 10:41 ` [PATCH v2 12/32] hw/ssi: Add Phytium E2000 QSPI controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 13/32] hw/arm: phytium: Connect the " Bin Meng
2026-09-08 10:41 ` [PATCH v2 14/32] hw/misc: Add Phytium E2000 PBR model Bin Meng
2026-09-08 10:41 ` [PATCH v2 15/32] hw/arm: phytium: Integrate the Phytium E2000 PBR Bin Meng
2026-09-08 10:41 ` [PATCH v2 16/32] hw/arm: phytium: Add Phytium E2000 control region placeholders Bin Meng
2026-09-08 10:41 ` [PATCH v2 17/32] hw/misc: Support Phytium E2000 SCMI CPU power control Bin Meng
2026-09-08 10:41 ` [PATCH v2 18/32] hw/arm: phytium: Select the Phytium E2000 PBR boot medium Bin Meng
2026-09-08 10:41 ` [PATCH v2 19/32] hw/arm: phytium: Connect the Phytium E2000 I2C controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 20/32] hw/arm: phytium: Add Phytium E2000 xHCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 21/32] hw/misc: Model the Phytium E2000 random generator Bin Meng
2026-09-08 10:41 ` [PATCH v2 22/32] hw/arm: phytium: Connect " Bin Meng
2026-09-08 10:41 ` [PATCH v2 23/32] hw/arm: phytium: Support Phytium E2000 direct Linux boot Bin Meng
2026-09-08 10:41 ` [PATCH v2 24/32] hw/arm: phytium: Add Phytium E2000Q COMe machine Bin Meng
2026-09-08 10:41 ` [PATCH v2 25/32] hw/block: m25p80: Add GigaDevice GD25Q128 flash Bin Meng
2026-09-08 10:41 ` [PATCH v2 26/32] hw/arm: phytium: Connect the Phytium E2000Q COMe QSPI flash Bin Meng
2026-09-08 10:41 ` [PATCH v2 27/32] hw/arm: phytium: Add Phytium E2000 AHCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 28/32] hw/arm: Add Phytium E2000 Linux SCMI channel Bin Meng
2026-09-08 10:41 ` [PATCH v2 29/32] hw/arm: phytium: Connect the Phytium E2000 SMMUv3 Bin Meng
2026-09-08 10:41 ` [PATCH v2 30/32] docs/system/arm: Document Phytium E2000 machines Bin Meng
2026-09-08 10:41 ` [PATCH v2 31/32] tests/functional/aarch64: Add Phytium Pi boot tests Bin Meng
2026-09-08 10:41 ` [PATCH v2 32/32] MAINTAINERS: Add Phytium E2000Q machines Bin Meng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260908104159.1621764-9-bin.meng@processmission.com \
--to=bin.meng@processmission.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is 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.