Rename WARN() to WARNING() to clear the namespace
[safe/jmp/linux-2.6] / drivers / usb / host / isp116x-hcd.c
index 1ed2aba..ce1ca0b 100644 (file)
 /* enqueuing/finishing log of urbs */
 //#define URB_TRACE
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/interrupt.h>
 #include <linux/usb.h>
-#include <linux/usb_isp116x.h>
+#include <linux/usb/isp116x.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
 
-#ifndef DEBUG
-#      define  STUB_DEBUG_FILE
-#endif
-
 #include "../core/hcd.h"
 #include "isp116x.h"
 
-#define DRIVER_VERSION "08 Apr 2005"
+#define DRIVER_VERSION "03 Nov 2005"
 #define DRIVER_DESC    "ISP116x USB Host Controller Driver"
 
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -103,6 +94,10 @@ static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
        u16 w;
        int quot = len % 4;
 
+       /* buffer is already in 'usb data order', which is LE. */
+       /* When reading buffer as u16, we have to take care byte order */
+       /* doesn't get mixed up */
+
        if ((unsigned long)dp2 & 1) {
                /* not aligned */
                for (; len > 1; len -= 2) {
@@ -114,8 +109,11 @@ static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len)
                        isp116x_write_data16(isp116x, (u16) * dp);
        } else {
                /* aligned */
-               for (; len > 1; len -= 2)
-                       isp116x_raw_write_data16(isp116x, *dp2++);
+               for (; len > 1; len -= 2) {
+                       /* Keep byte order ! */
+                       isp116x_raw_write_data16(isp116x, cpu_to_le16(*dp2++));
+               }
+
                if (len)
                        isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
        }
@@ -133,6 +131,10 @@ static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
        u16 w;
        int quot = len % 4;
 
+       /* buffer is already in 'usb data order', which is LE. */
+       /* When reading buffer as u16, we have to take care byte order */
+       /* doesn't get mixed up */
+
        if ((unsigned long)dp2 & 1) {
                /* not aligned */
                for (; len > 1; len -= 2) {
@@ -140,12 +142,16 @@ static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len)
                        *dp++ = w & 0xff;
                        *dp++ = (w >> 8) & 0xff;
                }
+
                if (len)
                        *dp = 0xff & isp116x_read_data16(isp116x);
        } else {
                /* aligned */
-               for (; len > 1; len -= 2)
-                       *dp2++ = isp116x_raw_read_data16(isp116x);
+               for (; len > 1; len -= 2) {
+                       /* Keep byte order! */
+                       *dp2++ = le16_to_cpu(isp116x_raw_read_data16(isp116x));
+               }
+
                if (len)
                        *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
        }
@@ -163,13 +169,11 @@ static void pack_fifo(struct isp116x *isp116x)
        struct ptd *ptd;
        int buflen = isp116x->atl_last_dir == PTD_DIR_IN
            ? isp116x->atl_bufshrt : isp116x->atl_buflen;
-       int ptd_count = 0;
 
        isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
        isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
        isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
        for (ep = isp116x->atl_active; ep; ep = ep->active) {
-               ++ptd_count;
                ptd = &ep->ptd;
                dump_ptd(ptd);
                dump_ptd_out_data(ptd, ep->data);
@@ -239,7 +243,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
                                   struct urb, urb_list);
                ptd = &ep->ptd;
                len = ep->length;
-               spin_lock(&urb->lock);
                ep->data = (unsigned char *)urb->transfer_buffer
                    + urb->actual_length;
 
@@ -275,7 +278,6 @@ static void preproc_atl_queue(struct isp116x *isp116x)
                    | PTD_EP(ep->epnum);
                ptd->len = PTD_LEN(len) | PTD_DIR(dir);
                ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe));
-               spin_unlock(&urb->lock);
                if (!ep->active) {
                        ptd->mps |= PTD_LAST_MSK;
                        isp116x->atl_last_dir = dir;
@@ -286,6 +288,61 @@ static void preproc_atl_queue(struct isp116x *isp116x)
 }
 
 /*
+  Take done or failed requests out of schedule. Give back
+  processed urbs.
+*/
+static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
+                          struct urb *urb, int status)
+__releases(isp116x->lock) __acquires(isp116x->lock)
+{
+       unsigned i;
+
+       ep->error_count = 0;
+
+       if (usb_pipecontrol(urb->pipe))
+               ep->nextpid = USB_PID_SETUP;
+
+       urb_dbg(urb, "Finish");
+
+       usb_hcd_unlink_urb_from_ep(isp116x_to_hcd(isp116x), urb);
+       spin_unlock(&isp116x->lock);
+       usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, status);
+       spin_lock(&isp116x->lock);
+
+       /* take idle endpoints out of the schedule */
+       if (!list_empty(&ep->hep->urb_list))
+               return;
+
+       /* async deschedule */
+       if (!list_empty(&ep->schedule)) {
+               list_del_init(&ep->schedule);
+               return;
+       }
+
+       /* periodic deschedule */
+       DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
+       for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
+               struct isp116x_ep *temp;
+               struct isp116x_ep **prev = &isp116x->periodic[i];
+
+               while (*prev && ((temp = *prev) != ep))
+                       prev = &temp->next;
+               if (*prev)
+                       *prev = ep->next;
+               isp116x->load[i] -= ep->load;
+       }
+       ep->branch = PERIODIC_SIZE;
+       isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
+           ep->load / ep->period;
+
+       /* switch irq type? */
+       if (!--isp116x->periodic_count) {
+               isp116x->irqenb &= ~HCuPINT_SOF;
+               isp116x->irqenb |= HCuPINT_ATL;
+       }
+}
+
+/*
   Analyze transfer results, handle partial transfers and errors
 */
 static void postproc_atl_queue(struct isp116x *isp116x)
