Commit 70c8ba53dd42d90bc50801610065ca0119dfb1b1

Authored by George Cherian
Committed by Sekhar Nori
1 parent 3c6368174e

usb: dwc3: Save/Restore OTG registers while suspend/resume

With DRD enabled, OTG registers can lose context during suspend
resume. Save the registers during suspend and restore them
while resuming.

Signed-off-by: George Cherian <george.cherian@ti.com>
[nsekhar@ti.com: minor tweaks to patch description]
Signed-off-by: Sekhar Nori <nsekhar@ti.com>

Showing 3 changed files with 33 additions and 2 deletions Side-by-side Diff

drivers/usb/dwc3/core.c
... ... @@ -845,8 +845,9 @@
845 845 spin_lock_irqsave(&dwc->lock, flags);
846 846  
847 847 switch (dwc->dr_mode) {
848   - case USB_DR_MODE_PERIPHERAL:
849 848 case USB_DR_MODE_OTG:
  849 + dwc3_otg_suspend(dwc);
  850 + case USB_DR_MODE_PERIPHERAL:
850 851 dwc3_gadget_suspend(dwc);
851 852 /* FALLTHROUGH */
852 853 case USB_DR_MODE_HOST:
853 854  
... ... @@ -888,8 +889,9 @@
888 889 dwc3_event_buffers_setup(dwc);
889 890  
890 891 switch (dwc->dr_mode) {
891   - case USB_DR_MODE_PERIPHERAL:
892 892 case USB_DR_MODE_OTG:
  893 + dwc3_otg_resume(dwc);
  894 + case USB_DR_MODE_PERIPHERAL:
893 895 dwc3_gadget_resume(dwc);
894 896 /* FALLTHROUGH */
895 897 case USB_DR_MODE_HOST:
drivers/usb/dwc3/core.h
... ... @@ -780,6 +780,11 @@
780 780 /* used for suspend/resume */
781 781 u32 dcfg;
782 782 u32 gctl;
  783 + u32 ocfg;
  784 + u32 octl;
  785 + u32 oevt;
  786 + u32 oevten;
  787 + u32 osts;
783 788  
784 789 u32 nr_scratch;
785 790 u32 num_event_buffers;
786 791  
... ... @@ -1037,10 +1042,16 @@
1037 1042 #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
1038 1043 int dwc3_otg_init(struct dwc3 *dwc);
1039 1044 void dwc3_otg_exit(struct dwc3 *dwc);
  1045 +void dwc3_otg_suspend(struct dwc3 *dwc);
  1046 +void dwc3_otg_resume(struct dwc3 *dwc);
1040 1047 #else
1041 1048 static inline int dwc3_otg_init(struct dwc3 *dwc)
1042 1049 { return 0; }
1043 1050 static inline void dwc3_otg_exit(struct dwc3 *dwc)
  1051 +{ }
  1052 +static inline void dwc3_otg_suspend(struct dwc3 *dwc)
  1053 +{ }
  1054 +static inline void dwc3_otg_resume(struct dwc3 *dwc)
1044 1055 { }
1045 1056 #endif
1046 1057  
drivers/usb/dwc3/otg.c
... ... @@ -124,4 +124,22 @@
124 124  
125 125 return 0;
126 126 }
  127 +
  128 +void dwc3_otg_suspend(struct dwc3 *dwc)
  129 +{
  130 + dwc->ocfg = dwc3_readl(dwc->regs, DWC3_OCFG);
  131 + dwc->octl = dwc3_readl(dwc->regs, DWC3_OCTL);
  132 + dwc->oevt = dwc3_readl(dwc->regs, DWC3_OEVT);
  133 + dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN);
  134 + dwc->osts = dwc3_readl(dwc->regs, DWC3_OSTS);
  135 +}
  136 +
  137 +void dwc3_otg_resume(struct dwc3 *dwc)
  138 +{
  139 + dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg);
  140 + dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl);
  141 + dwc3_writel(dwc->regs, DWC3_OEVT, dwc->oevt);
  142 + dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
  143 + dwc3_writel(dwc->regs, DWC3_OSTS, dwc->osts);
  144 +}