summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-08-06 14:12:12 -0600
committerTom Rini <[email protected]>2026-08-06 19:36:40 -0600
commitfce4beb533674318de796eac9b4f1a49ded7bef6 (patch)
tree139e4b9c925b50a80ee795fa685952b0f00e8473
parent482f9d63b504ba9d33dbfbd6610801d8386c9b13 (diff)
parent98b59e181daa6c26d49f870fd58df8996b1cd7f1 (diff)
Merge branch 'main' of https://git.u-boot-project.org/u-boot/custodians/u-boot-riscv
CI: https://git.u-boot-project.org/u-boot/custodians/u-boot-riscv/-/pipelines/884 - board: MPFS: add hardware RNG support and fix RNG consumers - board: sophgo: add support for Milk-V Duo 256M
-rw-r--r--arch/riscv/Kconfig4
-rw-r--r--arch/riscv/dts/Makefile1
-rw-r--r--arch/riscv/dts/sg2002-milkv-duo256m.dts46
-rw-r--r--board/sophgo/common/ethernet.c (renamed from board/sophgo/milkv_duo/ethernet.c)0
-rw-r--r--board/sophgo/common/ethernet.h (renamed from board/sophgo/milkv_duo/ethernet.h)0
-rw-r--r--board/sophgo/milkv_duo/MAINTAINERS1
-rw-r--r--board/sophgo/milkv_duo/Makefile2
-rw-r--r--board/sophgo/milkv_duo/board.c2
-rw-r--r--board/sophgo/milkv_duo_256m/Kconfig30
-rw-r--r--board/sophgo/milkv_duo_256m/MAINTAINERS5
-rw-r--r--board/sophgo/milkv_duo_256m/Makefile6
-rw-r--r--board/sophgo/milkv_duo_256m/milkv_duo_256m.env8
-rw-r--r--configs/microchip_mpfs_generic_defconfig3
-rw-r--r--configs/milkv_duo_256m_defconfig42
-rw-r--r--doc/board/sophgo/index.rst1
-rw-r--r--doc/board/sophgo/milkv_duo_256m.rst84
-rw-r--r--drivers/mailbox/mpfs-mbox.c27
-rw-r--r--drivers/misc/mpfs_syscontroller.c36
-rw-r--r--drivers/rng/Kconfig7
-rw-r--r--drivers/rng/Makefile1
-rw-r--r--drivers/rng/mpfs_rng.c101
-rw-r--r--include/configs/milkv_duo_256m.h12
-rw-r--r--include/mpfs-mailbox.h2
23 files changed, 407 insertions, 14 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 0865620912c..c1b2890f1f3 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -29,6 +29,9 @@ config TARGET_MICROCHIP_GENERIC
config TARGET_MILKV_DUO
bool "Support Milk-v Duo Board"
+config TARGET_MILKV_DUO_256M
+ bool "Support Milk-V Duo 256M Board"
+
config TARGET_OPENPITON_RISCV64
bool "Support RISC-V cores on OpenPiton SoC"
@@ -118,6 +121,7 @@ source "board/sifive/unleashed/Kconfig"
source "board/sifive/unmatched/Kconfig"
source "board/sipeed/maix/Kconfig"
source "board/sophgo/milkv_duo/Kconfig"
+source "board/sophgo/milkv_duo_256m/Kconfig"
source "board/sophgo/licheerv_nano/Kconfig"
source "board/spacemit/k1/Kconfig"
source "board/starfive/visionfive2/Kconfig"
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 71c5c13d221..8ba75fdb9f5 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -5,6 +5,7 @@ dtb-$(CONFIG_TARGET_ANDES_VOYAGER) += qilai-voyager.dtb
dtb-$(CONFIG_TARGET_K230_CANMV) += k230-canmv.dtb
dtb-$(CONFIG_TARGET_MICROCHIP_ICICLE) += mpfs-icicle-kit.dtb
dtb-$(CONFIG_TARGET_MILKV_DUO) += cv1800b-milkv-duo.dtb
+dtb-$(CONFIG_TARGET_MILKV_DUO_256M) += sg2002-milkv-duo256m.dtb
dtb-$(CONFIG_TARGET_LICHEERV_NANO) += sg2002-licheerv-nano-b.dtb
dtb-$(CONFIG_TARGET_QEMU_VIRT) += qemu-virt32.dtb qemu-virt64.dtb
dtb-$(CONFIG_TARGET_OPENPITON_RISCV64) += openpiton-riscv64.dtb
diff --git a/arch/riscv/dts/sg2002-milkv-duo256m.dts b/arch/riscv/dts/sg2002-milkv-duo256m.dts
new file mode 100644
index 00000000000..4ad86ce39ec
--- /dev/null
+++ b/arch/riscv/dts/sg2002-milkv-duo256m.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2026 Hiago De Franco <[email protected]>
+ */
+
+/dts-v1/;
+
+#include "sg2002.dtsi"
+
+/ {
+ model = "Milk-V Duo 256M";
+ compatible = "milkv,duo256m", "sophgo,sg2002";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&ethernet0 {
+ status = "okay";
+ phy-mode = "rmii";
+};
+
+&osc {
+ clock-frequency = <25000000>;
+};
+
+&sdhci0 {
+ status = "okay";
+ bus-width = <4>;
+ no-1-8-v;
+ no-mmc;
+ no-sdio;
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/board/sophgo/milkv_duo/ethernet.c b/board/sophgo/common/ethernet.c
index e997ce1037f..e997ce1037f 100644
--- a/board/sophgo/milkv_duo/ethernet.c
+++ b/board/sophgo/common/ethernet.c
diff --git a/board/sophgo/milkv_duo/ethernet.h b/board/sophgo/common/ethernet.h
index 7b21f1b0f66..7b21f1b0f66 100644
--- a/board/sophgo/milkv_duo/ethernet.h
+++ b/board/sophgo/common/ethernet.h
diff --git a/board/sophgo/milkv_duo/MAINTAINERS b/board/sophgo/milkv_duo/MAINTAINERS
index 651a0592f7a..6941dc5b376 100644
--- a/board/sophgo/milkv_duo/MAINTAINERS
+++ b/board/sophgo/milkv_duo/MAINTAINERS
@@ -2,5 +2,6 @@ Milk-V Duo
M: Kongyang Liu <[email protected]>
S: Maintained
F: board/sophgo/milkv_duo/
+F: board/sophgo/common/
F: configs/milkv_duo_defconfig
F: doc/board/sophgo/milkv_duo.rst
diff --git a/board/sophgo/milkv_duo/Makefile b/board/sophgo/milkv_duo/Makefile
index 18ada7d72ff..aa321d15687 100644
--- a/board/sophgo/milkv_duo/Makefile
+++ b/board/sophgo/milkv_duo/Makefile
@@ -3,4 +3,4 @@
# Copyright (c) 2024, Kongyang Liu <[email protected]>
obj-y += board.o
-obj-$(CONFIG_NET_LEGACY) += ethernet.o
+obj-$(CONFIG_NET_LEGACY) += ../common/ethernet.o
diff --git a/board/sophgo/milkv_duo/board.c b/board/sophgo/milkv_duo/board.c
index f0944859b58..34339c42925 100644
--- a/board/sophgo/milkv_duo/board.c
+++ b/board/sophgo/milkv_duo/board.c
@@ -5,7 +5,7 @@
#include <dm/lists.h>
-#include "ethernet.h"
+#include "../common/ethernet.h"
int board_init(void)
{
diff --git a/board/sophgo/milkv_duo_256m/Kconfig b/board/sophgo/milkv_duo_256m/Kconfig
new file mode 100644
index 00000000000..a443207f65e
--- /dev/null
+++ b/board/sophgo/milkv_duo_256m/Kconfig
@@ -0,0 +1,30 @@
+if TARGET_MILKV_DUO_256M
+
+config SYS_BOARD
+ default "milkv_duo_256m"
+
+config SYS_VENDOR
+ default "sophgo"
+
+config SYS_CPU
+ default "cv1800b"
+
+config SYS_CONFIG_NAME
+ default "milkv_duo_256m"
+
+# The vendor FIP tool prepends a 32-byte loader header to u-boot.bin and loads
+# the result at 0x80200000, so the U-Boot code runs 0x20 bytes above that.
+config TEXT_BASE
+ default 0x80200020
+
+config ENV_SIZE
+ default 0x20000
+
+config ENV_SECT_SIZE
+ default 0x40000
+
+config BOARD_SPECIFIC_OPTIONS
+ def_bool y
+ select SOPHGO_CV1800B
+
+endif
diff --git a/board/sophgo/milkv_duo_256m/MAINTAINERS b/board/sophgo/milkv_duo_256m/MAINTAINERS
new file mode 100644
index 00000000000..929960e7251
--- /dev/null
+++ b/board/sophgo/milkv_duo_256m/MAINTAINERS
@@ -0,0 +1,5 @@
+Milk-V Duo 256M
+M: Hiago De Franco <[email protected]>
+S: Maintained
+F: board/sophgo/milkv_duo_256m/
+F: configs/milkv_duo_256m_defconfig
diff --git a/board/sophgo/milkv_duo_256m/Makefile b/board/sophgo/milkv_duo_256m/Makefile
new file mode 100644
index 00000000000..c3068e56bf4
--- /dev/null
+++ b/board/sophgo/milkv_duo_256m/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2026, Hiago De Franco <[email protected]>
+
+obj-y += ../milkv_duo/board.o
+obj-$(CONFIG_NET_LEGACY) += ../common/ethernet.o
diff --git a/board/sophgo/milkv_duo_256m/milkv_duo_256m.env b/board/sophgo/milkv_duo_256m/milkv_duo_256m.env
new file mode 100644
index 00000000000..4c1e17b53ca
--- /dev/null
+++ b/board/sophgo/milkv_duo_256m/milkv_duo_256m.env
@@ -0,0 +1,8 @@
+fdt_addr_r=0x84000000
+fdtfile=CONFIG_DEFAULT_DEVICE_TREE.dtb
+kernel_addr_r=0x80200000
+kernel_comp_addr_r=0x88000000
+kernel_comp_size=0x4000000
+pxefile_addr_r=0x84300000
+ramdisk_addr_r=0x84400000
+scriptaddr=0x84200000
diff --git a/configs/microchip_mpfs_generic_defconfig b/configs/microchip_mpfs_generic_defconfig
index 973ed09fa87..e3d794f08b9 100644
--- a/configs/microchip_mpfs_generic_defconfig
+++ b/configs/microchip_mpfs_generic_defconfig
@@ -21,6 +21,7 @@ CONFIG_SYS_PBSIZE=282
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_CMD_RNG=y
CONFIG_OF_UPSTREAM=y
CONFIG_OF_BOARD=y
CONFIG_OF_LIST="microchip/mpfs-icicle-kit microchip/mpfs-sev-kit"
@@ -29,4 +30,6 @@ CONFIG_ENV_OVERWRITE_ETHADDR_ONCE=y
CONFIG_ENV_RELOC_GD_ENV_ADDR=y
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_DM_MTD=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_MPFS=y
CONFIG_SYSRESET=y
diff --git a/configs/milkv_duo_256m_defconfig b/configs/milkv_duo_256m_defconfig
new file mode 100644
index 00000000000..9d92eec6394
--- /dev/null
+++ b/configs/milkv_duo_256m_defconfig
@@ -0,0 +1,42 @@
+CONFIG_RISCV=y
+CONFIG_SYS_MALLOC_LEN=0x820000
+CONFIG_SYS_MALLOC_F_LEN=0x8000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x82300000
+CONFIG_DEFAULT_DEVICE_TREE="sg2002-milkv-duo256m"
+CONFIG_SYS_LOAD_ADDR=0x80080000
+CONFIG_IDENT_STRING="milkv_duo_256m"
+CONFIG_TARGET_MILKV_DUO_256M=y
+CONFIG_ARCH_RV64I=y
+CONFIG_RISCV_SMODE=y
+CONFIG_FIT=y
+CONFIG_BOOTSTD_FULL=y
+# CONFIG_BOOTMETH_EFI_BOOTMGR is not set
+CONFIG_SD_BOOT=y
+CONFIG_SYS_CBSIZE=512
+CONFIG_SYS_PBSIZE=544
+CONFIG_SYS_PROMPT="milkv_duo_256m# "
+# CONFIG_CMD_BOOTDEV is not set
+CONFIG_CMD_MBR=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_POWEROFF=y
+# CONFIG_CMD_MII is not set
+CONFIG_CMD_EXT4_WRITE=y
+# CONFIG_ISO_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+CONFIG_ENV_OVERWRITE=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK_SOPHGO_CV1800B=y
+CONFIG_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ADMA=y
+CONFIG_MMC_SDHCI_CV1800B=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_SYS_NS16550=y
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_SPI=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CV1800B=y
diff --git a/doc/board/sophgo/index.rst b/doc/board/sophgo/index.rst
index 26dba4a4851..19c9a19b1d4 100644
--- a/doc/board/sophgo/index.rst
+++ b/doc/board/sophgo/index.rst
@@ -6,4 +6,5 @@ Sophgo
:maxdepth: 1
milkv_duo
+ milkv_duo_256m
licheerv_nano
diff --git a/doc/board/sophgo/milkv_duo_256m.rst b/doc/board/sophgo/milkv_duo_256m.rst
new file mode 100644
index 00000000000..9e2cbddf4db
--- /dev/null
+++ b/doc/board/sophgo/milkv_duo_256m.rst
@@ -0,0 +1,84 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Milk-V Duo 256M
+===============
+
+SG2002 RISC-V SoC
+------------------
+The SG2002 is a high-performance, low-power 64-bit RISC-V/ARM SoC from Sophgo.
+
+Mainline support
+----------------
+The support for following drivers are already enabled:
+
+1. ns16550 UART Driver.
+2. Synopsys Designware MSHC Driver.
+3. Synopsys Designware Ethernet Controller.
+
+Building
+~~~~~~~~
+1. Add the RISC-V toolchain to your PATH.
+2. Setup ARCH & cross compilation environment variable:
+
+.. code-block:: console
+
+ export CROSS_COMPILE=<riscv64 toolchain prefix>
+ cd <U-Boot-dir>
+ make milkv_duo_256m_defconfig
+ make
+
+This will generate u-boot.bin
+
+Booting
+~~~~~~~
+Currently, we rely on vendor FSBL (First Stage Boot Loader) to initialize the
+clock and load OpenSBI and the u-boot image, then bootup from it.
+
+To run u-boot.bin on top of FSBL, follow these steps:
+
+1. Generate a compatible u-boot.bin using U-Boot with the Milk-V Duo 256M
+ default configuration.
+
+2. Use mainline OpenSBI with a newer version than 1.5 to generate fw_dynamic.
+ Use FDT_FW_PATH to point to sg2002-milkv-duo256m.dtb device tree file while
+ compiling fw_dynamic. Example:
+
+.. code-block:: console
+
+ cd open-sbi
+ PLATFORM=generic FW_FDT_PATH=../u-boot/arch/riscv/dts/sg2002-milkv-duo256m.dtb make
+
+This will generate build/platform/generic/firmware/fw_dynamic.bin.
+
+3. Use the vendor-provided tool [1] to create a unified fip.bin file containing
+ FSBL, OpenSBI, and U-Boot.
+ Note that you will have to use the file cv181x.bin as the FSBL.
+
+4. Place the generated fip.bin file into the FAT partition of the SD card.
+
+5. Insert the SD card into the board and power it on.
+
+The board will automatically execute the FSBL from the fip.bin file.
+Subsequently, it will transition to OpenSBI, and finally, OpenSBI will invoke
+U-Boot.
+
+[1]: https://github.com/sophgo/fiptool
+
+Sample boot log from Milk-V 256M Duo board
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. code-block:: none
+
+ U-Boot 2026.07-00002-g0b690770386f-dirty (Jul 07 2026 - 13:33:36 -0300)milkv_duo_256m
+
+ DRAM: 256 MiB
+ Core: 20 devices, 13 uclasses, devicetree: separate
+ MMC: mmc@4310000: 0
+ Loading Environment from nowhere... OK
+ In: serial@4140000
+ Out: serial@4140000
+ Err: serial@4140000
+ Net:
+ Warning: ethernet@4070000 (eth0) using random MAC address - 0a:f3:23:40:7e:55
+ eth0: ethernet@4070000
+ Hit any key to stop autoboot: 0
+ milkv_duo_256m#
diff --git a/drivers/mailbox/mpfs-mbox.c b/drivers/mailbox/mpfs-mbox.c
index b1ce377525e..8b7a2719330 100644
--- a/drivers/mailbox/mpfs-mbox.c
+++ b/drivers/mailbox/mpfs-mbox.c
@@ -18,6 +18,7 @@
#include <linux/compat.h>
#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/iopoll.h>
#include <log.h>
#include <mailbox-uclass.h>
#include <mpfs-mailbox.h>
@@ -60,11 +61,15 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data)
u32 mailbox_val, cmd_shifted, value;
u8 *byte_buf;
u8 idx, byte_idx, byte_offset;
+ int ret;
u32 *word_buf = (u32 *)msg->cmd_data;
- if (mpfs_mbox_busy(chan))
- return -EBUSY;
+ ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_SR_OFFSET,
+ value, !(value & SERVICE_SR_BUSY_MASK),
+ 1, 20);
+ if (ret)
+ return ret;
for (idx = 0; idx < (msg->cmd_data_size / BYTES_4); idx++)
writel(word_buf[idx], mbox->mbox_base + msg->mbox_offset + idx * BYTES_4);
@@ -86,13 +91,19 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data)
regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, cmd_shifted);
- do {
- regmap_read(mbox->control_scb, SERVICES_CR_OFFSET, &value);
- } while (SERVICE_CR_REQ_MASK == (value & SERVICE_CR_REQ_MASK));
+ ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_CR_OFFSET,
+ value, !(value & SERVICE_CR_REQ_MASK),
+ 1, /* poll every 1 µs */
+ 20); /* timeout 20 ms */
+ if (ret)
+ return ret;
- do {
- regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &value);
- } while (SERVICE_SR_BUSY_MASK == (value & SERVICE_SR_BUSY_MASK));
+ ret = regmap_read_poll_timeout(mbox->control_scb, SERVICES_SR_OFFSET,
+ value, !(value & SERVICE_SR_BUSY_MASK),
+ 1,
+ 20);
+ if (ret)
+ return ret;
msg->response->resp_status = (value >> SERVICE_SR_STATUS_SHIFT);
if (msg->response->resp_status)
diff --git a/drivers/misc/mpfs_syscontroller.c b/drivers/misc/mpfs_syscontroller.c
index f608d5518b0..b9aea7e1181 100644
--- a/drivers/misc/mpfs_syscontroller.c
+++ b/drivers/misc/mpfs_syscontroller.c
@@ -11,6 +11,7 @@
#include <asm/system.h>
#include <dm.h>
#include <dm/device_compat.h>
+#include <dm/lists.h>
#include <env.h>
#include <errno.h>
#include <linux/compat.h>
@@ -86,6 +87,30 @@ int mpfs_syscontroller_run_service(struct mpfs_syscontroller_priv *sys_controlle
EXPORT_SYMBOL_GPL(mpfs_syscontroller_run_service);
/**
+ * mpfs_syscontroller_recv_response() - Receive the MPFS system service response
+ * @sys_controller: MPFS system controller instance
+ * @msg: System service message
+ * @timeout_ms: Timeout in milliseconds
+ *
+ * Receive the mailbox response for a previously issued MPFS system
+ * controller service request and populate the response buffer.
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+int mpfs_syscontroller_recv_response(struct mpfs_syscontroller_priv *sys_controller, struct
+ mpfs_mss_msg * msg, unsigned long timeout_ms)
+{
+ int ret;
+
+ ret = mbox_recv(&sys_controller->chan, msg, timeout_ms);
+ if (ret)
+ dev_err(sys_controller->chan.dev, "Service failed: %d, abort. Failure: %u\n", ret,
+ msg->response->resp_status);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mpfs_syscontroller_recv_response);
+
+/**
* mpfs_syscontroller_read_sernum() - Use system service to read the device serial number
* @sys_serv_priv: system service private data
* @device_serial_number: device serial number
@@ -116,11 +141,9 @@ int mpfs_syscontroller_read_sernum(struct mpfs_sys_serv *sys_serv_priv, u8 *devi
}
/* Receive the response */
- ret = mbox_recv(&sys_serv_priv->sys_controller->chan, &msg, timeoutsecs);
- if (ret) {
- dev_err(sys_serv_priv->sys_controller->chan.dev, "Service failed: %d, abort. Failure: %u\n", ret, msg.response->resp_status);
+ ret = mpfs_syscontroller_recv_response(sys_serv_priv->sys_controller, &msg, timeoutsecs);
+ if (ret)
return ret;
- }
debug("%s: Read successful %s\n",
__func__, sys_serv_priv->sys_controller->chan.dev->name);
@@ -312,6 +335,7 @@ EXPORT_SYMBOL(mpfs_syscontroller_process_dtbo);
static int mpfs_syscontroller_probe(struct udevice *dev)
{
struct mpfs_syscontroller_priv *sys_controller = dev_get_priv(dev);
+ struct udevice *rng_dev;
int ret;
ret = mbox_get_by_index(dev, 0, &sys_controller->chan);
@@ -321,6 +345,10 @@ static int mpfs_syscontroller_probe(struct udevice *dev)
return ret;
}
+ ret = device_bind_driver(dev, "mpfs_rng", "mpfs-rng", &rng_dev);
+ if (ret)
+ dev_err(dev, "Failed to bind mpfs_rng: %d\n", ret);
+
init_completion(&sys_controller->c);
dev_info(dev, "Registered MPFS system controller\n");
diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig
index 19b2b707677..bacb026308b 100644
--- a/drivers/rng/Kconfig
+++ b/drivers/rng/Kconfig
@@ -23,6 +23,13 @@ config RNG_MESON
Enable support for hardware random number generator
of Amlogic Meson SoCs.
+config RNG_MPFS
+ bool "Microchip PolarFire SoC Random Number Generator support"
+ depends on DM_RNG && MPFS_SYSCONTROLLER
+ help
+ Enable support for hardware random number generator
+ of Microchip's PolarFire SoCs.
+
config RNG_SANDBOX
bool "Sandbox random number generator"
depends on SANDBOX
diff --git a/drivers/rng/Makefile b/drivers/rng/Makefile
index 30c58272d41..50622d4705f 100644
--- a/drivers/rng/Makefile
+++ b/drivers/rng/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_$(PHASE_)DM_RNG) += rng-uclass.o
obj-$(CONFIG_RNG_MESON) += meson-rng.o
+obj-$(CONFIG_RNG_MPFS) += mpfs_rng.o
obj-$(CONFIG_RNG_SANDBOX) += sandbox_rng.o
obj-$(CONFIG_RNG_MSM) += msm_rng.o
obj-$(CONFIG_RNG_NPCM) += npcm_rng.o
diff --git a/drivers/rng/mpfs_rng.c b/drivers/rng/mpfs_rng.c
new file mode 100644
index 00000000000..820103a0202
--- /dev/null
+++ b/drivers/rng/mpfs_rng.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Microchip's PolarFire SoC (MPFS) System Controller Driver
+ *
+ * Copyright (C) 2026 Microchip Technology Inc. All rights reserved.
+ *
+ * Author: Jamie Gibbons <[email protected]>
+ *
+ */
+
+#include <dm.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/printk.h>
+#include <mailbox.h>
+#include <malloc.h>
+#include <mpfs-mailbox.h>
+#include <rng.h>
+#include <string.h>
+
+#define CMD_OPCODE 0x21
+#define CMD_DATA_SIZE 0U
+#define CMD_DATA NULL
+#define MBOX_OFFSET 0U
+#define RESP_OFFSET 0U
+#define RNG_RESP_BYTES 32U
+
+/**
+ * struct mpfs_rng_priv - Structure representing System Controller data.
+ * @mpfs_syscontroller_priv: System Controller
+ */
+struct mpfs_rng_priv {
+ struct mpfs_syscontroller_priv *sys_controller;
+};
+
+static int mpfs_rng_read(struct udevice *dev, void *data, size_t len)
+{
+ struct mpfs_rng_priv *rng_priv = dev_get_priv(dev);
+ u32 response_msg[RNG_RESP_BYTES / sizeof(u32)];
+ size_t count = 0, copy_size;
+ int ret;
+
+ struct mpfs_mss_response response = {
+ .resp_status = 0U,
+ .resp_msg = (u32 *)response_msg,
+ .resp_size = RNG_RESP_BYTES,
+ };
+ struct mpfs_mss_msg msg = {
+ .cmd_opcode = CMD_OPCODE,
+ .cmd_data_size = CMD_DATA_SIZE,
+ .response = &response,
+ .cmd_data = CMD_DATA,
+ .mbox_offset = MBOX_OFFSET,
+ .resp_offset = RESP_OFFSET,
+ };
+
+ while (count < len) {
+ ret = mpfs_syscontroller_run_service(rng_priv->sys_controller, &msg);
+ if (ret)
+ return ret;
+
+ ret = mpfs_syscontroller_recv_response(rng_priv->sys_controller, &msg, 1000);
+ if (ret)
+ return ret;
+
+ copy_size = (len - count > RNG_RESP_BYTES) ? RNG_RESP_BYTES : (len - count);
+ memcpy((u8 *)data + count, response_msg, copy_size);
+ count += copy_size;
+ }
+
+ return 0;
+}
+
+static int mpfs_rng_probe(struct udevice *dev)
+{
+ struct mpfs_rng_priv *rng_priv = dev_get_priv(dev);
+
+ rng_priv->sys_controller = mpfs_syscontroller_get(dev->parent);
+ if (IS_ERR(rng_priv->sys_controller)) {
+ dev_err(dev, "Failed to get system controller\n");
+ return PTR_ERR(rng_priv->sys_controller);
+ }
+
+ return 0;
+}
+
+static const struct dm_rng_ops mpfs_rng_ops = {
+ .read = mpfs_rng_read,
+};
+
+U_BOOT_DRIVER(mpfs_rng) = {
+ .name = "mpfs_rng",
+ .id = UCLASS_RNG,
+ .probe = mpfs_rng_probe,
+ .priv_auto = sizeof(struct mpfs_rng_priv),
+ .ops = &mpfs_rng_ops,
+};
diff --git a/include/configs/milkv_duo_256m.h b/include/configs/milkv_duo_256m.h
new file mode 100644
index 00000000000..4d6678b9c84
--- /dev/null
+++ b/include/configs/milkv_duo_256m.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2026, Hiago De Franco <[email protected]>
+ *
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CFG_SYS_SDRAM_BASE 0x80000000
+
+#endif /* __CONFIG_H */
diff --git a/include/mpfs-mailbox.h b/include/mpfs-mailbox.h
index c0ff327a4ce..39c998e4c8d 100644
--- a/include/mpfs-mailbox.h
+++ b/include/mpfs-mailbox.h
@@ -58,6 +58,8 @@ struct mpfs_sys_serv {
};
int mpfs_syscontroller_run_service(struct mpfs_syscontroller_priv *sys_controller, struct mpfs_mss_msg *msg);
+int mpfs_syscontroller_recv_response(struct mpfs_syscontroller_priv
+ *sys_controller, struct mpfs_mss_msg *msg, unsigned long timeout_ms);
int mpfs_syscontroller_read_sernum(struct mpfs_sys_serv *sys_serv_priv, u8 *device_serial_number);
void mpfs_syscontroller_process_dtbo(struct mpfs_sys_serv *sys_serv_priv);
struct mpfs_syscontroller_priv *mpfs_syscontroller_get(struct udevice *dev);