@@ -295,6 +352,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
        struct usb_device *udev;
        struct ptd *ptd;
        int short_not_ok;
+       int status;
        u8 cc;
 
        for (ep = isp116x->atl_active; ep; ep = ep->active) {
@@ -304,9 +362,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                udev = urb->dev;
                ptd = &ep->ptd;
                cc = PTD_GET_CC(ptd);
-
-               spin_lock(&urb->lock);
                short_not_ok = 1;
+               status = -EINPROGRESS;
 
                /* Data underrun is special. For allowed underrun
                   we clear the error and continue as normal. For
@@ -314,46 +371,36 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                   immediately while for control transfer,
                   we do a STATUS stage. */
                if (cc == TD_DATAUNDERRUN) {
-                       if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) {
-                               DBG("Allowed data underrun\n");
+                       if (!(urb->transfer_flags & URB_SHORT_NOT_OK) ||
+                                       usb_pipecontrol(urb->pipe)) {
+                               DBG("Allowed or control data underrun\n");
                                cc = TD_CC_NOERROR;
                                short_not_ok = 0;
                        } else {
                                ep->error_count = 1;
-                               if (usb_pipecontrol(urb->pipe))
-                                       ep->nextpid = USB_PID_ACK;
-                               else
-                                       usb_settoggle(udev, ep->epnum,
-                                                     ep->nextpid ==
-                                                     USB_PID_OUT,
-                                                     PTD_GET_TOGGLE(ptd) ^ 1);
-                               urb->status = cc_to_error[TD_DATAUNDERRUN];
-                               spin_unlock(&urb->lock);
-                               continue;
+                               usb_settoggle(udev, ep->epnum,
+                                             ep->nextpid == USB_PID_OUT,
+                                             PTD_GET_TOGGLE(ptd));
+                               urb->actual_length += PTD_GET_COUNT(ptd);
+                               status = cc_to_error[TD_DATAUNDERRUN];
+                               goto done;
                        }
                }
-               /* Keep underrun error through the STATUS stage */
-               if (urb->status == cc_to_error[TD_DATAUNDERRUN])
-                       cc = TD_DATAUNDERRUN;
 
                if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED
                    && (++ep->error_count >= 3 || cc == TD_CC_STALL
                        || cc == TD_DATAOVERRUN)) {
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = cc_to_error[cc];
+                       status = cc_to_error[cc];
                        if (ep->nextpid == USB_PID_ACK)
                                ep->nextpid = 0;
-                       spin_unlock(&urb->lock);
-                       continue;
+                       goto done;
                }
                /* According to usb spec, zero-length Int transfer signals
                   finishing of the urb. Hey, does this apply only
                   for IN endpoints? */
                if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) {
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = 0;
-                       spin_unlock(&urb->lock);
-                       continue;
+                       status = 0;
+                       goto done;
                }
 
                /* Relax after previously failed, but later succeeded
@@ -392,8 +439,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                        /* All data for this URB is transferred, let's finish */
                        if (usb_pipecontrol(urb->pipe))
                                ep->nextpid = USB_PID_ACK;
-                       else if (urb->status == -EINPROGRESS)
-                               urb->status = 0;
+                       else
+                               status = 0;
                        break;
                case USB_PID_SETUP:
                        if (PTD_GET_ACTIVE(ptd)
@@ -413,69 +460,16 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                        if (PTD_GET_ACTIVE(ptd)
                            || (cc != TD_CC_NOERROR && cc < 0x0E))
                                break;
-                       if (urb->status == -EINPROGRESS)
-                               urb->status = 0;
+                       status = 0;
                        ep->nextpid = 0;
                        break;
                default:
-                       BUG_ON(1);
+                       BUG();
                }
-               spin_unlock(&urb->lock);
-       }
-}
-
-/*
-  Take done or failed requests out of schedule. Give back
-  processed urbs.
-*/
-static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
-                          struct urb *urb, struct pt_regs *regs)
-__releases(isp116x->lock) __acquires(isp116x->lock)
-{
-       unsigned i;
-
-       urb->hcpriv = NULL;
-       ep->error_count = 0;
-
-       if (usb_pipecontrol(urb->pipe))
-               ep->nextpid = USB_PID_SETUP;
-
-       urb_dbg(urb, "Finish");
-
-       spin_unlock(&isp116x->lock);
-       usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb, regs);
-       spin_lock(&isp116x->lock);
-
-       /* take idle endpoints out of the schedule */
-       if (!list_empty(&ep->hep->urb_list))
-               return;
-
-       /* async deschedule */
-       if (!list_empty(&ep->schedule)) {
-               list_del_init(&ep->schedule);
-               return;
-       }
-
-       /* periodic deschedule */
-       DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch);
-       for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) {
-               struct isp116x_ep *temp;
-               struct isp116x_ep **prev = &isp116x->periodic[i];
-
-               while (*prev && ((temp = *prev) != ep))
-                       prev = &temp->next;
-               if (*prev)
-                       *prev = ep->next;
-               isp116x->load[i] -= ep->load;
-       }
-       ep->branch = PERIODIC_SIZE;
-       isp116x_to_hcd(isp116x)->self.bandwidth_allocated -=
-           ep->load / ep->period;
 
