¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

[RFC v1 0/7] common: usb_onboard_hub: Add support for Odroid onboard USB hub reset

 

Odroid C1+/C2/C4/N2/N2-plus devices have an onboard USB hub
controlled by a reset GPIO pin. Adds changes to the onboard USB hub
driver to perform a proper reset of the USB hub.

Added conditional compilation for I2C initialization based
on CONFIG_DM_I2C for failed to compile.

Thanks
-Anand

Anand Moon (7):
usb: onboard-hub: Add support for Genesys GL852G hub
configs: odorid-c2: Enable Onboard HUB driver
usb: onboard-hub: Add support for Genesys GL853G
configs: odorid-n2: Enable Oboard HUB driver
usb: onboard-hub: Add support for VL817 USB hub
configs: odorid-c4: Enable Oboard HUB driver
usb: onboard-hub: Add conditional compilation for I2C initialization

common/usb_onboard_hub.c | 28 ++++++++++++++++++++++++++++
configs/odroid-c2_defconfig | 1 +
configs/odroid-c4_defconfig | 1 +
configs/odroid-n2_defconfig | 1 +
4 files changed, 31 insertions(+)


base-commit: 48db49b0977cc1c9c9abf82c0fb704238fcef4fd
--
2.49.0


Re: Odroid n2+ usb broken on reboot

 

On Wed May 7, 2025 at 1:03 PM UTC, Wayne Schroeder wrote:
It's hard for me to quantify if usb works in u-boot as I'm not loading
off of any usb storage devices. It certainly never lets me use the
keyboard to abort auto boot, and never has. On reboot, to reliably
You can send bytes via UART to abort boot, if you happen to have a UART
adapter around.


Re: [PATCH v2 12/22] amlogic: Include env.h to permit reading the environment

 

01/05/2025 04.04, Simon Glass via groups.io wrote:
This file reads from the environment but does not include the correct
header. Update it.
Signed-off-by: Simon Glass <sjg@...>
---
(no changes since v1)
board/amlogic/jethub-j100/jethub-j100.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/board/amlogic/jethub-j100/jethub-j100.c b/board/amlogic/jethub-j100/jethub-j100.c
index b770a1f8c53..9e87fb9f9d7 100644
--- a/board/amlogic/jethub-j100/jethub-j100.c
+++ b/board/amlogic/jethub-j100/jethub-j100.c
@@ -5,6 +5,7 @@
*/
#include <dm.h>
+#include <env.h>
#include <init.h>
#include <net.h>
#include <asm/io.h>
Reviewed-by: Viacheslav Bocharov <adeep@...>


Re: Odroid n2+ usb broken on reboot

 

Hi Wayne,

On Wed, 7 May 2025 at 17:31, Neil Armstrong via groups.io
<neil.armstrong@...> wrote:

On 05/05/2025 15:12, Wayne Schroeder wrote:
If I add the usb reset command, it works reliably at reboot, but it
does not work on a fresh power-up with that change.
OK this means there's a dangling resource, Does USB always work within
U-Boot or it breaks U-Boot and Linux in those cases ?



On Mon, May 5, 2025 at 2:07?AM <neil.armstrong@...> wrote:

I think it's a very long term issue, USB lacks a proper reset at probe on
warm reset, does USB still work from U-Boot after the reboot ?
I wanted to enable CONFIG_USB_ONBOARD_HUB on Odroid platform on u-boot
I think this should help USB hub reset, I'll check this and let you know.

Thanks
-Anand






Re: Odroid n2+ usb broken on reboot

Wayne Schroeder
 

It's hard for me to quantify if usb works in u-boot as I'm not loading
off of any usb storage devices. It certainly never lets me use the
keyboard to abort auto boot, and never has. On reboot, to reliably
get it to work, I have to do a usb reset and sleep some amount of time
before doing distro boot. I picked 10 seconds. If you would like for
me to do some scripted boot command additions before my extlinux to
gather data, I can.

Right now, what I have done is make a reboot hook in linux to touch a
file on the boot partition that my bootcommand fatrms and if it was
present, it resets usb and sleeps 10 seconds, so it's reliable to
reboot remotely like that. Let me know how else I can gather any
data.

On Wed, May 7, 2025 at 7:01?AM <neil.armstrong@...> wrote:

On 05/05/2025 15:12, Wayne Schroeder wrote:
If I add the usb reset command, it works reliably at reboot, but it
does not work on a fresh power-up with that change.
OK this means there's a dangling resource, Does USB always work within
U-Boot or it breaks U-Boot and Linux in those cases ?



On Mon, May 5, 2025 at 2:07?AM <neil.armstrong@...> wrote:

I think it's a very long term issue, USB lacks a proper reset at probe on
warm reset, does USB still work from U-Boot after the reboot ?


Re: Odroid n2+ usb broken on reboot

 

On 05/05/2025 15:12, Wayne Schroeder wrote:
If I add the usb reset command, it works reliably at reboot, but it
does not work on a fresh power-up with that change.
OK this means there's a dangling resource, Does USB always work within
U-Boot or it breaks U-Boot and Linux in those cases ?

On Mon, May 5, 2025 at 2:07?AM <neil.armstrong@...> wrote:

