summaryrefslogtreecommitdiffstats
path: root/drivers/usb/cdns3/host.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-10 11:30:31 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-10 11:30:31 +0100
commitd2a968dddf98b837de9f9b3f954537c86c9a9f81 (patch)
tree2e7047f6a47bee0709f88ec00c2fda80d629d448 /drivers/usb/cdns3/host.c
parent8010622c86ca5bb44bc98492f5968726fc7c7a21 (diff)
parent8435ff0fd7e15ab4ec9e53107c9afefa23717e0f (diff)
downloadlinux-d2a968dddf98b837de9f9b3f954537c86c9a9f81.tar.bz2
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/host.c')
-rw-r--r--drivers/usb/cdns3/host.c60
1 files changed, 59 insertions, 1 deletions
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);