-       /* switch irq type? */
-       if (!--isp116x->periodic_count) {
-               isp116x->irqenb &= ~HCuPINT_SOF;
-               isp116x->irqenb |= HCuPINT_ATL;
+ done:
+               if (status != -EINPROGRESS || urb->unlinked)
+                       finish_request(isp116x, ep, urb, status);
        }
 }
 
@@ -579,11 +573,8 @@ static void start_atl_transfers(struct isp116x *isp116x)
 /*
   Finish the processed transfers
 */
-static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs)
+static void finish_atl_transfers(struct isp116x *isp116x)
 {
-       struct isp116x_ep *ep;
-       struct urb *urb;
-
        if (!isp116x->atl_active)
                return;
        /* Fifo not ready? */
@@ -593,20 +584,10 @@ static void finish_atl_transfers(struct isp116x *isp116x, struct pt_regs *regs)
        atomic_inc(&isp116x->atl_finishing);
        unpack_fifo(isp116x);
        postproc_atl_queue(isp116x);
-       for (ep = isp116x->atl_active; ep; ep = ep->active) {
-               urb =
-                   container_of(ep->hep->urb_list.next, struct urb, urb_list);
-               /* USB_PID_ACK check here avoids finishing of
-                  control transfers, for which TD_DATAUNDERRUN
-                  occured, while URB_SHORT_NOT_OK was set */
-               if (urb && urb->status != -EINPROGRESS
-                   && ep->nextpid != USB_PID_ACK)
-                       finish_request(isp116x, ep, urb, regs);
-       }
        atomic_dec(&isp116x->atl_finishing);
 }
 
-static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
+static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        u16 irqstat;
@@ -619,28 +600,29 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 
        if (irqstat & (HCuPINT_ATL | HCuPINT_SOF)) {
                ret = IRQ_HANDLED;
-               finish_atl_transfers(isp116x, regs);
+               finish_atl_transfers(isp116x);
        }
 
        if (irqstat & HCuPINT_OPR) {
                u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
                isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
                if (intstat & HCINT_UE) {
-                       ERR("Unrecoverable error\n");
-                       /* What should we do here? Reset?  */
-               }
-               if (intstat & HCINT_RHSC) {
-                       isp116x->rhstatus =
-                           isp116x_read_reg32(isp116x, HCRHSTATUS);
-                       isp116x->rhport[0] =
-                           isp116x_read_reg32(isp116x, HCRHPORT1);
-                       isp116x->rhport[1] =
-                           isp116x_read_reg32(isp116x, HCRHPORT2);
+                       ERR("Unrecoverable error, HC is dead!\n");
+                       /* IRQ's are off, we do no DMA,
+                          perfectly ready to die ... */
+                       hcd->state = HC_STATE_HALT;
+                       ret = IRQ_HANDLED;
+                       goto done;
                }
+               if (intstat & HCINT_RHSC)
+                       /* When root hub or any of its ports is going
+                          to come out of suspend, it may take more
+                          than 10ms for status bits to stabilize. */
+                       mod_timer(&hcd->rh_timer, jiffies
+                                 + msecs_to_jiffies(20) + 1);
                if (intstat & HCINT_RD) {
                        DBG("---- remote wakeup\n");
-                       schedule_work(&isp116x->rh_resume);
-                       ret = IRQ_HANDLED;
+                       usb_hcd_resume_root_hub(hcd);
                }
                irqstat &= ~HCuPINT_OPR;
                ret = IRQ_HANDLED;
@@ -651,6 +633,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
        }
 
        isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+      done:
        spin_unlock(&isp116x->lock);
        return ret;
 }
@@ -694,8 +677,8 @@ static int balance(struct isp116x *isp116x, u16 period, u16 load)
 /*-----------------------------------------------------------------*/
 
 static int isp116x_urb_enqueue(struct usb_hcd *hcd,
-                              struct usb_host_endpoint *hep, struct urb *urb,
-                              unsigned mem_flags)
+                              struct urb *urb,
+                              gfp_t mem_flags)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        struct usb_device *udev = urb->dev;
@@ -703,6 +686,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
        int is_out = !usb_pipein(pipe);
        int type = usb_pipetype(pipe);
        int epnum = usb_pipeendpoint(pipe);
+       struct usb_host_endpoint *hep = urb->ep;
        struct isp116x_ep *ep = NULL;
        unsigned long flags;
        int i;
@@ -724,15 +708,21 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
 
        spin_lock_irqsave(&isp116x->lock, flags);
        if (!HC_IS_RUNNING(hcd->state)) {
+               kfree(ep);
                ret = -ENODEV;
-               goto fail;
+               goto fail_not_linked;
+       }
+       ret = usb_hcd_link_urb_to_ep(hcd, urb);
+       if (ret) {
+               kfree(ep);
+               goto fail_not_linked;
        }
 
        if (hep->hcpriv)
                ep = hep->hcpriv;
        else {
                INIT_LIST_HEAD(&ep->schedule);
-               ep->udev = usb_get_dev(udev);
+               ep->udev = udev;
                ep->epnum = epnum;
                ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out);
                usb_settoggle(udev, epnum, is_out, 0);
@@ -789,7 +779,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
                if (ep->branch < PERIODIC_SIZE)
                        break;
 
