Skip to content

hw/riscv: restore PolarFire SoC Icicle Kit firmware boot - #38

Merged
zevorn merged 30 commits into
develfrom
codex/pfsoc-sdhci-series
Sep 5, 2026
Merged

zevorn merged 30 commits into
develfrom
codex/pfsoc-sdhci-series

Conversation

@zevorn

@zevorn zevorn commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

This pull request restores Microchip PolarFire SoC Icicle Kit firmware boot support and brings the referenced hw/sd SDHCI series onto the current devel branch.

The change includes the 26-patch Patchwork series, its SDMA boundary continuation prerequisite, and the required adaptations for the current devel tree. The SDHCI ADMA scheduling change is also covered by the K3 qtest timing update.

Testing:

  • meson test qtest-riscv64/mchp_pfsoc_l2cc_test qtest-riscv64/mchp_pfsoc_rtc_test qtest-riscv64/spacemit-k3-test --print-errorlogs
  • meson test qtest-arm/xilinx-zynq-sdhci-test --print-errorlogs
  • Rebuilt the K3 image from qemu-machine-images commit 13b4f06 on the remote build host; all files passed SHA256SUMS verification.
  • Booted that image with the modified qemu-system-riscv64; it reached K3_LINUX_MVP_PASS.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-02T07:04:39.997261Z d606e7c New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7654ab054a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hw/rtc/mchp_pfsoc_rtc.c
