[PATCH v4 2/3] usb: gadget: rcar: Add support for reset controller

Michele Bisogno micbis.openwrt at gmail.com
Wed Apr 22 18:59:37 CEST 2026


Some Renesas SoCs, such as the RZ/G2L, require the USBHS core to
be explicitly deasserted from reset before register access is
possible.

Update the OTG probe to handle a bulk reset controller. To maintain
hardware stability, the reset is deasserted after clocks are
enabled in probe(), and asserted before clocks are disabled
in remove().

Update the error paths in probe to ensures clocks are disabled
if the reset initialization fails.

Signed-off-by: Michele Bisogno <micbis.openwrt at gmail.com>
---
 drivers/usb/gadget/rcar/common.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/rcar/common.c b/drivers/usb/gadget/rcar/common.c
index f7b34f0485f..a5d56f8dbe4 100644
--- a/drivers/usb/gadget/rcar/common.c
+++ b/drivers/usb/gadget/rcar/common.c
@@ -16,6 +16,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <usb.h>
+#include <reset.h>
 
 #include "common.h"
 
@@ -290,6 +291,9 @@ struct usbhs_priv_otg_data {
 	void __iomem		*base;
 	void __iomem		*phybase;
 
+	struct clk_bulk clk_bulk;
+	struct reset_ctl_bulk reset_bulk;
+
 	struct platform_device	usbhs_dev;
 	struct usbhs_priv	usbhs_priv;
 
@@ -355,7 +359,7 @@ static int usbhs_udc_otg_gadget_handle_interrupts(struct udevice *dev)
 	return 0;
 }
 
-static int usbhs_probe(struct usbhs_priv *priv)
+static int usbhs_probe(struct usbhs_priv *priv, struct udevice *dev)
 {
 	int ret;
 
@@ -396,21 +400,28 @@ static int usbhs_udc_otg_probe(struct udevice *dev)
 {
 	struct usbhs_priv_otg_data *priv = dev_get_priv(dev);
 	struct usb_gadget *gadget;
-	struct clk_bulk clk_bulk;
 	int ret = -EINVAL;
 
 	priv->base = dev_read_addr_ptr(dev);
 	if (!priv->base)
 		return -EINVAL;
 
-	ret = clk_get_bulk(dev, &clk_bulk);
+	ret = clk_get_bulk(dev, &priv->clk_bulk);
 	if (ret)
 		return ret;
 
-	ret = clk_enable_bulk(&clk_bulk);
+	ret = clk_enable_bulk(&priv->clk_bulk);
 	if (ret)
 		return ret;
 
+	ret = reset_get_bulk(dev, &priv->reset_bulk);
+	if (ret)
+		goto err_clk;
+
+	ret = reset_deassert_bulk(&priv->reset_bulk);
+	if (ret)
+		goto err_clk;
+
 	clrsetbits_le32(priv->base + UGCTRL2, UGCTRL2_USB0SEL_MASK, UGCTRL2_USB0SEL_EHCI);
 	clrsetbits_le16(priv->base + LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
 
@@ -423,7 +434,7 @@ static int usbhs_udc_otg_probe(struct udevice *dev)
 	priv->usbhs_priv.pdev = &priv->usbhs_dev;
 	priv->usbhs_priv.base = priv->base;
 	priv->usbhs_dev.dev.driver_data = &priv->usbhs_priv;
-	ret = usbhs_probe(&priv->usbhs_priv);
+	ret = usbhs_probe(&priv->usbhs_priv, dev);
 	if (ret < 0)
 		goto err_phy;
 
@@ -440,7 +451,7 @@ static int usbhs_udc_otg_probe(struct udevice *dev)
 err_phy:
 	generic_shutdown_phy(&priv->phy);
 err_clk:
-	clk_disable_bulk(&clk_bulk);
+	clk_disable_bulk(&priv->clk_bulk);
 	return ret;
 }
 
@@ -457,6 +468,12 @@ static int usbhs_udc_otg_remove(struct udevice *dev)
 	usbhs_fifo_remove(&priv->usbhs_priv);
 	usbhs_pipe_remove(&priv->usbhs_priv);
 
+	reset_assert_bulk(&priv->reset_bulk);
+	reset_release_bulk(&priv->reset_bulk);
+
+	clk_disable_bulk(&priv->clk_bulk);
+	clk_release_bulk(&priv->clk_bulk);
+
 	generic_shutdown_phy(&priv->phy);
 
 	return dm_scan_fdt_dev(dev);
-- 
2.34.1



More information about the U-Boot mailing list