-               ret = ep->branch = balance(isp116x, ep->period, ep->load);
+               ep->branch = ret = balance(isp116x, ep->period, ep->load);
                if (ret < 0)
                        goto fail;
                ret = 0;
@@ -828,19 +818,13 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
                }
        }
 
-       /* in case of unlink-during-submit */
-       spin_lock(&urb->lock);
-       if (urb->status != -EINPROGRESS) {
-               spin_unlock(&urb->lock);
-               finish_request(isp116x, ep, urb, NULL);
-               ret = 0;
-               goto fail;
-       }
        urb->hcpriv = hep;
-       spin_unlock(&urb->lock);
        start_atl_transfers(isp116x);
 
       fail:
+       if (ret)
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+      fail_not_linked:
        spin_unlock_irqrestore(&isp116x->lock, flags);
        return ret;
 }
@@ -848,20 +832,21 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
 /*
    Dequeue URBs.
 */
-static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+               int status)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        struct usb_host_endpoint *hep;
        struct isp116x_ep *ep, *ep_act;
        unsigned long flags;
+       int rc;
 
        spin_lock_irqsave(&isp116x->lock, flags);
+       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (rc)
+               goto done;
+
        hep = urb->hcpriv;
-       /* URB already unlinked (or never linked)? */
-       if (!hep) {
-               spin_unlock_irqrestore(&isp116x->lock, flags);
-               return 0;
-       }
        ep = hep->hcpriv;
        WARN_ON(hep != ep->hep);
 
@@ -878,17 +863,17 @@ static int isp116x_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
                        }
 
        if (urb)
-               finish_request(isp116x, ep, urb, NULL);
-
+               finish_request(isp116x, ep, urb, status);
+ done:
        spin_unlock_irqrestore(&isp116x->lock, flags);
-       return 0;
+       return rc;
 }
 
 static void isp116x_endpoint_disable(struct usb_hcd *hcd,
                                     struct usb_host_endpoint *hep)
 {
        int i;
-       struct isp116x_ep *ep = hep->hcpriv;;
+       struct isp116x_ep *ep = hep->hcpriv;
 
        if (!ep)
                return;
@@ -897,9 +882,8 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
        for (i = 0; i < 100 && !list_empty(&hep->urb_list); i++)
                msleep(3);
        if (!list_empty(&hep->urb_list))
-               WARN("ep %p not empty?\n", ep);
+               WARNING("ep %p not empty?\n", ep);
 
-       usb_put_dev(ep->udev);
        kfree(ep);
        hep->hcpriv = NULL;
 }
@@ -916,8 +900,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
        return (int)fmnum;
 }
 
-/*----------------------------------------------------------------*/
-
 /*
   Adapted from ohci-hub.c. Currently we don't support autosuspend.
 */
@@ -925,28 +907,34 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        int ports, i, changed = 0;
+       unsigned long flags;
 
        if (!HC_IS_RUNNING(hcd->state))
                return -ESHUTDOWN;
 
-       ports = isp116x->rhdesca & RH_A_NDP;
+       /* Report no status change now, if we are scheduled to be
+          called later */
+       if (timer_pending(&hcd->rh_timer))
+               return 0;
 
-       /* init status */
+       ports = isp116x->rhdesca & RH_A_NDP;
+       spin_lock_irqsave(&isp116x->lock, flags);
+       isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
        if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC))
                buf[0] = changed = 1;
        else
                buf[0] = 0;
 
        for (i = 0; i < ports; i++) {
-               u32 status = isp116x->rhport[i];
+               u32 status = isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
 
                if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
                              | RH_PS_OCIC | RH_PS_PRSC)) {
                        changed = 1;
                        buf[0] |= 1 << (i + 1);
-                       continue;
                }
        }
+       spin_unlock_irqrestore(&isp116x->lock, flags);
        return changed;
 }
 
@@ -960,11 +948,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
        desc->bHubContrCurrent = 0;
        desc->bNbrPorts = (u8) (reg & 0x3);
        /* Power switching, device type, overcurrent. */
