diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-12-10 11:30:31 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-12-10 11:30:31 +0100 |
commit | d2a968dddf98b837de9f9b3f954537c86c9a9f81 (patch) | |
tree | 2e7047f6a47bee0709f88ec00c2fda80d629d448 /drivers/usb/cdns3 | |
parent | 8010622c86ca5bb44bc98492f5968726fc7c7a21 (diff) | |
parent | 8435ff0fd7e15ab4ec9e53107c9afefa23717e0f (diff) |
Merge tag 'usb-v5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-next
Peter writes:
Below are main changes for v5.11-rc1:
For Chipidea USB2:
- Add tracepoint support for UDC
- Some tiny improvements
For Cadence USB3
- Add some quirks for host mode, and let host work well at more use cases
* SKIP_PHY_INIT
* Disable BEI
* Enable runtime PM default for i.mx platform
- Some tiny improvements
* tag 'usb-v5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb:
MAINTAINERS: Add myself as a reviewer for CADENCE USB3 DRD IP DRIVER
usb: chipidea: ci_hdrc_imx: Use of_device_get_match_data()
usb: chipidea: usbmisc_imx: Use of_device_get_match_data()
usb: cdns3: fix NULL pointer dereference on no platform data
usb: chipidea: trace: fix the endian issue
usb: chipidea: add tracepoint support for udc
doc: dt-binding: cdns,usb3: add wakeup-irq
usb: cdns3: imx: enable runtime pm by default
usb: cdns3: add quirk for enable runtime pm by default
usb: cdns3: host: disable BEI support
usb: cdns3: host: add xhci_plat_priv quirk XHCI_SKIP_PHY_INIT
usb: cdns3: host: add .suspend_quirk for xhci-plat.c
usb: cdns3: Rids of duplicate error message
usb: cdns3: Add static to cdns3_gadget_exit function
Diffstat (limited to 'drivers/usb/cdns3')
-rw-r--r-- | drivers/usb/cdns3/cdns3-imx.c | 2 | ||||
-rw-r--r-- | drivers/usb/cdns3/core.c | 15 | ||||
-rw-r--r-- | drivers/usb/cdns3/core.h | 4 | ||||
-rw-r--r-- | drivers/usb/cdns3/gadget-export.h | 3 | ||||
-rw-r--r-- | drivers/usb/cdns3/gadget.c | 2 | ||||
-rw-r--r-- | drivers/usb/cdns3/host-export.h | 6 | ||||
-rw-r--r-- | drivers/usb/cdns3/host.c | 60 |
7 files changed, 75 insertions, 17 deletions
diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c index 54a2d70a9c73..22a56c4dce67 100644 --- a/drivers/usb/cdns3/cdns3-imx.c +++ b/drivers/usb/cdns3/cdns3-imx.c @@ -151,6 +151,7 @@ static int cdns_imx_platform_suspend(struct device *dev, bool suspend, bool wakeup); static struct cdns3_platform_data cdns_imx_pdata = { .platform_suspend = cdns_imx_platform_suspend, + .quirks = CDNS3_DEFAULT_PM_RUNTIME_ALLOW, }; static const struct of_dev_auxdata cdns_imx_auxdata[] = { @@ -206,7 +207,6 @@ static int cdns_imx_probe(struct platform_device *pdev) device_set_wakeup_capable(dev, true); pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_forbid(dev); return ret; err: diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c index 039ab5d2435e..1991cb5cf6bf 100644 --- a/drivers/usb/cdns3/core.c +++ b/drivers/usb/cdns3/core.c @@ -465,11 +465,8 @@ static int cdns3_probe(struct platform_device *pdev) cdns->xhci_res[1] = *res; cdns->dev_irq = platform_get_irq_byname(pdev, "peripheral"); - if (cdns->dev_irq == -EPROBE_DEFER) - return cdns->dev_irq; - if (cdns->dev_irq < 0) - dev_err(dev, "couldn't get peripheral irq\n"); + return cdns->dev_irq; regs = devm_platform_ioremap_resource_byname(pdev, "dev"); if (IS_ERR(regs)) @@ -477,14 +474,9 @@ static int cdns3_probe(struct platform_device *pdev) cdns->dev_regs = regs; cdns->otg_irq = platform_get_irq_byname(pdev, "otg"); - if (cdns->otg_irq == -EPROBE_DEFER) + if (cdns->otg_irq < 0) return cdns->otg_irq; - if (cdns->otg_irq < 0) { - dev_err(dev, "couldn't get otg irq\n"); - return cdns->otg_irq; - } - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otg"); if (!res) { dev_err(dev, "couldn't get otg resource\n"); @@ -569,7 +561,8 @@ static int cdns3_probe(struct platform_device *pdev) device_set_wakeup_capable(dev, true); pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_forbid(dev); + if (!(cdns->pdata && (cdns->pdata->quirks & CDNS3_DEFAULT_PM_RUNTIME_ALLOW))) + pm_runtime_forbid(dev); /* * The controller needs less time between bus and controller suspend, diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h index 8a40d53d5ede..3176f924293a 100644 --- a/drivers/usb/cdns3/core.h +++ b/drivers/usb/cdns3/core.h @@ -42,6 +42,8 @@ struct cdns3_role_driver { struct cdns3_platform_data { int (*platform_suspend)(struct device *dev, bool suspend, bool wakeup); + unsigned long quirks; +#define CDNS3_DEFAULT_PM_RUNTIME_ALLOW BIT(0) }; /** @@ -73,6 +75,7 @@ struct cdns3_platform_data { * @wakeup_pending: wakeup interrupt pending * @pdata: platform data from glue layer * @lock: spinlock structure + * @xhci_plat_data: xhci private data structure pointer */ struct cdns3 { struct device *dev; @@ -106,6 +109,7 @@ struct cdns3 { bool wakeup_pending; struct cdns3_platform_data *pdata; spinlock_t lock; + struct xhci_plat_priv *xhci_plat_data; }; int cdns3_hw_role_switch(struct cdns3 *cdns); diff --git a/drivers/usb/cdns3/gadget-export.h b/drivers/usb/cdns3/gadget-export.h index 577469eee961..702c5a267a92 100644 --- a/drivers/usb/cdns3/gadget-export.h +++ b/drivers/usb/cdns3/gadget-export.h @@ -13,7 +13,6 @@ #ifdef CONFIG_USB_CDNS3_GADGET int cdns3_gadget_init(struct cdns3 *cdns); -void cdns3_gadget_exit(struct cdns3 *cdns); #else static inline int cdns3_gadget_init(struct cdns3 *cdns) @@ -21,8 +20,6 @@ static inline int cdns3_gadget_init(struct cdns3 *cdns) return -ENXIO; } -static inline void cdns3_gadget_exit(struct cdns3 *cdns) { } - #endif #endif /* __LINUX_CDNS3_GADGET_EXPORT */ diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 0aa85cc07ff1..08a4e693c470 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -3084,7 +3084,7 @@ static void cdns3_gadget_release(struct device *dev) kfree(priv_dev); } -void cdns3_gadget_exit(struct cdns3 *cdns) +static void cdns3_gadget_exit(struct cdns3 *cdns) { struct cdns3_device *priv_dev; diff --git a/drivers/usb/cdns3/host-export.h b/drivers/usb/cdns3/host-export.h index ae11810f8826..26041718a086 100644 --- a/drivers/usb/cdns3/host-export.h +++ b/drivers/usb/cdns3/host-export.h @@ -9,9 +9,11 @@ #ifndef __LINUX_CDNS3_HOST_EXPORT #define __LINUX_CDNS3_HOST_EXPORT +struct usb_hcd; #ifdef CONFIG_USB_CDNS3_HOST int cdns3_host_init(struct cdns3 *cdns); +int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd); #else @@ -21,6 +23,10 @@ static inline int cdns3_host_init(struct cdns3 *cdns) } static inline void cdns3_host_exit(struct cdns3 *cdns) { } +static inline int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd) +{ + return 0; +} #endif /* CONFIG_USB_CDNS3_HOST */ diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c index b3e2cb69762c..ec89f2e5430f 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c @@ -14,6 +14,19 @@ #include "drd.h" #include "host-export.h" #include <linux/usb/hcd.h> +#include "../host/xhci.h" +#include "../host/xhci-plat.h" + +#define XECP_PORT_CAP_REG 0x8000 +#define XECP_AUX_CTRL_REG1 0x8120 + +#define CFG_RXDET_P3_EN BIT(15) +#define LPM_2_STB_SWITCH_EN BIT(25) + +static const struct xhci_plat_priv xhci_plat_cdns3_xhci = { + .quirks = XHCI_SKIP_PHY_INIT | XHCI_AVOID_BEI, + .suspend_quirk = xhci_cdns3_suspend_quirk, +}; static int __cdns3_host_init(struct cdns3 *cdns) { @@ -39,10 +52,25 @@ static int __cdns3_host_init(struct cdns3 *cdns) goto err1; } + cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci, + sizeof(struct xhci_plat_priv), GFP_KERNEL); + if (!cdns->xhci_plat_data) { + ret = -ENOMEM; + goto err1; + } + + if (cdns->pdata && (cdns->pdata->quirks & CDNS3_DEFAULT_PM_RUNTIME_ALLOW)) + cdns->xhci_plat_data->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; + + ret = platform_device_add_data(xhci, cdns->xhci_plat_data, + sizeof(struct xhci_plat_priv)); + if (ret) + goto free_memory; + ret = platform_device_add(xhci); if (ret) { dev_err(cdns->dev, "failed to register xHCI device\n"); - goto err1; + goto free_memory; } /* Glue needs to access xHCI region register for Power management */ @@ -51,13 +79,43 @@ static int __cdns3_host_init(struct cdns3 *cdns) cdns->xhci_regs = hcd->regs; return 0; + +free_memory: + kfree(cdns->xhci_plat_data); err1: platform_device_put(xhci); return ret; } +int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + u32 value; + + if (pm_runtime_status_suspended(hcd->self.controller)) + return 0; + + /* set usbcmd.EU3S */ + value = readl(&xhci->op_regs->command); + value |= CMD_PM_INDEX; + writel(value, &xhci->op_regs->command); + + if (hcd->regs) { + value = readl(hcd->regs + XECP_AUX_CTRL_REG1); + value |= CFG_RXDET_P3_EN; + writel(value, hcd->regs + XECP_AUX_CTRL_REG1); + + value = readl(hcd->regs + XECP_PORT_CAP_REG); + value |= LPM_2_STB_SWITCH_EN; + writel(value, hcd->regs + XECP_PORT_CAP_REG); + } + + return 0; +} + static void cdns3_host_exit(struct cdns3 *cdns) { + kfree(cdns->xhci_plat_data); platform_device_unregister(cdns->host_dev); cdns->host_dev = NULL; cdns3_drd_host_off(cdns); |