Commit 70c8ba53dd42d90bc50801610065ca0119dfb1b1
Committed by
Sekhar Nori
1 parent
3c6368174e
Exists in
ti-linux-3.14.y
and in
2 other branches
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 | +} |