-       desc->wHubCharacteristics =
-           (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
+       desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
        desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
        /* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-       desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+       desc->bitmap[0] = 0;
        desc->bitmap[1] = ~0;
 }
 
@@ -1058,7 +1045,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
                DBG("GetPortStatus\n");
                if (!wIndex || wIndex > ports)
                        goto error;
-               tmp = isp116x->rhport[--wIndex];
+               spin_lock_irqsave(&isp116x->lock, flags);
+               tmp = isp116x_read_reg32(isp116x, (--wIndex) ? HCRHPORT2 : HCRHPORT1);
+               spin_unlock_irqrestore(&isp116x->lock, flags);
                *(__le32 *) buf = cpu_to_le32(tmp);
                DBG("GetPortStatus: port[%d]  %08x\n", wIndex + 1, tmp);
                break;
@@ -1107,8 +1096,6 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
                spin_lock_irqsave(&isp116x->lock, flags);
                isp116x_write_reg32(isp116x, wIndex
                                    ? HCRHPORT2 : HCRHPORT1, tmp);
-               isp116x->rhport[wIndex] =
-                   isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);
                spin_unlock_irqrestore(&isp116x->lock, flags);
                break;
        case SetPortFeature:
@@ -1122,24 +1109,22 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
                        spin_lock_irqsave(&isp116x->lock, flags);
                        isp116x_write_reg32(isp116x, wIndex
                                            ? HCRHPORT2 : HCRHPORT1, RH_PS_PSS);
+                       spin_unlock_irqrestore(&isp116x->lock, flags);
                        break;
                case USB_PORT_FEAT_POWER:
                        DBG("USB_PORT_FEAT_POWER\n");
                        spin_lock_irqsave(&isp116x->lock, flags);
                        isp116x_write_reg32(isp116x, wIndex
                                            ? HCRHPORT2 : HCRHPORT1, RH_PS_PPS);
+                       spin_unlock_irqrestore(&isp116x->lock, flags);
                        break;
                case USB_PORT_FEAT_RESET:
                        DBG("USB_PORT_FEAT_RESET\n");
                        root_port_reset(isp116x, wIndex);
-                       spin_lock_irqsave(&isp116x->lock, flags);
                        break;
                default:
                        goto error;
                }
-               isp116x->rhport[wIndex] =
-                   isp116x_read_reg32(isp116x, wIndex ? HCRHPORT2 : HCRHPORT1);
-               spin_unlock_irqrestore(&isp116x->lock, flags);
                break;
 
        default:
@@ -1151,145 +1136,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
        return ret;
 }
 
-#ifdef CONFIG_PM
-
-static int isp116x_hub_suspend(struct usb_hcd *hcd)
-{
-       struct isp116x *isp116x = hcd_to_isp116x(hcd);
-       unsigned long flags;
-       u32 val;
-       int ret = 0;
-
-       spin_lock_irqsave(&isp116x->lock, flags);
-
-       val = isp116x_read_reg32(isp116x, HCCONTROL);
-       switch (val & HCCONTROL_HCFS) {
-       case HCCONTROL_USB_OPER:
-               hcd->state = HC_STATE_QUIESCING;
-               val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
-               val |= HCCONTROL_USB_SUSPEND;
-               if (hcd->remote_wakeup)
-                       val |= HCCONTROL_RWE;
-               /* Wait for usb transfers to finish */
-               mdelay(2);
-               isp116x_write_reg32(isp116x, HCCONTROL, val);
-               hcd->state = HC_STATE_SUSPENDED;
-               /* Wait for devices to suspend */
-               mdelay(5);
-       case HCCONTROL_USB_SUSPEND:
-               break;
-       case HCCONTROL_USB_RESUME:
-               isp116x_write_reg32(isp116x, HCCONTROL,
-                                   (val & ~HCCONTROL_HCFS) |
-                                   HCCONTROL_USB_RESET);
-       case HCCONTROL_USB_RESET:
-               ret = -EBUSY;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       spin_unlock_irqrestore(&isp116x->lock, flags);
-       return ret;
-}
-
-static int isp116x_hub_resume(struct usb_hcd *hcd)
-{
-       struct isp116x *isp116x = hcd_to_isp116x(hcd);
-       u32 val;
-       int ret = -EINPROGRESS;
-
-       msleep(5);
-       spin_lock_irq(&isp116x->lock);
-
-       val = isp116x_read_reg32(isp116x, HCCONTROL);
-       switch (val & HCCONTROL_HCFS) {
-       case HCCONTROL_USB_SUSPEND:
-               val &= ~HCCONTROL_HCFS;
-               val |= HCCONTROL_USB_RESUME;
-               isp116x_write_reg32(isp116x, HCCONTROL, val);
-       case HCCONTROL_USB_RESUME:
-               break;
-       case HCCONTROL_USB_OPER:
-               /* Without setting power_state here the
-                  SUSPENDED state won't be removed from
-                  sysfs/usbN/power.state as a response to remote
-                  wakeup. Maybe in the future. */
-               hcd->self.root_hub->dev.power.power_state = PMSG_ON;
-               ret = 0;
-               break;
-       default:
-               ret = -EBUSY;
-       }
-
-       if (ret != -EINPROGRESS) {
-               spin_unlock_irq(&isp116x->lock);
-               return ret;
-       }
-
-       val = isp116x->rhdesca & RH_A_NDP;
-       while (val--) {
-               u32 stat =
-                   isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
-               /* force global, not selective, resume */
-               if (!(stat & RH_PS_PSS))
-                       continue;
-               DBG("%s: Resuming port %d\n", __func__, val);
-               isp116x_write_reg32(isp116x, RH_PS_POCI, val
-                                   ? HCRHPORT2 : HCRHPORT1);
-       }
-       spin_unlock_irq(&isp116x->lock);
-
-       hcd->state = HC_STATE_RESUMING;
-       mdelay(20);
-
-       /* Go operational */
-       spin_lock_irq(&isp116x->lock);
-       val = isp116x_read_reg32(isp116x, HCCONTROL);
-       isp116x_write_reg32(isp116x, HCCONTROL,
-                           (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
-       spin_unlock_irq(&isp116x->lock);
-       /* see analogous comment above */
-       hcd->self.root_hub->dev.power.power_state = PMSG_ON;
-       hcd->state = HC_STATE_RUNNING;
-
-       return 0;
-}
-
-static void isp116x_rh_resume(void *_hcd)
-{
-       struct usb_hcd *hcd = _hcd;
-
-       usb_resume_device(hcd->self.root_hub);
-}
-
-#else
-
-#define        isp116x_hub_suspend     NULL
-#define        isp116x_hub_resume      NULL
-
-static void isp116x_rh_resume(void *_hcd)
-{
-}
-
-#endif
-
 /*-----------------------------------------------------------------*/
 
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct isp116x *isp116x)
-{
-}
-
-static inline void remove_debug_file(struct isp116x *isp116x)
-{
-}
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#ifdef CONFIG_DEBUG_FS
 
 static void dump_irq(struct seq_file *s, char *label, u16 mask)
 {
@@ -1313,13 +1162,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
                   mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
 }
 
-static int proc_isp116x_show(struct seq_file *s, void *unused)
+static int isp116x_show_dbg(struct seq_file *s, void *unused)
 {
        struct isp116x *isp116x = s->private;
-       struct isp116x_ep *ep;
-       struct urb *urb;
-       unsigned i;
-       char *str;
 
        seq_printf(s, "%s\n%s version %s\n",
                   isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@@ -1335,105 +1180,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
        }
 
        spin_lock_irq(&isp116x->lock);
-
        dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
        dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
        dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
        dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
-
-       list_for_each_entry(ep, &isp116x->async, schedule) {
-
-               switch (ep->nextpid) {
-               case USB_PID_IN:
-                       str = "in";
-                       break;
-               case USB_PID_OUT:
-                       str = "out";
-                       break;
-               case USB_PID_SETUP:
-                       str = "setup";
-                       break;
-               case USB_PID_ACK:
-                       str = "status";
-                       break;
-               default:
-                       str = "?";
-                       break;
-               };
-               seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
-                          ep->epnum, str, ep->maxpacket);
-               list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
-                       seq_printf(s, "  urb%p, %d/%d\n", urb,
-                                  urb->actual_length,
-                                  urb->transfer_buffer_length);
-               }
-       }
-       if (!list_empty(&isp116x->async))
-               seq_printf(s, "\n");
-
-       seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
-
-       for (i = 0; i < PERIODIC_SIZE; i++) {
-               ep = isp116x->periodic[i];
-               if (!ep)
-                       continue;
-               seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
-
-               /* DUMB: prints shared entries multiple times */
-               do {
-                       seq_printf(s, "   %d/%p (%sdev%d ep%d%s max %d)\n",
-                                  ep->period, ep,
-                                  (ep->udev->speed ==
-                                   USB_SPEED_FULL) ? "" : "ls ",
-                                  ep->udev->devnum, ep->epnum,
-                                  (ep->epnum ==
-                                   0) ? "" : ((ep->nextpid ==
-                                               USB_PID_IN) ? "in" : "out"),
-                                  ep->maxpacket);
-                       ep = ep->next;
-               } while (ep);
-       }
+       isp116x_show_regs_seq(isp116x, s);
        spin_unlock_irq(&isp116x->lock);
        seq_printf(s, "\n");
 
        return 0;
 }
 
