From 024c3e86eaa39059f19a3196a4d44a1a30f3cd3c Mon Sep 17 00:00:00 2001 From: Mathew McBride Date: Fri, 1 May 2026 11:36:03 +1000 Subject: board: ten64: add fdt fixup to hide usb hub topology The USB Hub (microchip,usb5744) can enter a dis-/reconnect loop if a driver tries to re-initialise the hub over I2C. On the Ten64 board, this process only needs to be run once per system reset cycle, which is carried out by U-Boot. As there are distributions shipping with the affected driver by default, the best solution is to remove the USB hub topology information from the FDT passed to the operating system, so the OS won't attempt to re-initialise the USB hub under any circumstance. Signed-off-by: Mathew McBride Signed-off-by: Peng Fan --- board/traverse/ten64/ten64.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/board/traverse/ten64/ten64.c b/board/traverse/ten64/ten64.c index d41bd2e9dee..c5fbf4b4a04 100644 --- a/board/traverse/ten64/ten64.c +++ b/board/traverse/ten64/ten64.c @@ -186,6 +186,58 @@ void fdt_fixup_board_enet(void *fdt) fdt_status_fail(fdt, offset); } +/* The onboard USB hub driver (microchip,usb5744) + * can cause a disconnect-reconnect loop if the operating system + * attempts to re-initialise the hub after U-Boot has already done it. + * (This process only needs to be done once per system RESET cycle) + * + * To avoid this condition, make the hub topology invisible + * to the operating system. + * It is also required to remove the hub on boards + * without it (RevD). + * + * The USB hub fixup may fail for legitimate reasons: + * 1. FDT has already been fixed. For example, the control + * FDT previously modified by board_fix_fdt is + * re-used for bootflow. + * 2. The FDT blob is based on an older version + * without the hub topology, such as older OpenWrt + * FIT images with their own device tree. + */ +int fdt_fixup_usb_hub(void *fdt) +{ + int usb1_hub2744_offset, usb1_hub5744_offset; + int i2c_usb5744_offset; + int err; + + usb1_hub2744_offset = fdt_path_offset(fdt, "/soc/usb@3110000/hub@1"); + + if (usb1_hub2744_offset < 0) + return usb1_hub2744_offset; + + err = fdt_del_node(fdt, usb1_hub2744_offset); + if (err) + return err; + + usb1_hub5744_offset = fdt_path_offset(fdt, "/soc/usb@3110000/hub@2"); + if (usb1_hub5744_offset < 0) + return usb1_hub5744_offset; + + err = fdt_del_node(fdt, usb1_hub5744_offset); + if (err) + return err; + + i2c_usb5744_offset = fdt_path_offset(fdt, "/soc/i2c@2000000/usb-hub@2d"); + if (i2c_usb5744_offset < 0) + return i2c_usb5744_offset; + + err = fdt_setprop_string(fdt, i2c_usb5744_offset, "status", "disabled"); + if (err) + return err; + + return 0; +} + /* Called after SoC board_late_init in fsl-layerscape/soc.c */ int fsl_board_late_init(void) { @@ -251,6 +303,11 @@ int ft_board_setup(void *blob, struct bd_info *bd) fdt_fixup_icid(blob); + /* This fixup may fail for legitimate + * reasons (see comments for fdt_fixup_usb_hub). + * Hence, errors with it are silently ignored. + */ + fdt_fixup_usb_hub(blob); return 0; } -- cgit v1.2.3