diff options
Diffstat (limited to 'drivers/usb/musb/musb_virthub.c')
-rw-r--r-- | drivers/usb/musb/musb_virthub.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index eb634433ef09..e2d2d8c9891b 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -135,7 +135,8 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) | |||
135 | 135 | ||
136 | /* later, GetPortStatus will stop RESUME signaling */ | 136 | /* later, GetPortStatus will stop RESUME signaling */ |
137 | musb->port1_status |= MUSB_PORT_STAT_RESUME; | 137 | musb->port1_status |= MUSB_PORT_STAT_RESUME; |
138 | schedule_delayed_work(&musb->finish_resume_work, 20); | 138 | schedule_delayed_work(&musb->finish_resume_work, |
139 | msecs_to_jiffies(20)); | ||
139 | } | 140 | } |
140 | } | 141 | } |
141 | 142 | ||
@@ -158,7 +159,6 @@ void musb_port_reset(struct musb *musb, bool do_reset) | |||
158 | */ | 159 | */ |
159 | power = musb_readb(mbase, MUSB_POWER); | 160 | power = musb_readb(mbase, MUSB_POWER); |
160 | if (do_reset) { | 161 | if (do_reset) { |
161 | |||
162 | /* | 162 | /* |
163 | * If RESUME is set, we must make sure it stays minimum 20 ms. | 163 | * If RESUME is set, we must make sure it stays minimum 20 ms. |
164 | * Then we must clear RESUME and wait a bit to let musb start | 164 | * Then we must clear RESUME and wait a bit to let musb start |
@@ -167,11 +167,22 @@ void musb_port_reset(struct musb *musb, bool do_reset) | |||
167 | * detected". | 167 | * detected". |
168 | */ | 168 | */ |
169 | if (power & MUSB_POWER_RESUME) { | 169 | if (power & MUSB_POWER_RESUME) { |
170 | while (time_before(jiffies, musb->rh_timer)) | 170 | long remain = (unsigned long) musb->rh_timer - jiffies; |
171 | msleep(1); | 171 | |
172 | if (musb->rh_timer > 0 && remain > 0) { | ||
173 | /* take into account the minimum delay after resume */ | ||
174 | schedule_delayed_work( | ||
175 | &musb->deassert_reset_work, remain); | ||
176 | return; | ||
177 | } | ||
178 | |||
172 | musb_writeb(mbase, MUSB_POWER, | 179 | musb_writeb(mbase, MUSB_POWER, |
173 | power & ~MUSB_POWER_RESUME); | 180 | power & ~MUSB_POWER_RESUME); |
174 | msleep(1); | 181 | |
182 | /* Give the core 1 ms to clear MUSB_POWER_RESUME */ | ||
183 | schedule_delayed_work(&musb->deassert_reset_work, | ||
184 | msecs_to_jiffies(1)); | ||
185 | return; | ||
175 | } | 186 | } |
176 | 187 | ||
177 | power &= 0xf0; | 188 | power &= 0xf0; |
@@ -180,7 +191,8 @@ void musb_port_reset(struct musb *musb, bool do_reset) | |||
180 | 191 | ||
181 | musb->port1_status |= USB_PORT_STAT_RESET; | 192 | musb->port1_status |= USB_PORT_STAT_RESET; |
182 | musb->port1_status &= ~USB_PORT_STAT_ENABLE; | 193 | musb->port1_status &= ~USB_PORT_STAT_ENABLE; |
183 | schedule_delayed_work(&musb->deassert_reset_work, 50); | 194 | schedule_delayed_work(&musb->deassert_reset_work, |
195 | msecs_to_jiffies(50)); | ||
184 | } else { | 196 | } else { |
185 | dev_dbg(musb->controller, "root port reset stopped\n"); | 197 | dev_dbg(musb->controller, "root port reset stopped\n"); |
186 | musb_writeb(mbase, MUSB_POWER, | 198 | musb_writeb(mbase, MUSB_POWER, |