Loading drivers/usb/cdns3/host-export.h +6 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 */ Loading drivers/usb/cdns3/host.c +43 −0 Original line number Diff line number Diff line Loading @@ -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 BIT(15) #define LPM_2_STB_SWITCH_EN BIT(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) { Loading @@ -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"); Loading @@ -56,6 +73,32 @@ 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; 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) { platform_device_unregister(cdns->host_dev); Loading Loading
drivers/usb/cdns3/host-export.h +6 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 */ Loading
drivers/usb/cdns3/host.c +43 −0 Original line number Diff line number Diff line Loading @@ -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 BIT(15) #define LPM_2_STB_SWITCH_EN BIT(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) { Loading @@ -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"); Loading @@ -56,6 +73,32 @@ 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; 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) { platform_device_unregister(cdns->host_dev); Loading