From a5f93037f28624c612288e2d97604d73e03af5a3 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:44 +0100 Subject: misc: mpfs_syscontroller: add mailbox RX helper for service responses The MPFS system controller run_service() helper only submits the mailbox request but does not read back the response data. However, the caller must explicitly receive the response. Add a public system controller helper to receive mailbox service responses to populate the response buffer after issuing a system controller request. Without this, the drivers copy uninitialised stack data instead of mailbox response data, resulting in deterministic output. Signed-off-by: Jamie Gibbons Acked-by: Conor Dooley --- drivers/misc/mpfs_syscontroller.c | 30 ++++++++++++++++++++++++++---- include/mpfs-mailbox.h | 2 ++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/misc/mpfs_syscontroller.c b/drivers/misc/mpfs_syscontroller.c index f608d5518b0..d29cb2e9e59 100644 --- a/drivers/misc/mpfs_syscontroller.c +++ b/drivers/misc/mpfs_syscontroller.c @@ -85,6 +85,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 @@ -116,11 +140,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); 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); -- cgit v1.3.1 From 752704d854fd22985470b03df8d4b303c265b307 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:45 +0100 Subject: misc: mpfs_syscontroller: bind RNG sub-device The MPFS RNG driver is not described by the device tree and is instead registered dynamically by the system controller. Explicitly bind the MPFS RNG driver as a child device during system controller probe. This ensures the RNG device is instantiated and available via UCLASS_RNG without requiring a device tree node. Signed-off-by: Jamie Gibbons Acked-by: Conor Dooley --- drivers/misc/mpfs_syscontroller.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/misc/mpfs_syscontroller.c b/drivers/misc/mpfs_syscontroller.c index d29cb2e9e59..b9aea7e1181 100644 --- a/drivers/misc/mpfs_syscontroller.c +++ b/drivers/misc/mpfs_syscontroller.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -334,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); @@ -343,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"); -- cgit v1.3.1 From c58dc99616b5ec6bc8dbec143c4888cc42f775b7 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:46 +0100 Subject: rng: add Microchip PolarFire SoC hardware RNG driver Add a U-Boot RNG driver for Microchip's PolarFire SoC (MPFS). The hardware RNG is accessed indirectly via the MPFS system controller using the mailbox interface. The driver implements the UCLASS_RNG interface, requesting random data from the system controller and returning it to the caller. This allows use of the PolarFire SoC hardware RNG via the standard 'rng' command and DM RNG API. Signed-off-by: Jamie Gibbons Reviewed-by: Leo Yu-Chi Liang --- drivers/rng/Kconfig | 7 ++++ drivers/rng/Makefile | 1 + drivers/rng/mpfs_rng.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 drivers/rng/mpfs_rng.c 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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, +}; -- cgit v1.3.1 From 899cbeee1c8a521cf9f2c4242bc17c26c6ebc448 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:47 +0100 Subject: configs: microchip_mpfs_generic: enable MPFS RNG support Enable the MPFS hardware RNG and associated infrastructure in the Microchip PolarFire SoC generic defconfig. Signed-off-by: Jamie Gibbons Reviewed-by: Leo Yu-Chi Liang --- configs/microchip_mpfs_generic_defconfig | 3 +++ 1 file changed, 3 insertions(+) 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 -- cgit v1.3.1 From 47cd1fd361e61be4c8293e02aa4b6c60c2d26d76 Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:48 +0100 Subject: mailbox: mpfs-mbox: replace unbounded BUSY polling with bounded waits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MPFS mailbox driver used unbounded polling loops and treated the BUSY bit as a fatal condition in several paths. On MPFS, BUSY may be transiently reasserted even after response data is written, which is observable in U-Boot’s synchronous, polled execution model. Replace the unbounded loops with a bounded regmap_read_poll_timeout()-based helper that waits for the controller to become idle. This preserves existing behaviour while preventing infinite stalls and avoiding spurious failures during early boot. Signed-off-by: Jamie Gibbons Reviewed-by: Conor Dooley --- drivers/mailbox/mpfs-mbox.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/mailbox/mpfs-mbox.c b/drivers/mailbox/mpfs-mbox.c index b1ce377525e..165d9d89630 100644 --- a/drivers/mailbox/mpfs-mbox.c +++ b/drivers/mailbox/mpfs-mbox.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ 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; @@ -86,13 +88,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) -- cgit v1.3.1 From d803fb548e5844306830702438381c27373ce6ba Mon Sep 17 00:00:00 2001 From: Jamie Gibbons Date: Wed, 22 Jul 2026 16:45:49 +0100 Subject: mailbox: mpfs: add bounded wait for BUSY to clear before sending request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MPFS mailbox driver currently checks the BUSY bit at the start of mpfs_mbox_send() and immediately returns -EBUSY if the controller is busy. On MPFS, BUSY may be transiently asserted during early boot even though no other U-Boot service is actively executing. In Linux, returning -EBUSY here is retryable via the mailbox framework and scheduler, but in U-Boot this results in a hard failure. Replace the immediate BUSY check with a bounded wait using regmap_read_poll_timeout(), waiting for the controller to become idle before issuing a new request. This preserves the intent of the BUSY check while avoiding spurious early-boot failures in U-Boot’s synchronous, polled execution model. The timeout is conservative and based on observed MPFS behaviour, where BUSY clears within a few milliseconds. Signed-off-by: Jamie Gibbons Reviewed-by: Conor Dooley --- drivers/mailbox/mpfs-mbox.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mailbox/mpfs-mbox.c b/drivers/mailbox/mpfs-mbox.c index 165d9d89630..8b7a2719330 100644 --- a/drivers/mailbox/mpfs-mbox.c +++ b/drivers/mailbox/mpfs-mbox.c @@ -65,8 +65,11 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data) 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); -- cgit v1.3.1 From bacb61a06fd36661959ee8109e50f7e6eda76be1 Mon Sep 17 00:00:00 2001 From: Hiago De Franco Date: Thu, 23 Jul 2026 11:44:34 -0300 Subject: board: sophgo: move ethernet driver to common directory This will make easier for future boards to reuse the same driver (e.g. Milk-V Duo 256MB). Signed-off-by: Hiago De Franco Acked-by: Leo Yu-Chi Liang --- board/sophgo/common/ethernet.c | 79 ++++++++++++++++++++++++++++++++++++++ board/sophgo/common/ethernet.h | 11 ++++++ board/sophgo/milkv_duo/MAINTAINERS | 1 + board/sophgo/milkv_duo/Makefile | 2 +- board/sophgo/milkv_duo/board.c | 2 +- board/sophgo/milkv_duo/ethernet.c | 79 -------------------------------------- board/sophgo/milkv_duo/ethernet.h | 11 ------ 7 files changed, 93 insertions(+), 92 deletions(-) create mode 100644 board/sophgo/common/ethernet.c create mode 100644 board/sophgo/common/ethernet.h delete mode 100644 board/sophgo/milkv_duo/ethernet.c delete mode 100644 board/sophgo/milkv_duo/ethernet.h diff --git a/board/sophgo/common/ethernet.c b/board/sophgo/common/ethernet.c new file mode 100644 index 00000000000..e997ce1037f --- /dev/null +++ b/board/sophgo/common/ethernet.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu + */ + +#include +#include +#include + +#define REG_EPHY_TOP_WRAP (u32 *)0x03009800 +#define REG_EPHY_BASE (u32 *)0x03009000 + +#define REG_EPHY_CTL REG_EPHY_TOP_WRAP +#define REG_EPHY_APB_RW_SEL REG_EPHY_TOP_WRAP + 1 + +/* Page 0 register */ +#define REG_PHY_ID1 REG_EPHY_BASE + MII_PHYSID1 +#define REG_PHY_ID2 REG_EPHY_BASE + MII_PHYSID2 +#define REG_PHY_PAGE_SEL REG_EPHY_BASE + 0x1f + +/* Page 5 register */ +#define REG_PD_EN_CTL REG_EPHY_BASE + 0x10 + +/* REG_EPHY_CTL */ +#define REG_EPHY_SHUTDOWN BIT(0) +#define REG_EPHY_ANA_RST_N BIT(1) +#define REG_EPHY_DIG_RST_N BIT(2) +#define REG_EPHY_MAIN_RST_N BIT(3) + +/* REG_PD_EN_CTL */ +#define REG_EN_ETH_TXRT BIT(0) +#define REG_EN_ETH_CLK100M BIT(1) +#define REG_EN_ETH_CLK125M BIT(2) +#define REG_EN_ETH_PLL_LCKDET BIT(3) +#define REG_EN_ETH_RXADC BIT(4) +#define REG_EN_ETH_RXPGA BIT(5) +#define REG_EN_ETH_RXRT BIT(6) +#define REG_EN_ETH_TXCROSSOVER BIT(7) +#define REG_PD_ETH_PLL BIT(8) +#define REG_PD_ETH_TXDAC BIT(9) +#define REG_PD_ETH_TXDACBST BIT(10) +#define REG_PD_ETH_TXECHO BIT(11) +#define REG_PD_ETH_TXDRV_NMOS BIT(12) +#define REG_PD_ETH_TXLDO BIT(13) + +void cv1800b_ephy_init(void) +{ + u32 reg; + u32 phy_id = 1; + + /* enable direct memory access for phy register */ + writel(1, REG_EPHY_APB_RW_SEL); + + reg = readl(REG_EPHY_CTL); + reg &= ~REG_EPHY_SHUTDOWN; + reg |= REG_EPHY_ANA_RST_N | REG_EPHY_DIG_RST_N | REG_EPHY_MAIN_RST_N; + writel(reg, REG_EPHY_CTL); + + /* switch to page 5 */ + writel(5 << 8, REG_PHY_PAGE_SEL); + reg = readl(REG_PD_EN_CTL); + reg &= ~(REG_PD_ETH_TXLDO | REG_PD_ETH_TXDRV_NMOS | REG_PD_ETH_TXDAC | REG_PD_ETH_PLL); + reg |= REG_EN_ETH_TXRT | REG_EN_ETH_CLK100M | REG_EN_ETH_CLK125M + | REG_EN_ETH_PLL_LCKDET | REG_EN_ETH_RXADC | REG_EN_ETH_RXPGA | REG_EN_ETH_RXRT; + writel(reg, REG_PD_EN_CTL); + + /* switch to page 0 */ + writel(0 << 8, REG_PHY_PAGE_SEL); + /* + * As the phy_id in the cv1800b PHY register is initialized to 0, it + * is necessary to manually initialize the phy_id to an arbitrary + * value so that it could corresponds to the generic PHY driver. + */ + writel(phy_id >> 16, REG_PHY_ID1); + writel(phy_id & 0xffff, REG_PHY_ID2); + + /* switch to MDIO control */ + writel(0, REG_EPHY_APB_RW_SEL); +} diff --git a/board/sophgo/common/ethernet.h b/board/sophgo/common/ethernet.h new file mode 100644 index 00000000000..7b21f1b0f66 --- /dev/null +++ b/board/sophgo/common/ethernet.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024, Kongyang Liu + */ + +#ifndef __CV1800B_ETHERNET_H +#define __CV1800B_ETHERNET_H + +void cv1800b_ephy_init(void); + +#endif 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 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 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 -#include "ethernet.h" +#include "../common/ethernet.h" int board_init(void) { diff --git a/board/sophgo/milkv_duo/ethernet.c b/board/sophgo/milkv_duo/ethernet.c deleted file mode 100644 index e997ce1037f..00000000000 --- a/board/sophgo/milkv_duo/ethernet.c +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2024, Kongyang Liu - */ - -#include -#include -#include - -#define REG_EPHY_TOP_WRAP (u32 *)0x03009800 -#define REG_EPHY_BASE (u32 *)0x03009000 - -#define REG_EPHY_CTL REG_EPHY_TOP_WRAP -#define REG_EPHY_APB_RW_SEL REG_EPHY_TOP_WRAP + 1 - -/* Page 0 register */ -#define REG_PHY_ID1 REG_EPHY_BASE + MII_PHYSID1 -#define REG_PHY_ID2 REG_EPHY_BASE + MII_PHYSID2 -#define REG_PHY_PAGE_SEL REG_EPHY_BASE + 0x1f - -/* Page 5 register */ -#define REG_PD_EN_CTL REG_EPHY_BASE + 0x10 - -/* REG_EPHY_CTL */ -#define REG_EPHY_SHUTDOWN BIT(0) -#define REG_EPHY_ANA_RST_N BIT(1) -#define REG_EPHY_DIG_RST_N BIT(2) -#define REG_EPHY_MAIN_RST_N BIT(3) - -/* REG_PD_EN_CTL */ -#define REG_EN_ETH_TXRT BIT(0) -#define REG_EN_ETH_CLK100M BIT(1) -#define REG_EN_ETH_CLK125M BIT(2) -#define REG_EN_ETH_PLL_LCKDET BIT(3) -#define REG_EN_ETH_RXADC BIT(4) -#define REG_EN_ETH_RXPGA BIT(5) -#define REG_EN_ETH_RXRT BIT(6) -#define REG_EN_ETH_TXCROSSOVER BIT(7) -#define REG_PD_ETH_PLL BIT(8) -#define REG_PD_ETH_TXDAC BIT(9) -#define REG_PD_ETH_TXDACBST BIT(10) -#define REG_PD_ETH_TXECHO BIT(11) -#define REG_PD_ETH_TXDRV_NMOS BIT(12) -#define REG_PD_ETH_TXLDO BIT(13) - -void cv1800b_ephy_init(void) -{ - u32 reg; - u32 phy_id = 1; - - /* enable direct memory access for phy register */ - writel(1, REG_EPHY_APB_RW_SEL); - - reg = readl(REG_EPHY_CTL); - reg &= ~REG_EPHY_SHUTDOWN; - reg |= REG_EPHY_ANA_RST_N | REG_EPHY_DIG_RST_N | REG_EPHY_MAIN_RST_N; - writel(reg, REG_EPHY_CTL); - - /* switch to page 5 */ - writel(5 << 8, REG_PHY_PAGE_SEL); - reg = readl(REG_PD_EN_CTL); - reg &= ~(REG_PD_ETH_TXLDO | REG_PD_ETH_TXDRV_NMOS | REG_PD_ETH_TXDAC | REG_PD_ETH_PLL); - reg |= REG_EN_ETH_TXRT | REG_EN_ETH_CLK100M | REG_EN_ETH_CLK125M - | REG_EN_ETH_PLL_LCKDET | REG_EN_ETH_RXADC | REG_EN_ETH_RXPGA | REG_EN_ETH_RXRT; - writel(reg, REG_PD_EN_CTL); - - /* switch to page 0 */ - writel(0 << 8, REG_PHY_PAGE_SEL); - /* - * As the phy_id in the cv1800b PHY register is initialized to 0, it - * is necessary to manually initialize the phy_id to an arbitrary - * value so that it could corresponds to the generic PHY driver. - */ - writel(phy_id >> 16, REG_PHY_ID1); - writel(phy_id & 0xffff, REG_PHY_ID2); - - /* switch to MDIO control */ - writel(0, REG_EPHY_APB_RW_SEL); -} diff --git a/board/sophgo/milkv_duo/ethernet.h b/board/sophgo/milkv_duo/ethernet.h deleted file mode 100644 index 7b21f1b0f66..00000000000 --- a/board/sophgo/milkv_duo/ethernet.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 2024, Kongyang Liu - */ - -#ifndef __CV1800B_ETHERNET_H -#define __CV1800B_ETHERNET_H - -void cv1800b_ephy_init(void); - -#endif -- cgit v1.3.1 From 98b59e181daa6c26d49f870fd58df8996b1cd7f1 Mon Sep 17 00:00:00 2001 From: Hiago De Franco Date: Thu, 23 Jul 2026 11:44:35 -0300 Subject: board: sophgo: add support for Milk-V Duo 256M Add U-Boot support for Milk-V Duo 256M. This board has a different SoC compared to the Milk-V Duo 64M, it uses the Sophgo SG2002 instead of the Sophgo CV1800B. Both SoCs share many common IP blocks, so this board reuses the existing cv1800b CPU support. The board shares the same 'board.c' with Milk-V Duo 64MB (CV1800B), so use the same file for now. Link: https://milkv.io/docs/duo/getting-started/duo256m Signed-off-by: Hiago De Franco Acked-by: Leo Yu-Chi Liang --- arch/riscv/Kconfig | 4 ++ arch/riscv/dts/Makefile | 1 + arch/riscv/dts/sg2002-milkv-duo256m.dts | 46 ++++++++++++++ board/sophgo/milkv_duo_256m/Kconfig | 30 +++++++++ board/sophgo/milkv_duo_256m/MAINTAINERS | 5 ++ board/sophgo/milkv_duo_256m/Makefile | 6 ++ board/sophgo/milkv_duo_256m/milkv_duo_256m.env | 8 +++ configs/milkv_duo_256m_defconfig | 42 +++++++++++++ doc/board/sophgo/index.rst | 1 + doc/board/sophgo/milkv_duo_256m.rst | 84 ++++++++++++++++++++++++++ include/configs/milkv_duo_256m.h | 12 ++++ 11 files changed, 239 insertions(+) create mode 100644 arch/riscv/dts/sg2002-milkv-duo256m.dts create mode 100644 board/sophgo/milkv_duo_256m/Kconfig create mode 100644 board/sophgo/milkv_duo_256m/MAINTAINERS create mode 100644 board/sophgo/milkv_duo_256m/Makefile create mode 100644 board/sophgo/milkv_duo_256m/milkv_duo_256m.env create mode 100644 configs/milkv_duo_256m_defconfig create mode 100644 doc/board/sophgo/milkv_duo_256m.rst create mode 100644 include/configs/milkv_duo_256m.h 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 + */ + +/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"; + }; +}; + +ðernet0 { + 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_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 +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 + +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/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= + cd + 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/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 + * + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CFG_SYS_SDRAM_BASE 0x80000000 + +#endif /* __CONFIG_H */ -- cgit v1.3.1