I think it's a very long term issue, USB lacks a proper reset at probe on
warm reset, does USB still work from U-Boot after the reboot ?


Re: Odroid n2+ usb broken on reboot

Wayne Schroeder
 

If I add the usb reset command, it works reliably at reboot, but it
does not work on a fresh power-up with that change.

On Mon, May 5, 2025 at 2:07?AM <neil.armstrong@...> wrote:

I think it's a very long term issue, USB lacks a proper reset at probe on
warm reset, does USB still work from U-Boot after the reboot ?


Re: Odroid n2+ usb broken on reboot

Wayne Schroeder
 

It works at reboot with USB reset, but fails at a fresh power on now. I
had to remove it unfortunately.

On Mon, May 5, 2025, 2:07?AM <neil.armstrong@...> wrote:

Hi,

+CC [email protected]
+CC linux-amlogic@...

On 05/05/2025 00:34, Wayne Schroeder wrote:
Hello. I am not sure if this is a bug, or even related to u-boot, but I
am
reporting it here because it was easiest to resolve via a u-boot change.

I am using u-boot-2025.04 (source) with a mainline linux from Arch Linux
Arm.
Linux alarm 6.14.4-1-aarch64-ARCH #1 SMP PREEMPT_DYNAMIC Sat Apr 26
13:02:01 MDT 2025 aarch64 GNU/Linux

On my odroid-n2+, the USB ports work on the first boot after power. If I
run shutdown -r now, or hit ctl-alt-del and otherwise reboot the system,
the usb ports do not function at the next or subsequent boot up.
I think it's a very long term issue, USB lacks a proper reset at probe on
warm reset, does USB still work from U-Boot after the reboot ?


My apologies if this is not applicable to u-boot because it is a linux
issue--I am not sure what the source of the issue is, but adjusting the
u-boot .config after make odroid-n2_defconfig resolved the issue
entirely.

I am booting via extlinux/extlinux.conf and have adjusted my
CONFIG_BOOTCOMMAND before build to execute a usb reset prior to the
existing run distro_bootcmd.

CONFIG_BOOTCOMMAND="usb reset; run distro_bootcmd"
I'm pretty sure there's driver callbacks we should implement to do the
same here, I need to check.


This has allowed me to reboot the system and successfully have access to
the USB devices such as my keyboard, mouse, and root file system on USB3
SSD.

Thanks!

Wayne


Re: Odroid n2+ usb broken on reboot

 

Hi,

+CC [email protected]
+CC linux-amlogic@...

On 05/05/2025 00:34, Wayne Schroeder wrote:
Hello. I am not sure if this is a bug, or even related to u-boot, but I am
reporting it here because it was easiest to resolve via a u-boot change.
I am using u-boot-2025.04 (source) with a mainline linux from Arch Linux
Arm.
Linux alarm 6.14.4-1-aarch64-ARCH #1 SMP PREEMPT_DYNAMIC Sat Apr 26
13:02:01 MDT 2025 aarch64 GNU/Linux
On my odroid-n2+, the USB ports work on the first boot after power. If I
run shutdown -r now, or hit ctl-alt-del and otherwise reboot the system,
the usb ports do not function at the next or subsequent boot up.
I think it's a very long term issue, USB lacks a proper reset at probe on
warm reset, does USB still work from U-Boot after the reboot ?

My apologies if this is not applicable to u-boot because it is a linux
issue--I am not sure what the source of the issue is, but adjusting the
u-boot .config after make odroid-n2_defconfig resolved the issue entirely.
I am booting via extlinux/extlinux.conf and have adjusted my
CONFIG_BOOTCOMMAND before build to execute a usb reset prior to the
existing run distro_bootcmd.
CONFIG_BOOTCOMMAND="usb reset; run distro_bootcmd"
I'm pretty sure there's driver callbacks we should implement to do the
same here, I need to check.

This has allowed me to reboot the system and successfully have access to
the USB devices such as my keyboard, mouse, and root file system on USB3
SSD.
Thanks!
Wayne


[PATCH] net: mdio: mux-meson-gxl: set reversed bit when using internal phy

 

This bit is necessary to receive packets from the internal PHY.
Without this bit set, no activity occurs on the interface.

Normally u-boot sets this bit, but if u-boot is compiled without
net support, the interface will be up but without any activity.

The vendor SDK sets this bit along with the PHY_ID bits.

Ported from the Linux change at [1] from Da Xu merged in
commit [2].

[1]
[2] b23285e93bef ("net: mdio: mux-meson-gxl: set reversed bit when using internal phy")

