From: Bin Meng <bin.meng@processmission.com>
To: QEMU <qemu-devel@nongnu.org>
Cc: Conor Dooley <conor@kernel.org>,
Sebastian Huber <sebastian.huber@embedded-brains.de>,
qemu-riscv@nongnu.org
Subject: [PATCH 15/26] hw/misc: pfsoc: Model PolarFire SoC serial number service
Date: Thu, 23 Jul 2026 23:18:42 +0800 [thread overview]
Message-ID: <20260723151853.2143177-16-bin.meng@processmission.com> (raw)
In-Reply-To: <20260723151853.2143177-1-bin.meng@processmission.com>
U-Boot requests the PolarFire SoC device serial number during board
late initialization. The IOSCB previously rejected every request, so
board setup could not complete.
Model the System Services control registers and byte-addressable
mailbox. Obtain the 128-bit serial number from an optional device
property, using a deterministic value when it is not configured.
Return an explicit failure for unsupported services and reset the new
runtime state with the rest of the device.
Signed-off-by: Bin Meng <bin.meng@processmission.com>
---
include/hw/misc/mchp_pfsoc_ioscb.h | 6 ++
hw/misc/mchp_pfsoc_ioscb.c | 141 +++++++++++++++++++++++++----
2 files changed, 130 insertions(+), 17 deletions(-)
diff --git a/include/hw/misc/mchp_pfsoc_ioscb.h b/include/hw/misc/mchp_pfsoc_ioscb.h
index 9687ea25b1..fd31427304 100644
--- a/include/hw/misc/mchp_pfsoc_ioscb.h
+++ b/include/hw/misc/mchp_pfsoc_ioscb.h
@@ -25,6 +25,8 @@
#include "hw/core/sysbus.h"
+#define MCHP_PFSOC_IOSCB_MAILBOX_SIZE 0x1000
+
typedef struct MchpPfSoCIoscbState {
SysBusDevice parent;
MemoryRegion container;
@@ -47,6 +49,10 @@ typedef struct MchpPfSoCIoscbState {
MemoryRegion cfm_sgmii;
MemoryRegion bc_sgmii;
MemoryRegion io_calib_sgmii;
+ uint32_t services_cr;
+ uint32_t services_sr;
+ uint8_t mailbox_data[MCHP_PFSOC_IOSCB_MAILBOX_SIZE];
+ char *serial_number;
qemu_irq irq;
} MchpPfSoCIoscbState;
diff --git a/hw/misc/mchp_pfsoc_ioscb.c b/hw/misc/mchp_pfsoc_ioscb.c
index 09b702e520..7c82b55986 100644
--- a/hw/misc/mchp_pfsoc_ioscb.c
+++ b/hw/misc/mchp_pfsoc_ioscb.c
@@ -25,6 +25,7 @@
#include "qemu/log.h"
#include "qapi/error.h"
#include "hw/core/irq.h"
+#include "hw/core/qdev-properties.h"
#include "hw/core/sysbus.h"
#include "hw/misc/mchp_pfsoc_ioscb.h"
@@ -37,6 +38,9 @@
#define IOSCB_CCC_REG_SIZE 0x2000000
#define IOSCB_CTRL_REG_SIZE 0x800
#define IOSCB_QSPIXIP_REG_SIZE 0x200
+#define IOSCB_SERIAL_NUMBER_SIZE 16U
+#define IOSCB_DEFAULT_SERIAL_NUMBER "0123456789abcdef"
+#define IOSCB_PROP_SERIAL_NUMBER "serial-number"
/*
@@ -186,33 +190,71 @@ static const MemoryRegionOps mchp_pfsoc_io_calib_ddr_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
-#define SERVICES_CR 0x50
-#define SERVICES_SR 0x54
-#define SERVICES_STATUS_SHIFT 16
+#define SERVICES_CR 0x50
+#define SERVICES_CR_REQUEST BIT(0)
+#define SERVICES_CR_COMMAND_SHIFT 16
+#define SERVICES_CR_COMMAND_WIDTH 8
+#define SERVICES_CR_COMMAND_MASK \
+ MAKE_64BIT_MASK(SERVICES_CR_COMMAND_SHIFT, SERVICES_CR_COMMAND_WIDTH)
+#define SERVICES_CR_MASK \
+ (SERVICES_CR_REQUEST | SERVICES_CR_COMMAND_MASK)
+#define SERVICES_SR 0x54
+#define SERVICES_SR_STATUS_SHIFT 16
+#define SERVICES_COMMAND_SERIAL_NUMBER 0
+#define SERVICES_STATUS_SUCCESS 0
+#define SERVICES_STATUS_FAILED 1
+#define SERVICES_MAILBOX_RESPONSE_OFFSET 0
+
+static void services_cr_write(MchpPfSoCIoscbState *s, uint32_t value)
+{
+ uint32_t command;
+ uint32_t status = SERVICES_STATUS_FAILED;
+
+ if (device_is_in_reset(DEVICE(s)) ||
+ !(value & SERVICES_CR_REQUEST)) {
+ return;
+ }
+
+ /*
+ * System services complete synchronously in this model, so clear the
+ * request bit before exposing the response to the guest.
+ */
+ s->services_cr &= ~SERVICES_CR_REQUEST;
+
+ command = (value & SERVICES_CR_COMMAND_MASK) >>
+ SERVICES_CR_COMMAND_SHIFT;
+ if (command == SERVICES_COMMAND_SERIAL_NUMBER) {
+ /*
+ * The serial-number service returns a 128-bit response starting at
+ * the beginning of the mailbox.
+ */
+ memset(&s->mailbox_data[SERVICES_MAILBOX_RESPONSE_OFFSET], 0,
+ IOSCB_SERIAL_NUMBER_SIZE);
+ memcpy(&s->mailbox_data[SERVICES_MAILBOX_RESPONSE_OFFSET],
+ s->serial_number, strlen(s->serial_number));
+ status = SERVICES_STATUS_SUCCESS;
+ }
+
+ s->services_sr = status << SERVICES_SR_STATUS_SHIFT;
+ qemu_irq_raise(s->irq);
+}
static uint64_t mchp_pfsoc_ctrl_read(void *opaque, hwaddr offset,
unsigned size)
{
- uint32_t val = 0;
+ MchpPfSoCIoscbState *s = opaque;
switch (offset) {
+ case SERVICES_CR:
+ return s->services_cr;
case SERVICES_SR:
- /*
- * Although some services have no error codes, most do. All services
- * that do implement errors, begin their error codes at 1. Treat all
- * service requests as failures & return 1.
- * See the "PolarFire® FPGA and PolarFire SoC FPGA System Services"
- * user guide for more information on service error codes.
- */
- val = 1u << SERVICES_STATUS_SHIFT;
- break;
+ return s->services_sr;
default:
qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
"(size %d, offset 0x%" HWADDR_PRIx ")\n",
__func__, size, offset);
+ return 0;
}
-
- return val;
}
static void mchp_pfsoc_ctrl_write(void *opaque, hwaddr offset,
@@ -222,13 +264,17 @@ static void mchp_pfsoc_ctrl_write(void *opaque, hwaddr offset,
switch (offset) {
case SERVICES_CR:
- qemu_irq_raise(s->irq);
+ s->services_cr = value & SERVICES_CR_MASK;
+ services_cr_write(s, value);
+ break;
+ case SERVICES_SR:
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write "
"(size %d, value 0x%" PRIx64
", offset 0x%" HWADDR_PRIx ")\n",
__func__, size, value, offset);
+ break;
}
}
@@ -236,6 +282,55 @@ static const MemoryRegionOps mchp_pfsoc_ctrl_ops = {
.read = mchp_pfsoc_ctrl_read,
.write = mchp_pfsoc_ctrl_write,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = sizeof(uint32_t),
+ .max_access_size = sizeof(uint32_t),
+ },
+};
+
+/*
+ * The System Controller uses the mailbox as a byte-addressable shared buffer
+ * for service command payloads and responses.
+ */
+static uint64_t mchp_pfsoc_mailbox_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ MchpPfSoCIoscbState *s = opaque;
+
+ return ldn_le_p(&s->mailbox_data[offset], size);
+}
+
+static void mchp_pfsoc_mailbox_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ MchpPfSoCIoscbState *s = opaque;
+
+ stn_le_p(&s->mailbox_data[offset], size, value);
+}
+
+static const MemoryRegionOps mchp_pfsoc_mailbox_ops = {
+ .read = mchp_pfsoc_mailbox_read,
+ .write = mchp_pfsoc_mailbox_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid = {
+ .min_access_size = sizeof(uint8_t),
+ .max_access_size = sizeof(uint32_t),
+ },
+};
+
+static void mchp_pfsoc_ioscb_reset(DeviceState *dev)
+{
+ MchpPfSoCIoscbState *s = MCHP_PFSOC_IOSCB(dev);
+
+ s->services_cr = 0;
+ s->services_sr = 0;
+ memset(s->mailbox_data, 0, sizeof(s->mailbox_data));
+ qemu_irq_lower(s->irq);
+}
+
+static const Property mchp_pfsoc_ioscb_properties[] = {
+ DEFINE_PROP_STRING(IOSCB_PROP_SERIAL_NUMBER,
+ MchpPfSoCIoscbState, serial_number),
};
static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp)
@@ -243,6 +338,16 @@ static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp)
MchpPfSoCIoscbState *s = MCHP_PFSOC_IOSCB(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ /* Use a deterministic identity when no serial number is configured */
+ if (!s->serial_number) {
+ s->serial_number = g_strdup(IOSCB_DEFAULT_SERIAL_NUMBER);
+ }
+ if (strlen(s->serial_number) > IOSCB_SERIAL_NUMBER_SIZE) {
+ error_setg(errp, "The serial number can't be longer than %u bytes",
+ IOSCB_SERIAL_NUMBER_SIZE);
+ return;
+ }
+
memory_region_init(&s->container, OBJECT(s),
"mchp.pfsoc.ioscb", IOSCB_WHOLE_REG_SIZE);
sysbus_init_mmio(sbd, &s->container);
@@ -265,7 +370,7 @@ static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp)
"mchp.pfsoc.ioscb.qspixip", IOSCB_QSPIXIP_REG_SIZE);
memory_region_add_subregion(&s->container, IOSCB_QSPIXIP_BASE, &s->qspixip);
- memory_region_init_io(&s->mailbox, OBJECT(s), &mchp_pfsoc_dummy_ops, s,
+ memory_region_init_io(&s->mailbox, OBJECT(s), &mchp_pfsoc_mailbox_ops, s,
"mchp.pfsoc.ioscb.mailbox", IOSCB_SUBMOD_REG_SIZE);
memory_region_add_subregion(&s->container, IOSCB_MAILBOX_BASE, &s->mailbox);
@@ -343,6 +448,8 @@ static void mchp_pfsoc_ioscb_class_init(ObjectClass *klass, const void *data)
dc->desc = "Microchip PolarFire SoC IOSCB modules";
dc->realize = mchp_pfsoc_ioscb_realize;
+ device_class_set_legacy_reset(dc, mchp_pfsoc_ioscb_reset);
+ device_class_set_props(dc, mchp_pfsoc_ioscb_properties);
}
static const TypeInfo mchp_pfsoc_ioscb_info = {
--
2.34.1
next prev parent reply other threads:[~2026-07-23 15:20 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 15:18 [PATCH 00/26] hw/riscv: Restore Microchip PolarFire SoC Icicle Kit firmware boot Bin Meng
2026-07-23 15:18 ` [PATCH 01/26] hw/riscv: pfsoc: Correct the L2LIM maximum mapped size Bin Meng
2026-07-23 15:18 ` [PATCH 02/26] hw/riscv: pfsoc: Map the L2 zero device window Bin Meng
2026-07-23 15:18 ` [PATCH 03/26] hw/misc: pfsoc: Support PolarFire SoC DDR training with newer version HSS Bin Meng
2026-07-23 15:18 ` [PATCH 04/26] hw/misc: pfsoc: Model L2 cache controller registers Bin Meng
2026-07-23 15:18 ` [PATCH 05/26] hw/riscv: pfsoc: Couple L2CC to L2-LIM Bin Meng
2026-07-23 15:18 ` [PATCH 06/26] tests/qtest: Add PolarFire SoC L2CC coverage Bin Meng
2026-07-23 15:18 ` [PATCH 07/26] hw/sd: sdhci: Migrate the Host Control 2 register Bin Meng
2026-07-23 15:18 ` [PATCH 08/26] hw/sd: sdhci: Accept version 4 enable without UHS-I Bin Meng
2026-07-23 15:18 ` [PATCH 09/26] hw/sd: sdhci: Use version 4 system address for SDMA Bin Meng
2026-07-23 15:18 ` [PATCH 10/26] hw/sd: sdhci: Support version 4 ADMA 64-bit addressing Bin Meng
2026-07-23 15:18 ` [PATCH 11/26] hw/sd: sdhci: Resume version 4 SDMA at buffer boundaries Bin Meng
2026-07-23 15:18 ` [PATCH 12/26] hw/sd: sdhci: Run ADMA independently of MMIO Bin Meng
2026-07-23 15:18 ` [PATCH 13/26] hw/sd: sd: Keep high-capacity memory blocks at 512 bytes Bin Meng
2026-07-23 15:18 ` [PATCH 14/26] hw/sd: cadence: Advertise 64-bit system bus support Bin Meng
2026-07-23 15:18 ` Bin Meng [this message]
2026-07-23 15:18 ` [PATCH 16/26] hw/rtc: Add PolarFire SoC RTC model Bin Meng
2026-07-23 15:28 ` Conor Dooley
2026-07-23 15:55 ` Bin Meng
2026-07-23 15:58 ` Conor Dooley
2026-07-23 16:07 ` Bin Meng
2026-07-23 15:18 ` [PATCH 17/26] hw/riscv: pfsoc: Add PolarFire SoC RTC to Icicle Kit Bin Meng
2026-07-23 15:18 ` [PATCH 18/26] tests/qtest: Add PolarFire SoC RTC coverage Bin Meng
2026-07-23 15:18 ` [PATCH 19/26] hw/misc: pfsoc: Honor PolarFire service notification requests Bin Meng
2026-07-23 15:18 ` [PATCH 20/26] hw/riscv: pfsoc: Correct PolarFire SoC DDR aliases Bin Meng
2026-07-23 15:18 ` [PATCH 21/26] hw/riscv: pfsoc: Fix Icicle Kit RAM size at 2 GiB Bin Meng
2026-07-23 15:18 ` [PATCH 22/26] hw/riscv: pfsoc: Fix Icicle Kit hart count at five Bin Meng
2026-07-23 15:18 ` [PATCH 23/26] docs/system/riscv: Document Icicle Kit HSS boot Bin Meng
2026-07-23 15:18 ` [PATCH 24/26] docs/system/riscv: pfsoc: Document CLINT topology for direct Linux boot Bin Meng
2026-07-23 15:18 ` [PATCH 25/26] tests/functional/riscv64: Add Icicle Kit firmware boot test Bin Meng
2026-07-23 15:18 ` [PATCH 26/26] MAINTAINERS: Add PolarFire SoC Icicle Kit maintainer Bin Meng
2026-07-23 15:29 ` Conor Dooley via qemu development
2026-07-23 16:51 ` Markus Armbruster
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=20260723151853.2143177-16-bin.meng@processmission.com \
--to=bin.meng@processmission.com \
--cc=conor@kernel.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-riscv@nongnu.org \
--cc=sebastian.huber@embedded-brains.de \
/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.