musb->port1_status |=
                                                (USB_PORT_STAT_C_SUSPEND << 16)
                                                | MUSB_PORT_STAT_RESUME;
-                               musb->rh_timer = jiffies
-                                               + msecs_to_jiffies(20);
+                               schedule_delayed_work(
+                                       &musb->finish_resume_work, 20);
 
                                musb->xceiv->state = OTG_STATE_A_HOST;
                                musb->is_active = 1;
        musb_host_free(musb);
 }
 
+static void musb_deassert_reset(struct work_struct *work)
+{
+       struct musb *musb;
+       unsigned long flags;
+
+       musb = container_of(work, struct musb, deassert_reset_work.work);
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       if (musb->port1_status & USB_PORT_STAT_RESET)
+               musb_port_reset(musb, false);
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
 /*
  * Perform generic per-controller initialization.
  *
 
        /* Init IRQ workqueue before request_irq */
        INIT_WORK(&musb->irq_work, musb_irq_work);
+       INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
+       INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
 
        /* setup musb parts of the core (especially endpoints) */
        status = musb_core_init(plat->config->multipoint
 
 fail3:
        cancel_work_sync(&musb->irq_work);
+       cancel_delayed_work_sync(&musb->finish_resume_work);
+       cancel_delayed_work_sync(&musb->deassert_reset_work);
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 fail2_5:
                dma_controller_destroy(musb->dma_controller);
 
        cancel_work_sync(&musb->irq_work);
+       cancel_delayed_work_sync(&musb->finish_resume_work);
+       cancel_delayed_work_sync(&musb->deassert_reset_work);
        musb_free(musb);
        device_init_wakeup(dev, 0);
        return 0;
 
 
 #include "musb_core.h"
 
+void musb_host_finish_resume(struct work_struct *work)
+{
+       struct musb *musb;
+       unsigned long flags;
+       u8 power;
+
+       musb = container_of(work, struct musb, deassert_reset_work.work);
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       power = musb_readb(musb->mregs, MUSB_POWER);
+       power &= ~MUSB_POWER_RESUME;
+       dev_dbg(musb->controller, "root port resume stopped, power %02x\n",
+               power);
+       musb_writeb(musb->mregs, MUSB_POWER, power);
+
+       /*
+        * ISSUE:  DaVinci (RTL 1.300) disconnects after
+        * resume of high speed peripherals (but not full
+        * speed ones).
+        */
+       musb->is_active = 1;
+       musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | MUSB_PORT_STAT_RESUME);
+       musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+       usb_hcd_poll_rh_status(musb->hcd);
+       /* NOTE: it might really be A_WAIT_BCON ... */
+       musb->xceiv->state = OTG_STATE_A_HOST;
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+}
+
 void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
        struct usb_otg  *otg = musb->xceiv->otg;
 
                /* later, GetPortStatus will stop RESUME signaling */
                musb->port1_status |= MUSB_PORT_STAT_RESUME;
-               musb->rh_timer = jiffies + msecs_to_jiffies(20);
+               schedule_delayed_work(&musb->finish_resume_work, 20);
        }
 }
 
 
                musb->port1_status |= USB_PORT_STAT_RESET;
                musb->port1_status &= ~USB_PORT_STAT_ENABLE;
-               musb->rh_timer = jiffies + msecs_to_jiffies(50);
+               schedule_delayed_work(&musb->deassert_reset_work, 50);
        } else {
                dev_dbg(musb->controller, "root port reset stopped\n");
                musb_writeb(mbase, MUSB_POWER,
                if (wIndex != 1)
                        goto error;
 
-               /* finish RESET signaling? */
-               if ((musb->port1_status & USB_PORT_STAT_RESET)
-                               && time_after_eq(jiffies, musb->rh_timer))
-                       musb_port_reset(musb, false);
-
-               /* finish RESUME signaling? */
-               if ((musb->port1_status & MUSB_PORT_STAT_RESUME)
-                               && time_after_eq(jiffies, musb->rh_timer)) {
-                       u8              power;
-
-                       power = musb_readb(musb->mregs, MUSB_POWER);
-                       power &= ~MUSB_POWER_RESUME;
-                       dev_dbg(musb->controller, "root port resume stopped, power %02x\n",
-                                       power);
-                       musb_writeb(musb->mregs, MUSB_POWER, power);
-
-                       /* ISSUE:  DaVinci (RTL 1.300) disconnects after
-                        * resume of high speed peripherals (but not full
-                        * speed ones).
-                        */
-
-                       musb->is_active = 1;
-                       musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
-                                       | MUSB_PORT_STAT_RESUME);
-                       musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
-                       usb_hcd_poll_rh_status(musb->hcd);
-                       /* NOTE: it might really be A_WAIT_BCON ... */
-                       musb->xceiv->state = OTG_STATE_A_HOST;
-               }
-
                put_unaligned(cpu_to_le32(musb->port1_status
                                        & ~MUSB_PORT_STAT_RESUME),
                                (__le32 *) buf);