diff options
author | Ramneek Mehresh <ramneek.mehresh@freescale.com> | 2014-11-26 17:29:05 (GMT) |
---|---|---|
committer | Matthew Weigel <Matthew.Weigel@freescale.com> | 2014-12-11 18:41:33 (GMT) |
commit | cfacb4e6b8eb3889b5f36fd534f9e127268668f1 (patch) | |
tree | 54e52aa443334d28857493e3bebce00c5dc69e2b | |
parent | 6686e31d26bffe9d7ad3aa12b33502d9340ab8b5 (diff) | |
download | linux-fsl-qoriq-cfacb4e6b8eb3889b5f36fd534f9e127268668f1.tar.xz |
drivers: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>
Change-Id: Idc957b013a804bb4b12fa17836d0ae2371aeeed4
Reviewed-on: http://git.am.freescale.net:8181/24603
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Richard Schmitt <richard.schmitt@freescale.com>
-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 f5ead5c9..87a4eb9 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -37,11 +37,45 @@ #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]; +}; + struct ehci_fsl { struct ehci_hcd ehci; #ifdef CONFIG_PM - struct ehci_regs *saved_regs; + struct ehci_regs saved_regs; + struct ccsr_usb_phy saved_phy_regs; /* Saved USB PHY settings, need to restore after deep sleep. */ u32 usb_ctrl; #endif @@ -496,9 +530,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) { @@ -506,10 +540,10 @@ 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, + 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 = ioread32be(non_ehci + FSL_SOC_USB_CTRL); return 0; @@ -523,13 +557,13 @@ 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)); - iowrite32be(ehci_fsl->usb_ctrl, non_ehci + FSL_SOC_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; } |