-static int proc_isp116x_open(struct inode *inode, struct file *file)
+static int isp116x_open_seq(struct inode *inode, struct file *file)
 {
-       return single_open(file, proc_isp116x_show, PDE(inode)->data);
+       return single_open(file, isp116x_show_dbg, inode->i_private);
 }
 
-static struct file_operations proc_ops = {
-       .open = proc_isp116x_open,
+static const struct file_operations isp116x_debug_fops = {
+       .open = isp116x_open_seq,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = single_release,
 };
 
-/* expect just one isp116x per system */
-static const char proc_filename[] = "driver/isp116x";
-
-static void create_debug_file(struct isp116x *isp116x)
+static int create_debug_file(struct isp116x *isp116x)
 {
-       struct proc_dir_entry *pde;
-
-       pde = create_proc_entry(proc_filename, 0, NULL);
-       if (pde == NULL)
-               return;
-
-       pde->proc_fops = &proc_ops;
-       pde->data = isp116x;
-       isp116x->pde = pde;
+       isp116x->dentry = debugfs_create_file(hcd_name,
+                                             S_IRUGO, NULL, isp116x,
+                                             &isp116x_debug_fops);
+       if (!isp116x->dentry)
+               return -ENOMEM;
+       return 0;
 }
 
 static void remove_debug_file(struct isp116x *isp116x)
 {
-       if (isp116x->pde)
-               remove_proc_entry(proc_filename, NULL);
+       debugfs_remove(isp116x->dentry);
 }
 
-#endif
+#else
+
+#define        create_debug_file(d)    0
+#define        remove_debug_file(d)    do{}while(0)
+
+#endif                         /* CONFIG_DEBUG_FS */
 
 /*-----------------------------------------------------------------*/
 
@@ -1468,7 +1258,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        unsigned long t;
        u16 clkrdy = 0;
-       int ret = 0, timeout = 15 /* ms */ ;
+       int ret, timeout = 15 /* ms */ ;
 
        ret = isp116x_sw_reset(isp116x);
        if (ret)
@@ -1484,7 +1274,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
                        break;
        }
        if (!clkrdy) {
-               ERR("Clock not ready after 20ms\n");
+               ERR("Clock not ready after %dms\n", timeout);
                /* After sw_reset the clock won't report to be ready, if
                   H_WAKEUP pin is high. */
                ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@@ -1536,6 +1326,9 @@ static int isp116x_start(struct usb_hcd *hcd)
                return -ENODEV;
        }
 
+       /* To be removed in future */
+       hcd->uses_new_polling = 1;
+
        isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
        isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
 
