diff options
Diffstat (limited to 'drivers/usb/host/xhci-plat.c')
| -rw-r--r-- | drivers/usb/host/xhci-plat.c | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 3d071b875308..074d9c731639 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -20,6 +20,7 @@ #include <linux/acpi.h> #include <linux/usb/of.h> #include <linux/reset.h> +#include <linux/usb/xhci-sideband.h> #include "xhci.h" #include "xhci-plat.h" @@ -74,6 +75,16 @@ static int xhci_priv_resume_quirk(struct usb_hcd *hcd) return priv->resume_quirk(hcd); } +static int xhci_priv_post_resume_quirk(struct usb_hcd *hcd) +{ + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + + if (!priv->post_resume_quirk) + return 0; + + return priv->post_resume_quirk(hcd); +} + static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) { struct xhci_plat_priv *priv = xhci_to_priv(xhci); @@ -106,7 +117,7 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = { }; static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { - .init_quirk = xhci_mvebu_a3700_init_quirk, + .quirks = XHCI_RESET_ON_RESUME, }; static const struct xhci_plat_priv xhci_plat_brcm = { @@ -152,7 +163,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s int ret; int irq; struct xhci_plat_priv *priv = NULL; - bool of_match; + const struct of_device_id *of_match; if (usb_disabled()) return -ENODEV; @@ -171,6 +182,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s return ret; pm_runtime_set_active(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); @@ -256,8 +268,19 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk")) xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK; + if (device_property_read_bool(tmpdev, "write-64-hi-lo-quirk")) + xhci->quirks |= XHCI_WRITE_64_HI_LO; + + if (device_property_read_bool(tmpdev, "xhci-missing-cas-quirk")) + xhci->quirks |= XHCI_MISSING_CAS; + + if (device_property_read_bool(tmpdev, "xhci-skip-phy-init-quirk")) + xhci->quirks |= XHCI_SKIP_PHY_INIT; + device_property_read_u32(tmpdev, "imod-interval-ns", &xhci->imod_interval); + device_property_read_u16(tmpdev, "num-hc-interrupters", + &xhci->max_interrupters); } /* @@ -281,7 +304,8 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); - if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) + if ((priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) || + (xhci->quirks & XHCI_SKIP_PHY_INIT)) hcd->skip_phy_initialization = 1; if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK)) @@ -316,10 +340,13 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s } usb3_hcd = xhci_get_usb3_hcd(xhci); - if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4) + if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 && + !(xhci->quirks & XHCI_BROKEN_STREAMS)) usb3_hcd->can_do_streams = 1; if (xhci->shared_hcd) { + xhci->shared_hcd->rsrc_start = hcd->rsrc_start; + xhci->shared_hcd->rsrc_len = hcd->rsrc_len; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; @@ -439,7 +466,7 @@ void xhci_plat_remove(struct platform_device *dev) } EXPORT_SYMBOL_GPL(xhci_plat_remove); -static int xhci_plat_suspend(struct device *dev) +static int xhci_plat_suspend_common(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); @@ -467,9 +494,29 @@ static int xhci_plat_suspend(struct device *dev) return 0; } -static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg) +static int xhci_plat_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + + if (xhci_sideband_check(hcd)) { + priv->sideband_at_suspend = 1; + dev_dbg(dev, "sideband instance active, skip suspend.\n"); + return 0; + } + + return xhci_plat_suspend_common(dev); +} + +static int xhci_plat_freeze(struct device *dev) +{ + return xhci_plat_suspend_common(dev); +} + +static int xhci_plat_resume_common(struct device *dev, bool power_lost) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; @@ -489,7 +536,11 @@ static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg) if (ret) goto disable_clks; - ret = xhci_resume(xhci, pmsg); + ret = xhci_resume(xhci, power_lost || priv->power_lost, false); + if (ret) + goto disable_clks; + + ret = xhci_priv_post_resume_quirk(hcd); if (ret) goto disable_clks; @@ -510,12 +561,26 @@ disable_clks: static int xhci_plat_resume(struct device *dev) { - return xhci_plat_resume_common(dev, PMSG_RESUME); + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); + + if (priv->sideband_at_suspend) { + priv->sideband_at_suspend = 0; + dev_dbg(dev, "sideband instance active, skip resume.\n"); + return 0; + } + + return xhci_plat_resume_common(dev, false); +} + +static int xhci_plat_thaw(struct device *dev) +{ + return xhci_plat_resume_common(dev, false); } static int xhci_plat_restore(struct device *dev) { - return xhci_plat_resume_common(dev, PMSG_RESTORE); + return xhci_plat_resume_common(dev, true); } static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) @@ -536,15 +601,15 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); - return xhci_resume(xhci, PMSG_AUTO_RESUME); + return xhci_resume(xhci, false, true); } const struct dev_pm_ops xhci_plat_pm_ops = { .suspend = pm_sleep_ptr(xhci_plat_suspend), .resume = pm_sleep_ptr(xhci_plat_resume), - .freeze = pm_sleep_ptr(xhci_plat_suspend), - .thaw = pm_sleep_ptr(xhci_plat_resume), - .poweroff = pm_sleep_ptr(xhci_plat_suspend), + .freeze = pm_sleep_ptr(xhci_plat_freeze), + .thaw = pm_sleep_ptr(xhci_plat_thaw), + .poweroff = pm_sleep_ptr(xhci_plat_freeze), .restore = pm_sleep_ptr(xhci_plat_restore), SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, @@ -557,6 +622,7 @@ EXPORT_SYMBOL_GPL(xhci_plat_pm_ops); static const struct acpi_device_id usb_xhci_acpi_match[] = { /* XHCI-compliant USB Controller */ { "PNP0D10", }, + { "PNP0D15", }, { } }; MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); @@ -564,7 +630,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); static struct platform_driver usb_generic_xhci_driver = { .probe = xhci_generic_plat_probe, - .remove_new = xhci_plat_remove, + .remove = xhci_plat_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "xhci-hcd", |
