Message ID | 20200707074941.28078-9-peter.chen@nxp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | usb: some PM changes for cdns3 and xhci-plat | expand |
> >cdns3 has some special PM sequence between xhci_bus_suspend and >xhci_suspend, add quirk to implement it. > >Signed-off-by: Peter Chen <peter.chen@nxp.com> >--- > drivers/usb/cdns3/host-export.h | 6 +++++ > drivers/usb/cdns3/host.c | 40 +++++++++++++++++++++++++++++++++ > 2 files changed, 46 insertions(+) > >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 b579ef15f4e0..030d6421abd3 100644 >--- a/drivers/usb/cdns3/host.c >+++ b/drivers/usb/cdns3/host.c >@@ -14,6 +14,18 @@ > #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 (1 << 15) >+#define LPM_2_STB_SWITCH_EN (1 << 25) >+ Please use BIT(15) and BIT(25) Reviewed-by: Pawel Laszczak <pawell@cadence.com> Regards Pawel >+static const struct xhci_plat_priv xhci_plat_cdns3_xhci = { >+ .suspend_quirk = xhci_cdns3_suspend_quirk, >+}; > > static int __cdns3_host_init(struct cdns3 *cdns) > { >@@ -39,6 +51,11 @@ static int __cdns3_host_init(struct cdns3 *cdns) > goto err1; > } > >+ ret = platform_device_add_data(xhci, &xhci_plat_cdns3_xhci, >+ sizeof(struct xhci_plat_priv)); >+ if (ret) >+ goto err1; >+ > ret = platform_device_add(xhci); > if (ret) { > dev_err(cdns->dev, "failed to register xHCI device\n"); >@@ -56,6 +73,29 @@ static int __cdns3_host_init(struct cdns3 *cdns) > return ret; > } > >+int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd) >+{ >+ struct xhci_hcd *xhci = hcd_to_xhci(hcd); >+ u32 value; >+ >+ /* 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) > { > platform_device_unregister(cdns->host_dev); >-- >2.17.1
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 b579ef15f4e0..030d6421abd3 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c @@ -14,6 +14,18 @@ #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 (1 << 15) +#define LPM_2_STB_SWITCH_EN (1 << 25) + +static const struct xhci_plat_priv xhci_plat_cdns3_xhci = { + .suspend_quirk = xhci_cdns3_suspend_quirk, +}; static int __cdns3_host_init(struct cdns3 *cdns) { @@ -39,6 +51,11 @@ static int __cdns3_host_init(struct cdns3 *cdns) goto err1; } + ret = platform_device_add_data(xhci, &xhci_plat_cdns3_xhci, + sizeof(struct xhci_plat_priv)); + if (ret) + goto err1; + ret = platform_device_add(xhci); if (ret) { dev_err(cdns->dev, "failed to register xHCI device\n"); @@ -56,6 +73,29 @@ static int __cdns3_host_init(struct cdns3 *cdns) return ret; } +int xhci_cdns3_suspend_quirk(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + u32 value; + + /* 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) { platform_device_unregister(cdns->host_dev);
cdns3 has some special PM sequence between xhci_bus_suspend and xhci_suspend, add quirk to implement it. Signed-off-by: Peter Chen <peter.chen@nxp.com> --- drivers/usb/cdns3/host-export.h | 6 +++++ drivers/usb/cdns3/host.c | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+)