Comment on lines +150 to +152
if (target <= now) {
mchp_pfsoc_rtc_alarm(s);
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prevent recursive firing of a zero-period alarm

When the guest programs an alarm target of zero with RTC_MODE_WAKEUP_RESET | RTC_MODE_WAKEUP_CONTINUE, enabling the alarm reaches this branch, mchp_pfsoc_rtc_alarm() resets the count to zero and immediately calls mchp_pfsoc_rtc_schedule_alarm() again, which sees target <= now and recurses indefinitely. This guest-visible configuration therefore overflows QEMU's stack instead of producing a periodic alarm; defer the callback through the timer or otherwise stop immediate re-entry when the reset target is zero.

Useful? React with 👍 / 👎.

Comment thread hw/misc/mchp_pfsoc_l2cc.c
Comment on lines +212 to +214
device_class_set_legacy_reset(dc, mchp_pfsoc_l2cc_reset);
device_class_set_props(dc, mchp_pfsoc_l2cc_properties);
dc->realize = mchp_pfsoc_l2cc_realize;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Migrate the L2 controller state

The new controller has guest-writable way-enable and way-mask registers, and way-enable dynamically changes whether and how much of L2-LIM is mapped, but the device class installs no VMState description. Migrating after firmware assigns ways therefore leaves the destination at reset values and with the reset-size L2-LIM mapping, so register reads and the guest physical address map differ from the source and previously hidden RAM can become visible. Serialize the register state and restore the L2-LIM size during post-load.

Useful? React with 👍 / 👎.

Comment on lines 481 to +484
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Migrate IOSCB mailbox and interrupt state

This change makes IOSCB stateful (services_cr, services_sr, mailbox response bytes, and irq_pending) but registers only reset and properties, not a VMState description. If migration occurs after a system-service request but before the guest consumes or acknowledges its response, the destination loses the response and lowers the device IRQ while the migrated guest still expects it, potentially stalling the system-services transaction. The new service and mailbox state should be serialized and the IRQ level restored after load.

Useful? React with 👍 / 👎.

@zevorn

zevorn commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

@lbmeng Hi, some CI jobs failed for this series: https://patchwork.ozlabs.org/project/qemu-devel/list/?series=515264

I'll create a new PR rebased onto the latest upstream v11.1 release, and then rebase this PR on top of it. Please keep an eye on this PR.

PolarFire SoC has a 2MiB L2 cache, so the maximum mapped size of
L2LIM should be set to 2MiB too.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
HSS uses a window at 0x0a000000 while setting up the L2 cache,
decompressing its runtime image, and executing that image.
The missing mapping causes the E51 to trap before firmware can
initialize its UART.

Represent the window with RAM to provide its persistent read,
write, and execute effects without claiming to model the L2
cache itself.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
… HSS

HSS v2024.06 performs DDR and SGMII initialization through the DMC
register window before it can complete platform startup. The existing
model, which was validated against older version HSS in the early days,
exposes only a few fixed training results, so newer version HSS stalls
while waiting for PVT, PLL, DLL, ADDCMD, and verification status.

Update the DMC model by adding the minimum state and status behavior
needed by that firmware flow. Model the SGMII control registers,
main DDR PLL lock, deterministic ADDCMD transitions, and successful
gate and DQ/DQS verification. Keep training progress and writable
controls per device and clear them on reset.

These values are compatibility responses for HSS v2024.06 rather than
a cycle-accurate description of the DDR PHY. Document that limitation
in the source.

While we are here, update the license text to use the SPDX format.

Note at the time being there is an HSS bug [1] that consistenly blocks
the DDR traning from succeed when using an HSS image built from certain
version compiler like GCC 8.3.0. A patch [2] was proposed and verified
against HSS v2024.06.

[1] polarfire-soc/platform#36
[2] https://github.com/processmission/qemu-machine-images/blob/main/
    machine/riscv64/microchip-icicle-kit/
    0001-mpfs_hal-preserve-DDR-pattern-test-parameters.patch

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Implement the Config, WayEnable, and per-master WayMask registers
described by the PolarFire SoC MSS reference manual. Make WayEnable
monotonic and report the remaining register space as unimplemented.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Instantiate the L2CC in the PolarFire SoC machine and connect its
WayEnable register to the L2-LIM MemoryRegion. Back the complete 2 MiB
aperture and shrink it by 128 KiB for each cache way enabled.

Keep L2 Zero at its fixed aperture because it represents a cache
allocation window rather than the remaining L2-LIM capacity.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Add a dedicated qtest binary for L2CC register and memory-topology
behavior. Use underscores consistently in the test name.

Exercise Config, WayEnable, and every WayMask register, including
reset, monotonic writes, and unimplemented-register logging. Verify
that WayEnable resizes the guest-visible L2-LIM region while L2 Zero
remains fixed at the modeled 2 MiB size.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
The Host Control 2 register has been part of SDHCIState since its
initial implementation, but it was omitted from sdhci_vmstate.
Migration therefore resets the register to zero and can change tuning,
voltage, or DMA behavior.

Migrate nonzero values in an optional subsection. Clear the register
before loading so older streams retain the reset default without
changing the main stream version.

Fixes: ea55a22 ("sdhci: implement the Host Control 2 register (tuning sequence)")
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Host Control 2 writes have been conditional on modeled UHS-I support
since commit 0034ebe. Host Version 4 Enable does not control UHS
signaling, so controllers without modeled UHS-I cannot enter version
4 mode.

Retain Host Version 4 Enable independently of UHS-I while continuing
to reject UHS-specific fields and keeping voltage changes UHS-gated.

Fixes: 0034ebe ("sdhci: implement UHS-I voltage switch")
Cc: qemu-stable@nongnu.org
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
SDHCI version 4 moves the SDMA system address from the legacy 32-bit
register at offset 0x00 to the address pair at offsets 0x58 and 0x5c.
At present QEMU always uses the legacy register, so guest SDHCI driver
with version 4 mode enabled uses an incorrect DMA address.

Select the address register from Host Version 4 Enable and honor 64-bit
Addressing when reading and advancing it. Keep the existing offset 0x00
behavior when version 4 mode is disabled.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
The Cadence Linux driver enables version 4 mode and 64-bit addressing in
Host Control 2 but retains the ADMA2 encoding in Host Control 1. QEMU
treats the transfer as 32-bit ADMA and uses 12-byte descriptors because
it only decodes Host Control 1.

Resolve the DMA type from both control registers and use 16-byte version
4 descriptors. Preserve the legacy 12-byte ADMA2 64-bit format when
version 4 mode is disabled.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Version 4 SDMA selects its system address from the registers also named
as the ADMA System Address registers. Updating those registers does not
resume a transfer that stopped at the configured SDMA buffer boundary.

Resume 32-bit addressing after an access completes the lower 32 bits of
the ADMA System Address register. For 64-bit addressing, wait until an
access completes the upper 32 bits so software can update the low half
before the high half without starting from a mixed address.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
The SDHCI model processes the first ADMA descriptor batch inside the
command MMIO write, then resumes pending batches before every later
SDHCI MMIO read or write. This makes register access perform bulk DMA
work and can delay a status read even when completion bits are set.

On the Icicle Kit, U-Boot uses ADMA2-64 and CMD18 to load a roughly
19 MiB FIT image from SD. It can report:

  Timeout for status update: 00000001 00000001
  Timeout for status update: 00000003 00000001

The status already contains the requested Command Complete bit, and may
also contain Transfer Complete. However, reading the interrupt status
first executes a pending ADMA batch. The MMIO read can therefore return
after U-Boot has reached its one-second polling deadline.

Turn the existing transfer timer into an ADMA-only engine. Starting an
ADMA command arms the engine directly, and each timer callback runs one
bounded batch before yielding. MMIO reads and writes no longer perform
or schedule ADMA work. Keep PIO and SDMA synchronous.

Cancel the engine and clear ADMA activity and error state on DATA or ALL
reset.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
SDHC and SDXC memory commands always transfer 512-byte blocks regardless
of the length selected by CMD16. QEMU stores that selected length for
LOCK_UNLOCK but also used it directly for several memory command paths.

Route single- and multi-block memory sizing through the existing helper
that distinguishes high-capacity cards from SDSC.

This lets PolarFire SoC HSS validate the complete GPT header and locate
its boot partition instead of receiving only the eight-byte signature.

Fixes: 2d7adea ("hw/sd: Support SDHC size cards")
Cc: qemu-stable@nongnu.org
Signed-off-by: Bin Meng <bin.meng@processmission.com>
Signed-off-by: Chao Liu <chao.liu@processmission.com>
PolarFire SoC software selects 64-bit ADMA descriptors for the Cadence
SDHCI controller. Advertise 64-bit system bus support so the existing
generic descriptor engine can execute those transfers.

Signed-off-by: Bin Meng <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>
The PolarFire SoC exposes an RTC with binary and calendar modes,
programmable prescaling, alarms, and wakeup and match interrupts.

Add a standalone device model with explicit MMIO handling for time,
commands, alarms, interrupt state, reset, and migration. Add its
Kconfig and Meson entries and list it under the PolarFire SoC
maintainer section.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
The Icicle Kit memory map advertises the PolarFire RTC, but the
machine leaves its MMIO range unmapped. Linux faults when it
programs the RTC prescaler during boot.

Select and instantiate the RTC, map it at the documented address,
and wire its wakeup and match outputs to PLIC interrupts 80 and 81.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
Exercise RTC register masks, binary counter, upload and stop controls,
alarm and wakeup interrupt behavior, reset state, and PLIC wiring on
the Icicle Kit.

Also verify RTC state and pending interrupt migration, including streams
from QEMU versions that predate the RTC device.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Polling firmware requests system services without requesting an
interrupt. The old model ignored this distinction:

1. HSS requests the serial number with REQUEST set and NOTIFY clear.
2. QEMU synchronously fills the mailbox and clears REQUEST.
3. QEMU incorrectly asserts PLIC source 96.
4. HSS polls REQUEST and neither waits for nor handles the interrupt.
5. PLIC source 96 remains pending.
6. Linux registers the MPFS mailbox driver.
7. The stale interrupt immediately enters mpfs_mbox_inbox_isr().
8. Linux has not submitted a request or installed its response pointer.
9. The ISR dereferences that null pointer and faults near address 0x10.

Honor SERVICES_CR.NOTIFY, let IOSCB own the pending interrupt state,
and route the SYSREG acknowledgement through an IOSCB clear input.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
The 64-bit cached and non-cached windows alias the complete physical
DDR from offset zero. Treating them as only the portion above 1 GiB
leaves valid Icicle Kit memory nodes unbacked with the board's 2 GiB.

Map both high windows over the full machine RAM.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
The Icicle Kit has 2 GiB of RAM, and its firmware device tree
describes that fixed capacity. The model currently defaults to
1537 MiB and accepts any larger size, allowing configurations
that do not match the board.

Set the default to 2 GiB and reject every other size. Update the
documentation and L2CC qtest command line accordingly.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
The Icicle Kit always contains one E51 management hart and four U54
application harts. The model currently accepts two to five harts and
defaults to two, allowing configurations that cannot match the board.

Set the minimum and default CPU counts to the five-hart maximum.
Update the documentation to state that other hart counts are rejected.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
With all previous changes, the Icicle Kit model is now able to boot
HSS v2024.06 through a Buildroot 2026.05 SD image to U-Boot and Linux.

Document the tested source versions and exact commands to build HSS
and Buildroot. Include the sparse resize and GPT relocation steps
needed to make the generated SD image usable by QEMU.

Also describe the RAM and serial setup, boot stages, and remaining
model limitations.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
The generic OpenSBI platform derives the CLINT first hart and register
slot count from interrupts-extended.  Some S-mode-only MPFS device trees
mask the E51 M-mode interrupt entries with 0xffffffff, which shifts the
MSIP and MTIMECMP slots when the same DTB is used for direct boot.

Document the complete five-hart CLINT node. Require interrupts 3 and 7
for hart 0 as well as the U54 harts.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
lbmeng and others added 6 commits September 2, 2026 14:50
Add functional coverage using prebuilt HSS and SD card images.

Boot HSS and U-Boot with five harts and 2 GiB of RAM. Connect
the test console to MMUART1 and let U-Boot start Linux.

The complete boot exercises the SDHCI controller in the DMA modes
used at each stage. HSS uses Version 4 64-bit SDMA to load U-Boot.
U-Boot uses ADMA2-64 to read the boot script and the large FIT
image. Linux then selects 64-bit ADMA for SD card and rootfs I/O.

Check the machine identity, kernel ADMA initialization, root
filesystem mount, and login prompt.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Reviewed-by: Chao Liu <chao.liu@processmission.com>
The preceding Icicle Kit updates restore HSS, U-Boot, and Linux
boot. Functional test coverage is also added.

Restore myself as a maintainer and mark the machine as 'Supported'
to reflect its active maintenance.

Signed-off-by: Bin Meng <bin.meng@processmission.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Keep Host Control 2 and SDMA boundary state across migration.

Signed-off-by: Chao Liu <chao.liu@processmission.com>
Run scheduled ADMA before checking completion status.

Signed-off-by: Chao Liu <chao.liu@processmission.com>
Add a standalone qtest for the SDHCI controller on the
xilinx-zynq-a9 machine.

The test covers the SDMA boundary continuation case for a
multi-block read. After the controller stops at a boundary,
software updates SYSAD to continue the transfer. This verifies
the generic SDHCI behavior that previously failed when the
continuation SYSAD write was ignored and the transfer stalled.

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Signed-off-by: Tao Ding <dingtao0430@163.com>
Message-Id: <20260715160731.29969-3-dingtao0430@163.com>
Signed-off-by: Chao Liu <chao.liu@processmission.com>
Ensure the destination completed migration before checking RTC state.

Signed-off-by: Chao Liu <chao.liu@processmission.com>
@zevorn
zevorn force-pushed the codex/pfsoc-sdhci-series branch from 7654ab0 to d606e7c Compare September 2, 2026 06:57
@zevorn

zevorn commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased this series onto the latest devel branch and resolved the SDHCI conflicts while preserving the current base behavior.

The Windows CI failure was caused by the new xilinx-zynq-sdhci-test calling POSIX pwrite(). The test now uses QEMU's portable qemu_write_full() after seeking the test image, with O_BINARY enabled for Windows builds.

The fix is folded into qtest: add xilinx-zynq SDHCI sdma test, with my DCO appended. My DCO is also appended to hw/sd: sd: Keep high-capacity memory blocks at 512 bytes, whose conflict resolution changed that commit.

Local validation:

  • RISC-V L2CC, RTC migration, and SpacemiT K3 qtests: passed.
  • ARM Xilinx Zynq SDHCI SDMA qtest: passed.
  • RISC-V and ARM incremental builds: passed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d606e7c784

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hw/misc/mchp_pfsoc_dmc.c
Comment on lines 341 to +343
dc->desc = "Microchip PolarFire SoC DDR SGMII PHY module";
dc->realize = mchp_pfsoc_ddr_sgmii_phy_realize;
device_class_set_legacy_reset(dc, mchp_pfsoc_ddr_sgmii_phy_reset);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Migrate the DDR PHY training state

When migration occurs after HSS has programmed the modeled PHY, the destination resets regs, training_status_bit, addcmd_tap, and addcmd_move_active because this stateful device installs no VMState description. Migrating during the ADDCMD scan can therefore move its transition points and make training fail, while migrating afterward makes writable PLL/SGMII registers read back differently from the source; serialize these fields so the firmware-visible PHY state survives migration.

Useful? React with 👍 / 👎.

@zevorn
zevorn merged commit 2798247 into devel Sep 5, 2026
96 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants