Update Linux to v5.10.109
Sourced from [1]
[1] https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.109.tar.xz
Change-Id: I19bca9fc6762d4e63bcf3e4cba88bbe560d9c76c
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c
index ad788bf..1029777 100644
--- a/drivers/usb/cdns3/host.c
+++ b/drivers/usb/cdns3/host.c
@@ -13,13 +13,28 @@
#include "core.h"
#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,
+ .suspend_quirk = xhci_cdns3_suspend_quirk,
+};
static int __cdns3_host_init(struct cdns3 *cdns)
{
struct platform_device *xhci;
int ret;
+ struct usb_hcd *hcd;
- cdns3_drd_switch_host(cdns, 1);
+ cdns3_drd_host_on(cdns);
xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
if (!xhci) {
@@ -37,23 +52,73 @@
goto err1;
}
- ret = platform_device_add(xhci);
- if (ret) {
- dev_err(cdns->dev, "failed to register xHCI device\n");
+ 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 free_memory;
+ }
+
+ /* Glue needs to access xHCI region register for Power management */
+ hcd = platform_get_drvdata(xhci);
+ if (hcd)
+ 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_switch_host(cdns, 0);
+ cdns3_drd_host_off(cdns);
}
int cdns3_host_init(struct cdns3 *cdns)