@@ -1571,7 +1364,8 @@ static int isp116x_start(struct usb_hcd *hcd)
 
        val = 0;
        if (board->remote_wakeup_enable) {
-               hcd->can_wakeup = 1;
+               if (!device_can_wakeup(hcd->self.controller))
+                       device_init_wakeup(hcd->self.controller, 1);
                val |= RH_HS_DRWE;
        }
        isp116x_write_reg32(isp116x, HCRHSTATUS, val);
@@ -1599,12 +1393,119 @@ static int isp116x_start(struct usb_hcd *hcd)
        isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
        isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
 
-       isp116x_show_regs(isp116x);
+       isp116x_show_regs_log(isp116x);
        spin_unlock_irqrestore(&isp116x->lock, flags);
        return 0;
 }
 
-/*-----------------------------------------------------------------*/
+#ifdef CONFIG_PM
+
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
+{
+       struct isp116x *isp116x = hcd_to_isp116x(hcd);
+       unsigned long flags;
+       u32 val;
+       int ret = 0;
+
+       spin_lock_irqsave(&isp116x->lock, flags);
+       val = isp116x_read_reg32(isp116x, HCCONTROL);
+
+       switch (val & HCCONTROL_HCFS) {
+       case HCCONTROL_USB_OPER:
+               spin_unlock_irqrestore(&isp116x->lock, flags);
+               val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+               val |= HCCONTROL_USB_SUSPEND;
+               if (hcd->self.root_hub->do_remote_wakeup)
+                       val |= HCCONTROL_RWE;
+               /* Wait for usb transfers to finish */
+               msleep(2);
+               spin_lock_irqsave(&isp116x->lock, flags);
+               isp116x_write_reg32(isp116x, HCCONTROL, val);
+               spin_unlock_irqrestore(&isp116x->lock, flags);
+               /* Wait for devices to suspend */
+               msleep(5);
+               break;
+       case HCCONTROL_USB_RESUME:
+               isp116x_write_reg32(isp116x, HCCONTROL,
+                                   (val & ~HCCONTROL_HCFS) |
+                                   HCCONTROL_USB_RESET);
+       case HCCONTROL_USB_RESET:
+               ret = -EBUSY;
+       default:                /* HCCONTROL_USB_SUSPEND */
+               spin_unlock_irqrestore(&isp116x->lock, flags);
+               break;
+       }
+
+       return ret;
+}
+
+static int isp116x_bus_resume(struct usb_hcd *hcd)
+{
+       struct isp116x *isp116x = hcd_to_isp116x(hcd);
+       u32 val;
+
+       msleep(5);
+       spin_lock_irq(&isp116x->lock);
+
+       val = isp116x_read_reg32(isp116x, HCCONTROL);
+       switch (val & HCCONTROL_HCFS) {
+       case HCCONTROL_USB_SUSPEND:
+               val &= ~HCCONTROL_HCFS;
+               val |= HCCONTROL_USB_RESUME;
+               isp116x_write_reg32(isp116x, HCCONTROL, val);
+       case HCCONTROL_USB_RESUME:
+               break;
+       case HCCONTROL_USB_OPER:
+               spin_unlock_irq(&isp116x->lock);
+               return 0;
+       default:
+               /* HCCONTROL_USB_RESET: this may happen, when during
+                  suspension the HC lost power. Reinitialize completely */
+               spin_unlock_irq(&isp116x->lock);
+               DBG("Chip has been reset while suspended. Reinit from scratch.\n");
+               isp116x_reset(hcd);
+               isp116x_start(hcd);
+               isp116x_hub_control(hcd, SetPortFeature,
+                                   USB_PORT_FEAT_POWER, 1, NULL, 0);
+               if ((isp116x->rhdesca & RH_A_NDP) == 2)
+                       isp116x_hub_control(hcd, SetPortFeature,
+                                           USB_PORT_FEAT_POWER, 2, NULL, 0);
+               return 0;
+       }
+
+       val = isp116x->rhdesca & RH_A_NDP;
+       while (val--) {
+               u32 stat =
+                   isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
+               /* force global, not selective, resume */
+               if (!(stat & RH_PS_PSS))
+                       continue;
+               DBG("%s: Resuming port %d\n", __func__, val);
+               isp116x_write_reg32(isp116x, RH_PS_POCI, val
+                                   ? HCRHPORT2 : HCRHPORT1);
+       }
+       spin_unlock_irq(&isp116x->lock);
+
+       hcd->state = HC_STATE_RESUMING;
+       msleep(20);
+
+       /* Go operational */
+       spin_lock_irq(&isp116x->lock);
+       val = isp116x_read_reg32(isp116x, HCCONTROL);
+       isp116x_write_reg32(isp116x, HCCONTROL,
+                           (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+       spin_unlock_irq(&isp116x->lock);
+       hcd->state = HC_STATE_RUNNING;
+
+       return 0;
+}
+
+#else
+
+#define        isp116x_bus_suspend     NULL
+#define        isp116x_bus_resume      NULL
+
+#endif
 
 static struct hc_driver isp116x_hc_driver = {
        .description = hcd_name,
@@ -1626,23 +1527,21 @@ static struct hc_driver isp116x_hc_driver = {
 
        .hub_status_data = isp116x_hub_status_data,
        .hub_control = isp116x_hub_control,
-       .hub_suspend = isp116x_hub_suspend,
-       .hub_resume = isp116x_hub_resume,
+       .bus_suspend = isp116x_bus_suspend,
+       .bus_resume = isp116x_bus_resume,
 };
 
 /*----------------------------------------------------------------*/
 
-static int __init_or_module isp116x_remove(struct device *dev)
+static int isp116x_remove(struct platform_device *pdev)
 {
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
        struct isp116x *isp116x;
-       struct platform_device *pdev;
        struct resource *res;
 
-       if(!hcd)
+       if (!hcd)
                return 0;
        isp116x = hcd_to_isp116x(hcd);
-       pdev = container_of(dev, struct platform_device, dev);
        remove_debug_file(isp116x);
        usb_remove_hcd(hcd);
 
@@ -1659,18 +1558,16 @@ static int __init_or_module isp116x_remove(struct device *dev)
 
 #define resource_len(r) (((r)->end - (r)->start) + 1)
 
-static int __init isp116x_probe(struct device *dev)
+static int __devinit isp116x_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
        struct isp116x *isp116x;
-       struct platform_device *pdev;
        struct resource *addr, *data;
        void __iomem *addr_reg;
        void __iomem *data_reg;
        int irq;
        int ret = 0;
 
-       pdev = container_of(dev, struct platform_device, dev);
        if (pdev->num_resources < 3) {
                ret = -ENODEV;
                goto err1;
@@ -1684,7 +1581,7 @@ static int __init isp116x_probe(struct device *dev)
                goto err1;
        }
 
-       if (dev->dma_mask) {
+       if (pdev->dev.dma_mask) {
                DBG("DMA not supported\n");
                ret = -EINVAL;
                goto err1;
@@ -1710,7 +1607,7 @@ static int __init isp116x_probe(struct device *dev)
        }
 
        /* allocate and initialize hcd */
-       hcd = usb_create_hcd(&isp116x_hc_driver, dev, dev->bus_id);
+       hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd) {
                ret = -ENOMEM;
                goto err5;
@@ -1722,8 +1619,7 @@ static int __init isp116x_probe(struct device *dev)
        isp116x->addr_reg = addr_reg;
        spin_lock_init(&isp116x->lock);
        INIT_LIST_HEAD(&isp116x->async);
-       INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd);
-       isp116x->board = dev->platform_data;
+       isp116x->board = pdev->dev.platform_data;
 
        if (!isp116x->board) {
                ERR("Platform data structure not initialized\n");
@@ -1738,13 +1634,20 @@ static int __init isp116x_probe(struct device *dev)
                goto err6;
        }
 
-       ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
-       if (ret != 0)
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+       if (ret)
                goto err6;
 
-       create_debug_file(isp116x);
+       ret = create_debug_file(isp116x);
+       if (ret) {
+               ERR("Couldn't create debugfs entry\n");
+               goto err7;
+       }
+
        return 0;
 
+      err7:
+       usb_remove_hcd(hcd);
       err6:
        usb_put_hcd(hcd);
       err5:
@@ -1764,45 +1667,19 @@ static int __init isp116x_probe(struct device *dev)
 /*
   Suspend of platform device
 */
-static int isp116x_suspend(struct device *dev, pm_message_t state, u32 phase)
+static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
 {
-       int ret = 0;
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-       VDBG("%s: state %x, phase %x\n", __func__, state, phase);
-
-       if (phase != SUSPEND_DISABLE && phase != SUSPEND_POWER_DOWN)
-               return 0;
-
-       ret = usb_suspend_device(hcd->self.root_hub, state);
-       if (!ret) {
-               dev->power.power_state = state;
-               INFO("%s suspended\n", hcd_name);
-       } else
-               ERR("%s suspend failed\n", hcd_name);
-
-       return ret;
+       VDBG("%s: state %x\n", __func__, state.event);
+       return 0;
 }
 
 /*
   Resume platform device
 */
-static int isp116x_resume(struct device *dev, u32 phase)
+static int isp116x_resume(struct platform_device *dev)
 {
-       int ret = 0;
-       struct usb_hcd *hcd = dev_get_drvdata(dev);
-
-       VDBG("%s:  state %x, phase %x\n", __func__, dev->power.power_state,
-            phase);
-       if (phase != RESUME_POWER_ON)
-               return 0;
-
-       ret = usb_resume_device(hcd->self.root_hub);
-       if (!ret) {
-               dev->power.power_state = PMSG_ON;
-               VDBG("%s resumed\n", (char *)hcd_name);
-       }
-       return ret;
+       VDBG("%s\n", __func__);
+       return 0;
 }
 
 #else
@@ -1812,13 +1689,18 @@ static int isp116x_resume(struct device *dev, u32 phase)
 
 #endif
 
-static struct device_driver isp116x_driver = {
-       .name = (char *)hcd_name,
-       .bus = &platform_bus_type,
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:isp116x-hcd");
+
+static struct platform_driver isp116x_driver = {
        .probe = isp116x_probe,
        .remove = isp116x_remove,
        .suspend = isp116x_suspend,
        .resume = isp116x_resume,
+       .driver = {
+               .name = (char *)hcd_name,
+               .owner  = THIS_MODULE,
+       },
 };
 
 /*-----------------------------------------------------------------*/
@@ -1829,14 +1711,14 @@ static int __init isp116x_init(void)
                return -ENODEV;
 
        INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);
-       return driver_register(&isp116x_driver);
+       return platform_driver_register(&isp116x_driver);
 }
 
 module_init(isp116x_init);
 
 static void __exit isp116x_cleanup(void)
 {
-       driver_unregister(&isp116x_driver);
+       platform_driver_unregister(&isp116x_driver);
 }
 
 module_exit(isp116x_cleanup);