]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: uhci: Add reset control support
authorRyan Chen <ryan_chen@aspeedtech.com>
Mon, 22 Sep 2025 05:20:43 +0000 (13:20 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Oct 2025 07:11:49 +0000 (09:11 +0200)
Some SoCs, such as the Aspeed AST2700, require the UHCI controller
to be taken out of reset before it can operate. Add optional reset
control support to the UHCI platform driver.

The driver now acquires an optional reset line from device tree,
deasserts it during probe, and asserts it again in the error path
and shutdown.

Signed-off-by: Ryan Chen <ryan_chen@aspeedtech.com>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://lore.kernel.org/r/20250922052045.2421480-3-ryan_chen@aspeedtech.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-platform.c

index 13ee2a6144b2c98b6d628c97de9cb22891a0b76f..4326d1f3ca768d02cf241f5c1275a840f504b711 100644 (file)
@@ -445,6 +445,7 @@ struct uhci_hcd {
        short load[MAX_PHASE];                  /* Periodic allocations */
 
        struct clk *clk;                        /* (optional) clock source */
+       struct reset_control *rsts;             /* (optional) clock reset */
 
        /* Reset host controller */
        void    (*reset_hc) (struct uhci_hcd *uhci);
index 62318291f5664c9ec94f24535c71d962e28354f3..aa75b546672b5eca8d215b54fa6174a2f64f168d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/of.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/reset.h>
 
 static int uhci_platform_init(struct usb_hcd *hcd)
 {
@@ -132,17 +133,28 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
                goto err_rmr;
        }
 
+       uhci->rsts = devm_reset_control_array_get_optional_shared(&pdev->dev);
+       if (IS_ERR(uhci->rsts)) {
+               ret = PTR_ERR(uhci->rsts);
+               goto err_clk;
+       }
+       ret = reset_control_deassert(uhci->rsts);
+       if (ret)
+               goto err_clk;
+
        ret = platform_get_irq(pdev, 0);
        if (ret < 0)
-               goto err_clk;
+               goto err_reset;
 
        ret = usb_add_hcd(hcd, ret, IRQF_SHARED);
        if (ret)
-               goto err_clk;
+               goto err_reset;
 
        device_wakeup_enable(hcd->self.controller);
        return 0;
 
+err_reset:
+       reset_control_assert(uhci->rsts);
 err_clk:
        clk_disable_unprepare(uhci->clk);
 err_rmr:
@@ -156,6 +168,7 @@ static void uhci_hcd_platform_remove(struct platform_device *pdev)
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
+       reset_control_assert(uhci->rsts);
        clk_disable_unprepare(uhci->clk);
        usb_remove_hcd(hcd);
        usb_put_hcd(hcd);