diff options
Diffstat (limited to 'drivers/usb/dwc3/dwc3-imx8mp.c')
-rw-r--r-- | drivers/usb/dwc3/dwc3-imx8mp.c | 117 |
1 files changed, 54 insertions, 63 deletions
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c index 8ee448068503..3edc5aca76f9 100644 --- a/drivers/usb/dwc3/dwc3-imx8mp.c +++ b/drivers/usb/dwc3/dwc3-imx8mp.c @@ -5,6 +5,7 @@ * Copyright (c) 2020 NXP. */ +#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -96,7 +97,8 @@ static void imx8mp_configure_glue(struct dwc3_imx8mp *dwc3_imx) writel(value, dwc3_imx->glue_base + USB_CTRL1); } -static void dwc3_imx8mp_wakeup_enable(struct dwc3_imx8mp *dwc3_imx) +static void dwc3_imx8mp_wakeup_enable(struct dwc3_imx8mp *dwc3_imx, + pm_message_t msg) { struct dwc3 *dwc3 = platform_get_drvdata(dwc3_imx->dwc3); u32 val; @@ -106,12 +108,14 @@ static void dwc3_imx8mp_wakeup_enable(struct dwc3_imx8mp *dwc3_imx) val = readl(dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL); - if ((dwc3->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc3->xhci) - val |= USB_WAKEUP_EN | USB_WAKEUP_SS_CONN | - USB_WAKEUP_U3_EN | USB_WAKEUP_DPDM_EN; - else if (dwc3->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE) + if ((dwc3->current_dr_role == DWC3_GCTL_PRTCAP_HOST) && dwc3->xhci) { + val |= USB_WAKEUP_EN | USB_WAKEUP_DPDM_EN; + if (PMSG_IS_AUTO(msg)) + val |= USB_WAKEUP_SS_CONN | USB_WAKEUP_U3_EN; + } else { val |= USB_WAKEUP_EN | USB_WAKEUP_VBUS_EN | USB_WAKEUP_VBUS_SRC_SESS_VAL; + } writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL); } @@ -125,6 +129,16 @@ static void dwc3_imx8mp_wakeup_disable(struct dwc3_imx8mp *dwc3_imx) writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL); } +static const struct property_entry dwc3_imx8mp_properties[] = { + PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"), + PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"), + {}, +}; + +static const struct software_node dwc3_imx8mp_swnode = { + .properties = dwc3_imx8mp_properties, +}; + static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx) { struct dwc3_imx8mp *dwc3_imx = _dwc3_imx; @@ -147,7 +161,7 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx) static int dwc3_imx8mp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *dwc3_np, *node = dev->of_node; + struct device_node *node = dev->of_node; struct dwc3_imx8mp *dwc3_imx; struct resource *res; int err, irq; @@ -178,39 +192,26 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev) return PTR_ERR(dwc3_imx->glue_base); } - dwc3_imx->hsio_clk = devm_clk_get(dev, "hsio"); - if (IS_ERR(dwc3_imx->hsio_clk)) { - err = PTR_ERR(dwc3_imx->hsio_clk); - dev_err(dev, "Failed to get hsio clk, err=%d\n", err); - return err; - } + dwc3_imx->hsio_clk = devm_clk_get_enabled(dev, "hsio"); + if (IS_ERR(dwc3_imx->hsio_clk)) + return dev_err_probe(dev, PTR_ERR(dwc3_imx->hsio_clk), + "Failed to get hsio clk\n"); - err = clk_prepare_enable(dwc3_imx->hsio_clk); - if (err) { - dev_err(dev, "Failed to enable hsio clk, err=%d\n", err); - return err; - } - - dwc3_imx->suspend_clk = devm_clk_get(dev, "suspend"); - if (IS_ERR(dwc3_imx->suspend_clk)) { - err = PTR_ERR(dwc3_imx->suspend_clk); - dev_err(dev, "Failed to get suspend clk, err=%d\n", err); - goto disable_hsio_clk; - } - - err = clk_prepare_enable(dwc3_imx->suspend_clk); - if (err) { - dev_err(dev, "Failed to enable suspend clk, err=%d\n", err); - goto disable_hsio_clk; - } + dwc3_imx->suspend_clk = devm_clk_get_enabled(dev, "suspend"); + if (IS_ERR(dwc3_imx->suspend_clk)) + return dev_err_probe(dev, PTR_ERR(dwc3_imx->suspend_clk), + "Failed to get suspend clk\n"); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - err = irq; - goto disable_clks; - } + if (irq < 0) + return irq; dwc3_imx->irq = irq; + struct device_node *dwc3_np __free(device_node) = of_get_compatible_child(node, + "snps,dwc3"); + if (!dwc3_np) + return dev_err_probe(dev, -ENODEV, "failed to find dwc3 core child\n"); + imx8mp_configure_glue(dwc3_imx); pm_runtime_set_active(dev); @@ -219,17 +220,17 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev) if (err < 0) goto disable_rpm; - dwc3_np = of_get_compatible_child(node, "snps,dwc3"); - if (!dwc3_np) { + err = device_add_software_node(dev, &dwc3_imx8mp_swnode); + if (err) { err = -ENODEV; - dev_err(dev, "failed to find dwc3 core child\n"); + dev_err(dev, "failed to add software node\n"); goto disable_rpm; } err = of_platform_populate(node, NULL, NULL, dev); if (err) { dev_err(&pdev->dev, "failed to create dwc3 core\n"); - goto err_node_put; + goto remove_swnode; } dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np); @@ -238,7 +239,6 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev) err = -ENODEV; goto depopulate; } - of_node_put(dwc3_np); err = devm_request_threaded_irq(dev, irq, NULL, dwc3_imx8mp_interrupt, IRQF_ONESHOT, dev_name(dev), dwc3_imx); @@ -254,51 +254,42 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev) depopulate: of_platform_depopulate(dev); -err_node_put: - of_node_put(dwc3_np); +remove_swnode: + device_remove_software_node(dev); disable_rpm: pm_runtime_disable(dev); pm_runtime_put_noidle(dev); -disable_clks: - clk_disable_unprepare(dwc3_imx->suspend_clk); -disable_hsio_clk: - clk_disable_unprepare(dwc3_imx->hsio_clk); return err; } static void dwc3_imx8mp_remove(struct platform_device *pdev) { - struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; pm_runtime_get_sync(dev); of_platform_depopulate(dev); - - clk_disable_unprepare(dwc3_imx->suspend_clk); - clk_disable_unprepare(dwc3_imx->hsio_clk); + device_remove_software_node(dev); pm_runtime_disable(dev); pm_runtime_put_noidle(dev); } -static int __maybe_unused dwc3_imx8mp_suspend(struct dwc3_imx8mp *dwc3_imx, - pm_message_t msg) +static int dwc3_imx8mp_suspend(struct dwc3_imx8mp *dwc3_imx, pm_message_t msg) { if (dwc3_imx->pm_suspended) return 0; /* Wakeup enable */ if (PMSG_IS_AUTO(msg) || device_may_wakeup(dwc3_imx->dev)) - dwc3_imx8mp_wakeup_enable(dwc3_imx); + dwc3_imx8mp_wakeup_enable(dwc3_imx, msg); dwc3_imx->pm_suspended = true; return 0; } -static int __maybe_unused dwc3_imx8mp_resume(struct dwc3_imx8mp *dwc3_imx, - pm_message_t msg) +static int dwc3_imx8mp_resume(struct dwc3_imx8mp *dwc3_imx, pm_message_t msg) { struct dwc3 *dwc = platform_get_drvdata(dwc3_imx->dwc3); int ret = 0; @@ -331,7 +322,7 @@ static int __maybe_unused dwc3_imx8mp_resume(struct dwc3_imx8mp *dwc3_imx, return ret; } -static int __maybe_unused dwc3_imx8mp_pm_suspend(struct device *dev) +static int dwc3_imx8mp_pm_suspend(struct device *dev) { struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); int ret; @@ -349,7 +340,7 @@ static int __maybe_unused dwc3_imx8mp_pm_suspend(struct device *dev) return ret; } -static int __maybe_unused dwc3_imx8mp_pm_resume(struct device *dev) +static int dwc3_imx8mp_pm_resume(struct device *dev) { struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); int ret; @@ -379,7 +370,7 @@ static int __maybe_unused dwc3_imx8mp_pm_resume(struct device *dev) return ret; } -static int __maybe_unused dwc3_imx8mp_runtime_suspend(struct device *dev) +static int dwc3_imx8mp_runtime_suspend(struct device *dev) { struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); @@ -388,7 +379,7 @@ static int __maybe_unused dwc3_imx8mp_runtime_suspend(struct device *dev) return dwc3_imx8mp_suspend(dwc3_imx, PMSG_AUTO_SUSPEND); } -static int __maybe_unused dwc3_imx8mp_runtime_resume(struct device *dev) +static int dwc3_imx8mp_runtime_resume(struct device *dev) { struct dwc3_imx8mp *dwc3_imx = dev_get_drvdata(dev); @@ -398,9 +389,9 @@ static int __maybe_unused dwc3_imx8mp_runtime_resume(struct device *dev) } static const struct dev_pm_ops dwc3_imx8mp_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(dwc3_imx8mp_pm_suspend, dwc3_imx8mp_pm_resume) - SET_RUNTIME_PM_OPS(dwc3_imx8mp_runtime_suspend, - dwc3_imx8mp_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(dwc3_imx8mp_pm_suspend, dwc3_imx8mp_pm_resume) + RUNTIME_PM_OPS(dwc3_imx8mp_runtime_suspend, dwc3_imx8mp_runtime_resume, + NULL) }; static const struct of_device_id dwc3_imx8mp_of_match[] = { @@ -411,10 +402,10 @@ MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match); static struct platform_driver dwc3_imx8mp_driver = { .probe = dwc3_imx8mp_probe, - .remove_new = dwc3_imx8mp_remove, + .remove = dwc3_imx8mp_remove, .driver = { .name = "imx8mp-dwc3", - .pm = &dwc3_imx8mp_dev_pm_ops, + .pm = pm_ptr(&dwc3_imx8mp_dev_pm_ops), .of_match_table = dwc3_imx8mp_of_match, }, }; |