Suggested-by: Da Xue <da@...>
Signed-off-by: Neil Armstrong <neil.armstrong@...>
---
drivers/net/mdio_mux_meson_gxl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio_mux_meson_gxl.c b/drivers/net/mdio_mux_meson_gxl.c
index 8ef3ae598b77fabf7b992900141d309708428b13..31898ed437e4857dd7027d311ab496be3e448d16 100644
--- a/drivers/net/mdio_mux_meson_gxl.c
+++ b/drivers/net/mdio_mux_meson_gxl.c
@@ -19,6 +19,7 @@
#define REG2_LEDACT GENMASK(23, 22)
#define REG2_LEDLINK GENMASK(25, 24)
#define REG2_DIV4SEL BIT(27)
+#define REG2_REVERSED BIT(28)
#define REG2_ADCBYPASS BIT(30)
#define REG2_CLKINSEL BIT(31)
#define ETH_REG3 0x4
@@ -66,7 +67,7 @@ static int meson_gxl_enable_internal_mdio(struct mdio_mux_meson_gxl_priv *priv)
* The only constraint is that it must match the one in
* drivers/net/phy/meson-gxl.c to properly match the PHY.
*/
- writel(FIELD_PREP(REG2_PHYID, EPHY_GXL_ID),
+ writel(REG2_REVERSED | FIELD_PREP(REG2_PHYID, EPHY_GXL_ID),
priv->regs + ETH_REG2);

/* Enable the internal phy */

---
base-commit: 98a898e58499c78245e4fe36ee404b1b1208e32b
change-id: 20250502-u-boot-topic-mdio-mux-gxl-bit28-a6d03bf8e383

Best regards,
--
Neil Armstrong <neil.armstrong@...>


[PATCH v2 00/22] Deal with exfat versus byteorder

Simon Glass
 

Since exfat has its own byteorder functions we need to be careful about
including the normal U-Boot byteorder headers in code included by exfat.

One chain for include/linux/byteorder/little_endian.h is like this:

In file included from arch/sandbox/include/asm/byteorder.h:19,
from arch/sandbox/include/asm/byteorder.h:19,
from include/compiler.h:132,
from include/env.h:12,
from include/command.h:13,
from include/net-common.h:7,
from include/net.h:6,
from include/efi.h:23,
from include/blk.h:12,
from include/part.h:9,
from include/fs_internal.h:11,
from fs/exfat/io.c:52:

This series tidies things up so that efi.h can include net.h as
required.

Changes in v2:
- Add patches for other files exposed by this change

Simon Glass (22):
net: Use a forward declaration for cmd_tbl in net-common.h
congatec: Include env.h to permit reading the environment
dhelectronics: Include env.h to permit reading the environment
imx8ulp_evk: Include env.h to permit reading the environment
venice: Include env.h to permit reading the environment
phytec: Include env.h to permit reading the environment
ronetix: Include env.h to permit reading the environment
toradex: Include env.h to permit reading the environment
advantech: Include env.h in imx8qm_dmsse20_a1
tegra: Include env.h to permit reading the environment
synology: Include env.h to permit reading the environment
amlogic: Include env.h to permit reading the environment
freescale: Include env.h to permit reading the environment
google: Include env.h to permit reading the environment
liebherr: Include env.h to permit reading the environment
technexion: Include env.h to permit reading the environment
elf: Only use network environment-variables if net enabled
net: Include byteorder in net6.h
net: Include string.h in net-legacy.h
net: Include env.h in pcap.c
net: dc2114x: Include env.h to permit reading the environment
net: Move env_get_ip() out of the header file

arch/arm/mach-tegra/dt-setup.c | 1 +
board/Synology/ds414/ds414.c | 1 +
.../imx8qm_dmsse20_a1/imx8qm_dmsse20_a1.c | 1 +
board/amlogic/jethub-j100/jethub-j100.c | 1 +
board/congatec/cgtqmx8/cgtqmx8.c | 3 +-
board/dhelectronics/common/dh_common.c | 1 +
board/freescale/imx8ulp_evk/imx8ulp_evk.c | 1 +
board/freescale/mx7dsabresd/mx7dsabresd.c | 1 +
board/gateworks/venice/venice.c | 1 +
board/google/chameleonv3/board.c | 2 +
board/liebherr/xea/xea.c | 1 +
.../common/phytec_som_detection_blocks.c | 1 +
board/ronetix/imx8mq-cm/imx8mq_cm.c | 1 +
board/technexion/pico-imx7d/pico-imx7d.c | 1 +
board/toradex/colibri_imx7/colibri_imx7.c | 1 +
board/toradex/verdin-imx8mm/verdin-imx8mm.c | 2 +-
cmd/elf.c | 41 ++++++++++---------
drivers/net/dc2114x.c | 1 +
include/net-common.h | 9 ++--
include/net-legacy.h | 1 +
include/net6.h | 1 +
net/net-common.c | 6 +++
net/pcap.c | 1 +
23 files changed, 53 insertions(+), 27 deletions(-)

--
2.43.0

base-commit: b5d6220dd2f4612912989f3c2b5a710f2248cb36
branch: fix-net2


[PATCH v2 12/22] amlogic: Include env.h to permit reading the environment

Simon Glass
 

This file reads from the environment but does not include the correct
header. Update it.

Signed-off-by: Simon Glass <sjg@...>
---

(no changes since v1)

board/amlogic/jethub-j100/jethub-j100.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/board/amlogic/jethub-j100/jethub-j100.c b/board/amlogic/jethub-j100/jethub-j100.c
index b770a1f8c53..9e87fb9f9d7 100644
--- a/board/amlogic/jethub-j100/jethub-j100.c
+++ b/board/amlogic/jethub-j100/jethub-j100.c
@@ -5,6 +5,7 @@
*/

#include <dm.h>
+#include <env.h>
#include <init.h>
#include <net.h>
#include <asm/io.h>
--
2.43.0


[PATCH 2/2] ARM: mach-meson: use livetree by default

 

Finally enable OF_LIVE by default on the Amlogic support,
this add some cost to build the live tree, but makes DT
parsing from driver much faster.

Signed-off-by: Neil Armstrong <neil.armstrong@...>
---
arch/arm/mach-meson/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 7570f48e25fe477ce4dfb1eb608ed07b3a83d27f..10cef2ad6623180e2ff1ed2802543f3ba0714bd3 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -12,6 +12,7 @@ config MESON64_COMMON
select MMC_PWRSEQ
select BOARD_LATE_INIT
select MESON_SM
+ imply OF_LIVE
imply CMD_DM

config MESON_GX

--
2.34.1


[PATCH 1/2] pinctrl: meson: convert to livetree

 

From: Beniamino Galvani <b.galvani@...>

Update the Meson pinctrl/gpio driver to support a live device tree.

Signed-off-by: Beniamino Galvani <b.galvani@...>
Link:
Signed-off-by: Neil Armstrong <neil.armstrong@...>
---
drivers/pinctrl/meson/pinctrl-meson.c | 73 +++++++++++++++++++----------------
1 file changed, 39 insertions(+), 34 deletions(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index babf1bccc9697596522dc93d8906ff0454cfebf5..21409063ee89cd2f8aa3d511f3fed6b64f800e51 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -10,6 +10,8 @@
#include <dm/device-internal.h>
#include <dm/device_compat.h>
#include <dm/lists.h>
+#include <dm/of_addr.h>
+#include <linux/ioport.h>
#include <dm/pinctrl.h>
#include <fdt_support.h>
#include <linux/bitops.h>
@@ -319,88 +321,91 @@ int meson_gpio_probe(struct udevice *dev)
return 0;
}

-static fdt_addr_t parse_address(int offset, const char *name, int na, int ns)
+static phys_addr_t parse_address(struct udevice *dev, ofnode node,
+ const char *name)
{
- int index, len = 0;
- const fdt32_t *reg;
+ struct resource r;
+ fdt_size_t sz;
+ int na, ns, index;

- index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name);
+ index = ofnode_stringlist_search(node, "reg-names", name);
if (index < 0)
return FDT_ADDR_T_NONE;

- reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
- if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns))))
+ if (of_live_active()) {
+ if (of_address_to_resource(ofnode_to_np(node), index, &r))
+ return FDT_ADDR_T_NONE;
+ else
+ return r.start;
+ }
+
+ na = dev_read_addr_cells(dev->parent);
+ if (na < 1) {
+ debug("bad #address-cells\n");
return FDT_ADDR_T_NONE;
+ }

