diff options
author | Ramneek Mehresh <ramneek.mehresh@freescale.com> | 2014-11-26 17:29:05 (GMT) |
---|---|---|
committer | Xie Xiaobo <xiaobo.xie@nxp.com> | 2017-09-25 07:25:28 (GMT) |
commit | d0aa3d22a373a7884634b90177ace9b3eadb6001 (patch) | |
tree | 76f68ec9dda770b61a63194b4650e747902ea70a /drivers | |
parent | 53c99566aeffa132dcb23ede0ca53deb39a2f8cb (diff) | |
download | linux-d0aa3d22a373a7884634b90177ace9b3eadb6001.tar.xz |
usb: fsl: Fix deep-sleep resume issue caused by usb
usb ip driver needs to save and restore all registers including
phy registers across deep-sleep. This is required since latest
changes in u-boot code doesn't re-init usb phy anymore during
deep-sleep resume
Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
Signed-off-by: Suresh Gupta <suresh.gupta@freescale.com>
Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
Signed-off-by: yinbo.zhu <yinbo.zhu@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 62 |
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e09dcfd..b475bc5 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -40,6 +40,39 @@ #include "ehci.h" #include "ehci-fsl.h" +#define FSL_USB_PHY_ADDR 0xffe214000 + +struct ccsr_usb_port_ctrl { + u32 ctrl; + u32 drvvbuscfg; + u32 pwrfltcfg; + u32 sts; + u8 res_14[0xc]; + u32 bistcfg; + u32 biststs; + u32 abistcfg; + u32 abiststs; + u8 res_30[0x10]; + u32 xcvrprg; + u32 anaprg; + u32 anadrv; + u32 anasts; +}; + +struct ccsr_usb_phy { + u32 id; + struct ccsr_usb_port_ctrl port1; + u8 res_50[0xc]; + u32 tvr; + u32 pllprg[4]; + u8 res_70[0x4]; + u32 anaccfg; + u32 dbg; + u8 res_7c[0x4]; + struct ccsr_usb_port_ctrl port2; + u8 res_dc[0x334]; +}; + #define DRIVER_DESC "Freescale EHCI Host controller driver" #define DRV_NAME "ehci-fsl" @@ -507,9 +540,9 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) } - - #ifdef CONFIG_PM +void __iomem *phy_reg; + /* save usb registers */ static int ehci_fsl_save_context(struct usb_hcd *hcd) { @@ -517,11 +550,11 @@ static int ehci_fsl_save_context(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; - ehci_fsl->saved_regs = kzalloc(sizeof(struct ehci_regs), GFP_KERNEL); - if (!ehci_fsl->saved_regs) - return -ENOMEM; - _memcpy_fromio(ehci_fsl->saved_regs, ehci->regs, - sizeof(struct ehci_regs)); + phy_reg = ioremap(FSL_USB_PHY_ADDR, sizeof(struct ccsr_usb_phy)); + _memcpy_fromio((void *)&ehci_fsl->saved_phy_regs, phy_reg, + sizeof(struct ccsr_usb_phy)); + _memcpy_fromio((void *)&ehci_fsl->saved_regs, ehci->regs, + sizeof(struct ehci_regs)); ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL); return 0; @@ -534,13 +567,14 @@ static int ehci_fsl_restore_context(struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; - if (ehci_fsl->saved_regs) { - _memcpy_toio(ehci->regs, ehci_fsl->saved_regs, - sizeof(struct ehci_regs)); - out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl); - kfree(ehci_fsl->saved_regs); - ehci_fsl->saved_regs = NULL; - } + if (phy_reg) + _memcpy_toio(phy_reg, (void *)&ehci_fsl->saved_phy_regs, + sizeof(struct ccsr_usb_phy)); + + _memcpy_toio(ehci->regs, (void *)&ehci_fsl->saved_regs, + sizeof(struct ehci_regs)); + iowrite32be(ehci_fsl->usb_ctrl, non_ehci + FSL_SOC_USB_CTRL); + return 0; } |