aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_virthub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/musb_virthub.c')
-rw-r--r--drivers/usb/musb/musb_virthub.c26
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,