- reg += index * (na + ns);
+ ns = dev_read_size_cells(dev->parent);
+ if (ns < 1) {
+ debug("bad #size-cells\n");
+ return FDT_ADDR_T_NONE;
+ }

- return fdt_translate_address((void *)gd->fdt_blob, offset, reg);
+ return fdtdec_get_addr_size_fixed(gd->fdt_blob, ofnode_to_offset(node),
+ "reg", index, na, ns, &sz, true);
}

int meson_pinctrl_probe(struct udevice *dev)
{
struct meson_pinctrl *priv = dev_get_priv(dev);
+ ofnode node, gpio = ofnode_null();
struct uclass_driver *drv;
struct udevice *gpio_dev;
- fdt_addr_t addr;
- int node, gpio = -1, len;
- int na, ns;
+ phys_addr_t addr;
char *name;
+ int len;

- /* FIXME: Should use livetree */
- na = fdt_address_cells(gd->fdt_blob, dev_of_offset(dev->parent));
- if (na < 1) {
- debug("bad #address-cells\n");
- return -EINVAL;
- }
-
- ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
- if (ns < 1) {
- debug("bad #size-cells\n");
- return -EINVAL;
- }
-
- fdt_for_each_subnode(node, gd->fdt_blob, dev_of_offset(dev)) {
- if (fdt_getprop(gd->fdt_blob, node, "gpio-controller", &len)) {
+ dev_for_each_subnode(node, dev) {
+ if (ofnode_read_prop(node, "gpio-controller", &len)) {
gpio = node;
break;
}
}

- if (!gpio) {
+ if (!ofnode_valid(gpio)) {
debug("gpio node not found\n");
return -EINVAL;
}

- addr = parse_address(gpio, "mux", na, ns);
+ addr = parse_address(dev, gpio, "mux");
if (addr == FDT_ADDR_T_NONE) {
debug("mux address not found\n");
return -EINVAL;
}
priv->reg_mux = (void __iomem *)addr;

- addr = parse_address(gpio, "gpio", na, ns);
+ addr = parse_address(dev, gpio, "gpio");
if (addr == FDT_ADDR_T_NONE) {
debug("gpio address not found\n");
return -EINVAL;
}
priv->reg_gpio = (void __iomem *)addr;

- addr = parse_address(gpio, "pull", na, ns);
+ addr = parse_address(dev, gpio, "pull");
/* Use gpio region if pull one is not present */
if (addr == FDT_ADDR_T_NONE)
priv->reg_pull = priv->reg_gpio;
else
priv->reg_pull = (void __iomem *)addr;

- addr = parse_address(gpio, "pull-enable", na, ns);
+ addr = parse_address(dev, gpio, "pull-enable");
/* Use pull region if pull-enable one is not present */
if (addr == FDT_ADDR_T_NONE)
priv->reg_pullen = priv->reg_pull;
else
priv->reg_pullen = (void __iomem *)addr;

- addr = parse_address(gpio, "ds", na, ns);
+ addr = parse_address(dev, gpio, "ds");
/* Drive strength region is optional */
if (addr == FDT_ADDR_T_NONE)
priv->reg_ds = NULL;
@@ -420,8 +425,8 @@ int meson_pinctrl_probe(struct udevice *dev)
sprintf(name, "meson-gpio");

/* Create child device UCLASS_GPIO and bind it */
- device_bind(dev, priv->data->gpio_driver, name, NULL,
- offset_to_ofnode(gpio), &gpio_dev);
+ device_bind_with_driver_data(dev, priv->data->gpio_driver, name, 0,
+ gpio, &gpio_dev);

return 0;
}

--
2.34.1


[PATCH 0/2] ARM: meson: finally switch to livetree

 

Never late than never, finally try to land Beniamino's
"pinctrl: meson: convert to livetree" from 2017 to finally
be a modern platform with OF_LIVE !

Signed-off-by: Neil Armstrong <neil.armstrong@...>
---
Beniamino Galvani (1):
pinctrl: meson: convert to livetree

Neil Armstrong (1):
ARM: mach-meson: use livetree by default

arch/arm/mach-meson/Kconfig | 1 +
drivers/pinctrl/meson/pinctrl-meson.c | 73 +++++++++++++++++++----------------
2 files changed, 40 insertions(+), 34 deletions(-)
---
base-commit: f892a7f397a66d8d09f418d1e0e06dfb48bac27d
change-id: 20250411-u-boot-meson-livetree-8fd1b0a18066

Best regards,
--
Neil Armstrong <neil.armstrong@...>


[PATCH 2/3] designware: Use the remove() method with related drivers

Simon Glass
 

Several drivers make use of the designware Ethernet driver but do not
implement the remove() method. Add this so that DMA is stopped when the
OS is booted to avoid memory corruption, etc.

Signed-off-by: Simon Glass <sjg@...>
Reported-by: Christian Kohlsch¨¹tter <christian@...>
---

drivers/net/designware.c | 2 +-
drivers/net/designware.h | 12 ++++++++++++
drivers/net/dwmac_meson8b.c | 6 ++++++
drivers/net/dwmac_s700.c | 6 ++++++
drivers/net/dwmac_socfpga.c | 6 ++++++
5 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index eebf14bd51a..d4d31925fca 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -805,7 +805,7 @@ clk_err:
return err;
}

-static int designware_eth_remove(struct udevice *dev)
+int designware_eth_remove(struct udevice *dev)
{
struct dw_eth_dev *priv = dev_get_priv(dev);

diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index e47101ccaf6..8c9d0190e03 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -247,6 +247,18 @@ struct dw_eth_dev {

int designware_eth_of_to_plat(struct udevice *dev);
int designware_eth_probe(struct udevice *dev);
+
+/**
+ * designware_eth_remove() - Remove the device
+ *
+ * Disables DMA and marks the device as remove. This must be called before
+ * booting an OS, to ensure that DMA is inactive.
+ *
+ * @dev: Device to remove
+ * Return 0 if OK, -ve on error
+ */
+int designware_eth_remove(struct udevice *dev);
+
extern const struct eth_ops designware_eth_ops;

struct dw_eth_pdata {
diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c
index fde4aabbace..b2152f8da9b 100644
--- a/drivers/net/dwmac_meson8b.c
+++ b/drivers/net/dwmac_meson8b.c
@@ -145,6 +145,11 @@ static int dwmac_meson8b_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_meson8b_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static const struct udevice_id dwmac_meson8b_ids[] = {
{ .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx },
{ .compatible = "amlogic,meson-g12a-dwmac", .data = (ulong)dwmac_setup_axg },
@@ -158,6 +163,7 @@ U_BOOT_DRIVER(dwmac_meson8b) = {
.of_match = dwmac_meson8b_ids,
.of_to_plat = dwmac_meson8b_of_to_plat,
.probe = dwmac_meson8b_probe,
+ .remove = dwmac_meson8b_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_meson8b_plat),
diff --git a/drivers/net/dwmac_s700.c b/drivers/net/dwmac_s700.c
index 969d247b4f3..cfb37c3aa71 100644
--- a/drivers/net/dwmac_s700.c
+++ b/drivers/net/dwmac_s700.c
@@ -44,6 +44,11 @@ static int dwmac_s700_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_s700_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static int dwmac_s700_of_to_plat(struct udevice *dev)
{
return designware_eth_of_to_plat(dev);
@@ -60,6 +65,7 @@ U_BOOT_DRIVER(dwmac_s700) = {
.of_match = dwmac_s700_ids,
.of_to_plat = dwmac_s700_of_to_plat,
.probe = dwmac_s700_probe,
+ .remove = dwmac_s700_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct eth_pdata),
diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c
index a9e2d8c0972..8e7a9975d28 100644
--- a/drivers/net/dwmac_socfpga.c
+++ b/drivers/net/dwmac_socfpga.c
@@ -130,6 +130,11 @@ static int dwmac_socfpga_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_socfpga_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static const struct udevice_id dwmac_socfpga_ids[] = {
{ .compatible = "altr,socfpga-stmmac" },
{ }
@@ -141,6 +146,7 @@ U_BOOT_DRIVER(dwmac_socfpga) = {
.of_match = dwmac_socfpga_ids,
.of_to_plat = dwmac_socfpga_of_to_plat,
.probe = dwmac_socfpga_probe,
+ .remove = dwmac_socfpga_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_socfpga_plat),
--
2.43.0

base-commit: bcfa94be955ef263d37918ef4b8f898ee8964c61
branch: eth


[PATCH v2 2/4] net: designware: Mark drivers as having active DMA

Simon Glass
 

Network devices which use this driver have DMA running while receiving
packages. Add the required flag to driver model so that they will be
removed before starting the OS.

Signed-off-by: Simon Glass <sjg@...>
---

Changes in v2:
- Add a new patch to mark drivers as having active DMA

drivers/net/designware.c | 2 +-
drivers/net/dwmac_meson8b.c | 2 +-
drivers/net/dwmac_s700.c | 2 +-
drivers/net/dwmac_socfpga.c | 2 +-
drivers/net/gmac_rockchip.c | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 5385849ea6b..9b2b0a5d602 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -885,7 +885,7 @@ U_BOOT_DRIVER(eth_designware) = {
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dw_eth_pdata),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};

static struct pci_device_id supported[] = {
diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c
index bf94e50842d..95a99a98e99 100644
--- a/drivers/net/dwmac_meson8b.c
+++ b/drivers/net/dwmac_meson8b.c
@@ -162,5 +162,5 @@ U_BOOT_DRIVER(dwmac_meson8b) = {
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_meson8b_plat),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};
diff --git a/drivers/net/dwmac_s700.c b/drivers/net/dwmac_s700.c
index e78193f3376..21df8e3ce81 100644
--- a/drivers/net/dwmac_s700.c
+++ b/drivers/net/dwmac_s700.c
@@ -64,5 +64,5 @@ U_BOOT_DRIVER(dwmac_s700) = {
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct eth_pdata),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};
diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c
index dda33f90d65..9f262aaee60 100644
--- a/drivers/net/dwmac_socfpga.c
+++ b/drivers/net/dwmac_socfpga.c
@@ -145,5 +145,5 @@ U_BOOT_DRIVER(dwmac_socfpga) = {
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_socfpga_plat),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};
diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c
index 5c542d62bd8..52be3a5687f 100644
--- a/drivers/net/gmac_rockchip.c
+++ b/drivers/net/gmac_rockchip.c
@@ -760,5 +760,5 @@ U_BOOT_DRIVER(eth_gmac_rockchip) = {
.ops = &gmac_rockchip_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct gmac_rockchip_plat),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+ .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};
--
2.43.0


Re: [PATCH 2/3] designware: Use the remove() method with related drivers

Jonas Karlman
 

Hi Simon,

On 2025-04-06 23:10, Simon Glass wrote:
Hi Jonas,

On Sun, 6 Apr 2025 at 21:02, Jonas Karlman <jonas@...> wrote:

Hi Simon,

On 2025-04-06 00:12, Simon Glass wrote:
Several drivers make use of the designware Ethernet driver but do not
implement the remove() method. Add this so that DMA is stopped when the
OS is booted to avoid memory corruption, etc.
The designware Ethernet driver core should not need the remove() ops as
the eth_ops.stop() ops already should stop DMA. And the eth-uclass
pre_remove() ops already call the eth_ops.stop() ops.

All these drivers seem to use designware_eth_ops and thus have correct
stop() ops configured and should really not need the remove() ops.
That's interesting. I wrote that code about 9 years ago so perhaps can
be forgiven for forgetting.

Very few drivers set the DM_FLAG_ACTIVE_DMA flag, certainly not the
designware ones. So how would they be removed?
Ahh, I see, remove() is only called for devices with ACTIVE_DMA or
OS_PREPARE. So I guess that was probably the issue all along?

There is some confusion that dm_remove_devices_active() does not remove
device_active()=true devices and instead only remove ACTIVE_DMA and/or
OS_PREPARE flagged devices.


Side note, this also misses the gmac rockchip driver that uses its own
eth_ops instead of designware_eth_ops, however it also use same stop()
ops as all these drivers.
Hmm yes I saw that but then apparently forgot to include it.

I can perhaps redo this patch to add the DMA flag.
Maybe eth_post_probe() or similar should add the OS_PREPARE or
ACTIVE_DMA flag for all eth-uclass, to ensure remove() and thus stop()
gets called when dm_remove_devices_active() is called.

There is probably no need to add all these remove() ops, as they would
still not have been called by dm_remove_devices_active().

Regards,
Jonas




Signed-off-by: Simon Glass <sjg@...>
Reported-by: Christian Kohlsch¨¹tter <christian@...>
---

drivers/net/designware.c | 2 +-
drivers/net/designware.h | 12 ++++++++++++
drivers/net/dwmac_meson8b.c | 6 ++++++
drivers/net/dwmac_s700.c | 6 ++++++
drivers/net/dwmac_socfpga.c | 6 ++++++
5 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index eebf14bd51a..d4d31925fca 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -805,7 +805,7 @@ clk_err:
return err;
}

-static int designware_eth_remove(struct udevice *dev)
+int designware_eth_remove(struct udevice *dev)
{
struct dw_eth_dev *priv = dev_get_priv(dev);

diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index e47101ccaf6..8c9d0190e03 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -247,6 +247,18 @@ struct dw_eth_dev {

int designware_eth_of_to_plat(struct udevice *dev);
int designware_eth_probe(struct udevice *dev);
+
+/**
+ * designware_eth_remove() - Remove the device
+ *
+ * Disables DMA and marks the device as remove. This must be called before
+ * booting an OS, to ensure that DMA is inactive.
+ *
+ * @dev: Device to remove
+ * Return 0 if OK, -ve on error
+ */
+int designware_eth_remove(struct udevice *dev);
+
extern const struct eth_ops designware_eth_ops;

struct dw_eth_pdata {
diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c
index fde4aabbace..b2152f8da9b 100644
--- a/drivers/net/dwmac_meson8b.c
+++ b/drivers/net/dwmac_meson8b.c
@@ -145,6 +145,11 @@ static int dwmac_meson8b_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_meson8b_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static const struct udevice_id dwmac_meson8b_ids[] = {
{ .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx },
{ .compatible = "amlogic,meson-g12a-dwmac", .data = (ulong)dwmac_setup_axg },
@@ -158,6 +163,7 @@ U_BOOT_DRIVER(dwmac_meson8b) = {
.of_match = dwmac_meson8b_ids,
.of_to_plat = dwmac_meson8b_of_to_plat,
.probe = dwmac_meson8b_probe,
+ .remove = dwmac_meson8b_remove,
There is no reason to add the dwmac_meson8b_remove function above, you
could just use designware_eth_remove directly here.

Same for remaining drivers below.
Yes, I wasn't sure which way to go on that. I'll remove them.


Regards,
Jonas

.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_meson8b_plat),
diff --git a/drivers/net/dwmac_s700.c b/drivers/net/dwmac_s700.c
index 969d247b4f3..cfb37c3aa71 100644
--- a/drivers/net/dwmac_s700.c
+++ b/drivers/net/dwmac_s700.c
@@ -44,6 +44,11 @@ static int dwmac_s700_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_s700_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static int dwmac_s700_of_to_plat(struct udevice *dev)
{
return designware_eth_of_to_plat(dev);
@@ -60,6 +65,7 @@ U_BOOT_DRIVER(dwmac_s700) = {
.of_match = dwmac_s700_ids,
.of_to_plat = dwmac_s700_of_to_plat,
.probe = dwmac_s700_probe,
+ .remove = dwmac_s700_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct eth_pdata),
diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c
index a9e2d8c0972..8e7a9975d28 100644
--- a/drivers/net/dwmac_socfpga.c
+++ b/drivers/net/dwmac_socfpga.c
@@ -130,6 +130,11 @@ static int dwmac_socfpga_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_socfpga_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static const struct udevice_id dwmac_socfpga_ids[] = {
{ .compatible = "altr,socfpga-stmmac" },
{ }
@@ -141,6 +146,7 @@ U_BOOT_DRIVER(dwmac_socfpga) = {
.of_match = dwmac_socfpga_ids,
.of_to_plat = dwmac_socfpga_of_to_plat,
.probe = dwmac_socfpga_probe,
+ .remove = dwmac_socfpga_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_socfpga_plat),
Regards,
Simon


Re: [PATCH 2/3] designware: Use the remove() method with related drivers

Jonas Karlman
 

Hi Simon,

On 2025-04-06 00:12, Simon Glass wrote:
Several drivers make use of the designware Ethernet driver but do not
implement the remove() method. Add this so that DMA is stopped when the
OS is booted to avoid memory corruption, etc.
The designware Ethernet driver core should not need the remove() ops as
the eth_ops.stop() ops already should stop DMA. And the eth-uclass
pre_remove() ops already call the eth_ops.stop() ops.

All these drivers seem to use designware_eth_ops and thus have correct
stop() ops configured and should really not need the remove() ops.

Side note, this also misses the gmac rockchip driver that uses its own
eth_ops instead of designware_eth_ops, however it also use same stop()
ops as all these drivers.


Signed-off-by: Simon Glass <sjg@...>
Reported-by: Christian Kohlsch¨¹tter <christian@...>
---

drivers/net/designware.c | 2 +-
drivers/net/designware.h | 12 ++++++++++++
drivers/net/dwmac_meson8b.c | 6 ++++++
drivers/net/dwmac_s700.c | 6 ++++++
drivers/net/dwmac_socfpga.c | 6 ++++++
5 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index eebf14bd51a..d4d31925fca 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -805,7 +805,7 @@ clk_err:
return err;
}

-static int designware_eth_remove(struct udevice *dev)
+int designware_eth_remove(struct udevice *dev)
{
struct dw_eth_dev *priv = dev_get_priv(dev);

diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index e47101ccaf6..8c9d0190e03 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -247,6 +247,18 @@ struct dw_eth_dev {

int designware_eth_of_to_plat(struct udevice *dev);
int designware_eth_probe(struct udevice *dev);
+
+/**
+ * designware_eth_remove() - Remove the device
+ *
+ * Disables DMA and marks the device as remove. This must be called before
+ * booting an OS, to ensure that DMA is inactive.
+ *
+ * @dev: Device to remove
+ * Return 0 if OK, -ve on error
+ */
+int designware_eth_remove(struct udevice *dev);
+
extern const struct eth_ops designware_eth_ops;

struct dw_eth_pdata {
diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c
index fde4aabbace..b2152f8da9b 100644
--- a/drivers/net/dwmac_meson8b.c
+++ b/drivers/net/dwmac_meson8b.c
@@ -145,6 +145,11 @@ static int dwmac_meson8b_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_meson8b_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static const struct udevice_id dwmac_meson8b_ids[] = {
{ .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx },
{ .compatible = "amlogic,meson-g12a-dwmac", .data = (ulong)dwmac_setup_axg },
@@ -158,6 +163,7 @@ U_BOOT_DRIVER(dwmac_meson8b) = {
.of_match = dwmac_meson8b_ids,
.of_to_plat = dwmac_meson8b_of_to_plat,
.probe = dwmac_meson8b_probe,
+ .remove = dwmac_meson8b_remove,
There is no reason to add the dwmac_meson8b_remove function above, you
could just use designware_eth_remove directly here.

Same for remaining drivers below.

Regards,
Jonas

.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_meson8b_plat),
diff --git a/drivers/net/dwmac_s700.c b/drivers/net/dwmac_s700.c
index 969d247b4f3..cfb37c3aa71 100644
--- a/drivers/net/dwmac_s700.c
+++ b/drivers/net/dwmac_s700.c
@@ -44,6 +44,11 @@ static int dwmac_s700_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_s700_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static int dwmac_s700_of_to_plat(struct udevice *dev)
{
return designware_eth_of_to_plat(dev);
@@ -60,6 +65,7 @@ U_BOOT_DRIVER(dwmac_s700) = {
.of_match = dwmac_s700_ids,
.of_to_plat = dwmac_s700_of_to_plat,
.probe = dwmac_s700_probe,
+ .remove = dwmac_s700_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct eth_pdata),
diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c
index a9e2d8c0972..8e7a9975d28 100644
--- a/drivers/net/dwmac_socfpga.c
+++ b/drivers/net/dwmac_socfpga.c
@@ -130,6 +130,11 @@ static int dwmac_socfpga_probe(struct udevice *dev)
return designware_eth_probe(dev);
}

+static int dwmac_socfpga_remove(struct udevice *dev)
+{
+ return designware_eth_remove(dev);
+}
+
static const struct udevice_id dwmac_socfpga_ids[] = {
{ .compatible = "altr,socfpga-stmmac" },
{ }
@@ -141,6 +146,7 @@ U_BOOT_DRIVER(dwmac_socfpga) = {
.of_match = dwmac_socfpga_ids,
.of_to_plat = dwmac_socfpga_of_to_plat,
.probe = dwmac_socfpga_probe,
+ .remove = dwmac_socfpga_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_socfpga_plat),


Re: [PATCH 2/3] designware: Use the remove() method with related drivers

Simon Glass
 

Hi Jonas,

On Mon, 7 Apr 2025 at 09:36, Jonas Karlman <jonas@...> wrote:

Hi Simon,

On 2025-04-06 23:10, Simon Glass wrote:
Hi Jonas,

On Sun, 6 Apr 2025 at 21:02, Jonas Karlman <jonas@...> wrote:

Hi Simon,

On 2025-04-06 00:12, Simon Glass wrote:
Several drivers make use of the designware Ethernet driver but do not
implement the remove() method. Add this so that DMA is stopped when the
OS is booted to avoid memory corruption, etc.
The designware Ethernet driver core should not need the remove() ops as
the eth_ops.stop() ops already should stop DMA. And the eth-uclass
pre_remove() ops already call the eth_ops.stop() ops.

All these drivers seem to use designware_eth_ops and thus have correct
stop() ops configured and should really not need the remove() ops.
That's interesting. I wrote that code about 9 years ago so perhaps can
be forgiven for forgetting.

Very few drivers set the DM_FLAG_ACTIVE_DMA flag, certainly not the
designware ones. So how would they be removed?
Ahh, I see, remove() is only called for devices with ACTIVE_DMA or
OS_PREPARE. So I guess that was probably the issue all along?
I suppose so, yes.


There is some confusion that dm_remove_devices_active() does not remove
device_active()=true devices and instead only remove ACTIVE_DMA and/or
OS_PREPARE flagged devices.


Side note, this also misses the gmac rockchip driver that uses its own
eth_ops instead of designware_eth_ops, however it also use same stop()
ops as all these drivers.
Hmm yes I saw that but then apparently forgot to include it.

I can perhaps redo this patch to add the DMA flag.
Maybe eth_post_probe() or similar should add the OS_PREPARE or
ACTIVE_DMA flag for all eth-uclass, to ensure remove() and thus stop()
gets called when dm_remove_devices_active() is called.
But not all network drivers use DMA. It should really be set by the driver.


There is probably no need to add all these remove() ops, as they would
still not have been called by dm_remove_devices_active().
Well, since we can rely on the eth uclass, that is correct, but I
still think it is better to add it, as an example to other drivers.

Regards,
Simon