[adm5120] USB driver fixes
authorGabor Juhos <juhosg@openwrt.org>
Thu, 8 Nov 2007 12:28:27 +0000 (12:28 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Thu, 8 Nov 2007 12:28:27 +0000 (12:28 +0000)
SVN-Revision: 9513

target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c
target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c
target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c
target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c
target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c [new file with mode: 0644]
target/linux/adm5120/files/drivers/usb/host/adm5120-q.c
target/linux/adm5120/files/drivers/usb/host/adm5120.h

index 208416e03d3ce8502d045610f36d5224b4db25cf..60f955279df75313bef658e010acd34fec984a20 100644 (file)
@@ -163,14 +163,14 @@ static const struct hc_driver adm5120_hc_driver = {
        /*
         * scheduling support
         */
-       .get_frame_number =     admhc_get_frame,
+       .get_frame_number =     admhc_get_frame_number,
 
        /*
         * root hub support
         */
        .hub_status_data =      admhc_hub_status_data,
        .hub_control =          admhc_hub_control,
-       .hub_irq_enable =       admhc_rhsc_enable,
+       .hub_irq_enable =       admhc_hub_irq_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          admhc_bus_suspend,
        .bus_resume =           admhc_bus_resume,
@@ -201,8 +201,7 @@ static int usb_hcd_adm5120_remove(struct platform_device *pdev)
        return 0;
 }
 
-#if 0
-/* TODO */
+#ifdef CONFIG_PM
 static int usb_hcd_adm5120_suspend(struct platform_device *dev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(dev);
@@ -216,17 +215,17 @@ static int usb_hcd_adm5120_resume(struct platform_device *dev)
 
        return 0;
 }
-#endif
+#else
+#define usb_hcd_adm5120_suspend        NULL
+#define usb_hcd_adm5120_resume NULL
+#endif /* CONFIG_PM */
 
 static struct platform_driver usb_hcd_adm5120_driver = {
        .probe          = usb_hcd_adm5120_probe,
        .remove         = usb_hcd_adm5120_remove,
        .shutdown       = usb_hcd_platform_shutdown,
-#if 0
-       /* TODO */
        .suspend        = usb_hcd_adm5120_suspend,
        .resume         = usb_hcd_adm5120_resume,
-#endif
        .driver         = {
                .name   = "adm5120-hcd",
                .owner  = THIS_MODULE,
index fae5aa64fa3ee9cb95019bafe2ad2fdfba3ad22d..4dfd1f4fefc552863f034219f3eaefeaf364492f 100644 (file)
 #include "../core/hcd.h"
 #include "../core/hub.h"
 
-#define DRIVER_VERSION "v0.02"
+#define DRIVER_VERSION "v0.03"
 #define DRIVER_AUTHOR  "Gabor Juhos <juhosg at openwrt.org>"
 #define DRIVER_DESC    "ADMtek USB 1.1 Host Controller Driver"
 
 /*-------------------------------------------------------------------------*/
 
 #define ADMHC_VERBOSE_DEBUG    /* not always helpful */
-#undef LATE_ED_SCHEDULE
+#undef ADMHC_LOCK_DMA
 
 /* For initializing controller (mask in an HCFS mode too) */
 #define        OHCI_CONTROL_INIT       OHCI_CTRL_CBSR
@@ -73,9 +73,10 @@ static void admhc_dump(struct admhcd *ahcd, int verbose);
 static int admhc_init(struct admhcd *ahcd);
 static void admhc_stop(struct usb_hcd *hcd);
 
-#include "adm5120-hub.c"
 #include "adm5120-dbg.c"
 #include "adm5120-mem.c"
+#include "adm5120-pm.c"
+#include "adm5120-hub.c"
 #include "adm5120-q.c"
 
 /*-------------------------------------------------------------------------*/
@@ -92,7 +93,7 @@ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
        unsigned int    pipe = urb->pipe;
        int             td_cnt = 0;
        unsigned long   flags;
-       int             retval = 0;
+       int             ret = 0;
 
 #ifdef ADMHC_VERBOSE_DEBUG
        spin_lock_irqsave(&ahcd->lock, flags);
@@ -160,11 +161,11 @@ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
        spin_lock_irqsave(&ahcd->lock, flags);
        /* don't submit to a dead HC */
        if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
-               retval = -ENODEV;
+               ret = -ENODEV;
                goto fail;
        }
        if (!HC_IS_RUNNING(hcd->state)) {
-               retval = -ENODEV;
+               ret = -ENODEV;
                goto fail;
        }
 
@@ -174,7 +175,7 @@ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
                spin_unlock(&urb->lock);
                urb->hcpriv = urb_priv;
                finish_urb(ahcd, urb);
-               retval = 0;
+               ret = 0;
                goto fail;
        }
 
@@ -202,18 +203,18 @@ static int admhc_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *ep,
        list_add_tail(&urb_priv->pending, &ed->urb_pending);
 
        /* schedule the ED */
-       retval = ed_schedule(ahcd, ed);
+       ret = ed_schedule(ahcd, ed);
 
 fail0:
        spin_unlock(&urb->lock);
 fail:
-       if (retval) {
+       if (ret) {
                urb_priv = urb->hcpriv;
                urb_priv_free(ahcd, urb_priv);
        }
 
        spin_unlock_irqrestore(&ahcd->lock, flags);
-       return retval;
+       return ret;
 }
 
 /*
@@ -338,7 +339,7 @@ sanitize:
        return;
 }
 
-static int admhc_get_frame(struct usb_hcd *hcd)
+static int admhc_get_frame_number(struct usb_hcd *hcd)
 {
        struct admhcd *ahcd = hcd_to_admhcd(hcd);
 
@@ -364,8 +365,6 @@ admhc_shutdown(struct usb_hcd *hcd)
        admhc_intr_disable(ahcd, ADMHC_INTR_MIE);
        admhc_dma_disable(ahcd);
        admhc_usb_reset(ahcd);
-       /* flush the writes */
-       admhc_writel_flush(ahcd);
 }
 
 /*-------------------------------------------------------------------------*
@@ -509,7 +508,7 @@ static int admhc_run(struct admhcd *ahcd)
                        admhc_dbg(ahcd, "fminterval delta %d\n",
                                ahcd->fminterval - FI);
                ahcd->fminterval |=
-                       (FSLDP (ahcd->fminterval) << ADMHC_SFI_FSLDP_SHIFT);
+                       (FSLDP(ahcd->fminterval) << ADMHC_SFI_FSLDP_SHIFT);
                /* also: power/overcurrent flags in rhdesc */
        }
 
@@ -531,9 +530,6 @@ static int admhc_run(struct admhcd *ahcd)
        }
        admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control);
 
-       /* flush the writes */
-       admhc_writel_flush(ahcd);
-
        msleep(temp);
        temp = admhc_get_rhdesc(ahcd);
        if (!(temp & ADMHC_RH_NPS)) {
@@ -542,8 +538,6 @@ static int admhc_run(struct admhcd *ahcd)
                        admhc_writel(ahcd, ADMHC_PS_CPP,
                                &ahcd->regs->portstatus[temp]);
        }
-       /* flush those writes */
-       admhc_writel_flush(ahcd);
 
        /* 2msec timelimit here means no irqs/preempt */
        spin_lock_irq(&ahcd->lock);
@@ -585,9 +579,6 @@ retry:
 
        admhc_writel(ahcd, ADMHC_RH_NPS | ADMHC_RH_LPSC, &ahcd->regs->rhdesc);
 
-       /* flush those writes */
-       admhc_writel_flush(ahcd);
-
        /* start controller operations */
        ahcd->host_control = ADMHC_BUSS_OPER;
        admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control);
@@ -604,27 +595,8 @@ retry:
        }
 
        hcd->state = HC_STATE_RUNNING;
-
        ahcd->next_statechange = jiffies + STATECHANGE_DELAY;
 
-#if 0
-       /* FIXME: enabling DMA is always failed here for an unknown reason */
-       admhc_dma_enable(ahcd);
-
-       temp = 200;
-       while ((admhc_readl(ahcd, &ahcd->regs->host_control)
-                       & ADMHC_HC_DMAE) != ADMHC_HC_DMAE) {
-               if (--temp == 0) {
-                       spin_unlock_irq(&ahcd->lock);
-                       admhc_err(ahcd, "unable to enable DMA!\n");
-                       admhc_dump(ahcd, 1);
-                       return -1;
-               }
-               mdelay(1);
-       }
-
-#endif
-
        spin_unlock_irq(&ahcd->lock);
 
        mdelay(ADMHC_POTPGT);
@@ -650,7 +622,6 @@ static irqreturn_t admhc_irq(struct usb_hcd *hcd)
 
        ints &= admhc_readl(ahcd, &regs->int_enable);
 
-       spin_lock(&ahcd->lock);
        if (ints & ADMHC_INTR_FATI) {
                /* e.g. due to PCI Master/Target Abort */
                admhc_disable(ahcd);
@@ -700,7 +671,9 @@ static irqreturn_t admhc_irq(struct usb_hcd *hcd)
                if (HC_IS_RUNNING(hcd->state))
                        admhc_intr_disable(ahcd, ADMHC_INTR_TDC);
                admhc_vdbg(ahcd, "Transfer Descriptor Complete\n");
+               spin_lock(&ahcd->lock);
                admhc_td_complete(ahcd);
+               spin_unlock(&ahcd->lock);
                if (HC_IS_RUNNING(hcd->state))
                        admhc_intr_enable(ahcd, ADMHC_INTR_TDC);
        }
@@ -714,15 +687,15 @@ static irqreturn_t admhc_irq(struct usb_hcd *hcd)
                admhc_intr_ack(ahcd, ADMHC_INTR_SOFI);
                /* handle any pending ED removes */
                admhc_finish_unlinks(ahcd, admhc_frame_no(ahcd));
+               spin_lock(&ahcd->lock);
                admhc_sof_refill(ahcd);
+               spin_unlock(&ahcd->lock);
        }
 
        if (HC_IS_RUNNING(hcd->state)) {
                admhc_intr_ack(ahcd, ints);
                admhc_intr_enable(ahcd, ADMHC_INTR_MIE);
-               admhc_writel_flush(ahcd);
        }
-       spin_unlock(&ahcd->lock);
 
        return IRQ_HANDLED;
 }
@@ -750,87 +723,6 @@ static void admhc_stop(struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-/* must not be called from interrupt context */
-
-#ifdef CONFIG_PM
-
-static int admhc_restart(struct admhcd *ahcd)
-{
-       int temp;
-       int i;
-       struct urb_priv *priv;
-
-       /* mark any devices gone, so they do nothing till khubd disconnects.
-        * recycle any "live" eds/tds (and urbs) right away.
-        * later, khubd disconnect processing will recycle the other state,
-        * (either as disconnect/reconnect, or maybe someday as a reset).
-        */
-       spin_lock_irq(&ahcd->lock);
-       admhc_disable(ahcd);
-       usb_root_hub_lost_power(admhcd_to_hcd(ahcd)->self.root_hub);
-       if (!list_empty(&ahcd->pending))
-               admhc_dbg(ahcd, "abort schedule...\n");
-               list_for_each_entry(priv, &ahcd->pending, pending) {
-               struct urb      *urb = priv->td[0]->urb;
-               struct ed       *ed = priv->ed;
-
-               switch (ed->state) {
-               case ED_OPER:
-                       ed->state = ED_UNLINK;
-                       ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE);
-                       ed_deschedule (ahcd, ed);
-
-                       ed->ed_next = ahcd->ed_rm_list;
-                       ed->ed_prev = NULL;
-                       ahcd->ed_rm_list = ed;
-                       /* FALLTHROUGH */
-               case ED_UNLINK:
-                       break;
-               default:
-                       admhc_dbg(ahcd, "bogus ed %p state %d\n",
-                                       ed, ed->state);
-               }
-
-               spin_lock(&urb->lock);
-               urb->status = -ESHUTDOWN;
-               spin_unlock(&urb->lock);
-       }
-       finish_unlinks(ahcd, 0);
-       spin_unlock_irq(&ahcd->lock);
-
-       /* paranoia, in case that didn't work: */
-
-       /* empty the interrupt branches */
-       for (i = 0; i < NUM_INTS; i++) ahcd->load[i] = 0;
-       for (i = 0; i < NUM_INTS; i++) ahcd->hcca->int_table[i] = 0;
-
-       /* no EDs to remove */
-       ahcd->ed_rm_list = NULL;
-
-       /* empty control and bulk lists */
-       ahcd->ed_controltail = NULL;
-       ahcd->ed_bulktail    = NULL;
-
-       if ((temp = admhc_run(ahcd)) < 0) {
-               admhc_err(ahcd, "can't restart, %d\n", temp);
-               return temp;
-       } else {
-               /* here we "know" root ports should always stay powered,
-                * and that if we try to turn them back on the root hub
-                * will respond to CSC processing.
-                */
-               i = ahcd->num_ports;
-               while (i--)
-                       admhc_writel(ahcd, RH_PS_PSS,
-                               &ahcd->regs->portstatus[i]);
-               admhc_dbg(ahcd, "restart complete\n");
-       }
-       return 0;
-}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #ifdef CONFIG_MIPS_ADM5120
 #include "adm5120-drv.c"
 #define PLATFORM_DRIVER                usb_hcd_adm5120_driver
@@ -844,7 +736,7 @@ static int admhc_restart(struct admhcd *ahcd)
 
 static int __init admhc_hcd_mod_init(void)
 {
-       int retval = 0;
+       int ret = 0;
 
        if (usb_disabled())
                return -ENODEV;
@@ -854,18 +746,18 @@ static int __init admhc_hcd_mod_init(void)
                sizeof (struct ed), sizeof (struct td));
 
 #ifdef PLATFORM_DRIVER
-       retval = platform_driver_register(&PLATFORM_DRIVER);
-       if (retval < 0)
+       ret = platform_driver_register(&PLATFORM_DRIVER);
+       if (ret < 0)
                goto error_platform;
 #endif
 
-       return retval;
+       return ret;
 
 #ifdef PLATFORM_DRIVER
        platform_driver_unregister(&PLATFORM_DRIVER);
 error_platform:
 #endif
-       return retval;
+       return ret;
 }
 module_init(admhc_hcd_mod_init);
 
index dc1a4a52d724644bc47e1926485a63d365523750..48e61e9880d2001bdb71252c8db424eb5ccb5d40 100644 (file)
@@ -58,7 +58,7 @@
 /*-------------------------------------------------------------------------*/
 
 /* hcd->hub_irq_enable() */
-static void admhc_rhsc_enable(struct usb_hcd *hcd)
+static void admhc_hub_irq_enable(struct usb_hcd *hcd)
 {
        struct admhcd   *ahcd = hcd_to_admhcd(hcd);
 
@@ -69,360 +69,6 @@ static void admhc_rhsc_enable(struct usb_hcd *hcd)
        spin_unlock_irq(&ahcd->lock);
 }
 
-#define OHCI_SCHED_ENABLES \
-       (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
-
-#ifdef CONFIG_PM
-static int admhc_restart(struct admhcd *ahcd);
-
-static int admhc_rh_suspend(struct admhcd *ahcd, int autostop)
-__releases(ahcd->lock)
-__acquires(ahcd->lock)
-{
-       int                     status = 0;
-
-       ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
-       switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
-       case OHCI_USB_RESUME:
-               admhc_dbg(ahcd, "resume/suspend?\n");
-               ahcd->hc_control &= ~OHCI_CTRL_HCFS;
-               ahcd->hc_control |= OHCI_USB_RESET;
-               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
-               (void) admhc_readl(ahcd, &ahcd->regs->control);
-               /* FALL THROUGH */
-       case OHCI_USB_RESET:
-               status = -EBUSY;
-               admhc_dbg(ahcd, "needs reinit!\n");
-               goto done;
-       case OHCI_USB_SUSPEND:
-               if (!ahcd->autostop) {
-                       admhc_dbg(ahcd, "already suspended\n");
-                       goto done;
-               }
-       }
-       admhc_dbg(ahcd, "%s root hub\n",
-                       autostop ? "auto-stop" : "suspend");
-
-       /* First stop any processing */
-       if (!autostop && (ahcd->hc_control & OHCI_SCHED_ENABLES)) {
-               ahcd->hc_control &= ~OHCI_SCHED_ENABLES;
-               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
-               ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
-               admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->intrstatus);
-
-               /* sched disables take effect on the next frame,
-                * then the last WDH could take 6+ msec
-                */
-               admhc_dbg(ahcd, "stopping schedules ...\n");
-               ahcd->autostop = 0;
-               spin_unlock_irq (&ahcd->lock);
-               msleep (8);
-               spin_lock_irq (&ahcd->lock);
-       }
-       dl_done_list (ahcd);
-       finish_unlinks (ahcd, admhc_frame_no(ahcd));
-
-       /* maybe resume can wake root hub */
-       if (device_may_wakeup(&admhcd_to_hcd(ahcd)->self.root_hub->dev) ||
-                       autostop)
-               ahcd->hc_control |= OHCI_CTRL_RWE;
-       else {
-               admhc_writel(ahcd, OHCI_INTR_RHSC, &ahcd->regs->intrdisable);
-               ahcd->hc_control &= ~OHCI_CTRL_RWE;
-       }
-
-       /* Suspend hub ... this is the "global (to this bus) suspend" mode,
-        * which doesn't imply ports will first be individually suspended.
-        */
-       ahcd->hc_control &= ~OHCI_CTRL_HCFS;
-       ahcd->hc_control |= OHCI_USB_SUSPEND;
-       admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
-       (void) admhc_readl(ahcd, &ahcd->regs->control);
-
-       /* no resumes until devices finish suspending */
-       if (!autostop) {
-               ahcd->next_statechange = jiffies + msecs_to_jiffies (5);
-               ahcd->autostop = 0;
-       }
-
-done:
-       return status;
-}
-
-static inline struct ed *find_head(struct ed *ed)
-{
-       /* for bulk and control lists */
-       while (ed->ed_prev)
-               ed = ed->ed_prev;
-       return ed;
-}
-
-/* caller has locked the root hub */
-static int admhc_rh_resume(struct admhcd *ahcd)
-__releases(ahcd->lock)
-__acquires(ahcd->lock)
-{
-       struct usb_hcd          *hcd = admhcd_to_hcd (ahcd);
-       u32                     temp, enables;
-       int                     status = -EINPROGRESS;
-       int                     autostopped = ahcd->autostop;
-
-       ahcd->autostop = 0;
-       ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
-
-       if (ahcd->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-               /* this can happen after resuming a swsusp snapshot */
-               if (hcd->state == HC_STATE_RESUMING) {
-                       admhc_dbg(ahcd, "BIOS/SMM active, control %03x\n",
-                                       ahcd->hc_control);
-                       status = -EBUSY;
-               /* this happens when pmcore resumes HC then root */
-               } else {
-                       admhc_dbg(ahcd, "duplicate resume\n");
-                       status = 0;
-               }
-       } else switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
-       case OHCI_USB_SUSPEND:
-               ahcd->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
-               ahcd->hc_control |= OHCI_USB_RESUME;
-               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
-               (void) admhc_readl(ahcd, &ahcd->regs->control);
-               admhc_dbg(ahcd, "%s root hub\n",
-                               autostopped ? "auto-start" : "resume");
-               break;
-       case OHCI_USB_RESUME:
-               /* HCFS changes sometime after INTR_RD */
-               admhc_dbg(ahcd, "%swakeup root hub\n",
-                               autostopped ? "auto-" : "");
-               break;
-       case OHCI_USB_OPER:
-               /* this can happen after resuming a swsusp snapshot */
-               admhc_dbg(ahcd, "snapshot resume? reinit\n");
-               status = -EBUSY;
-               break;
-       default:                /* RESET, we lost power */
-               admhc_dbg(ahcd, "lost power\n");
-               status = -EBUSY;
-       }
-       if (status == -EBUSY) {
-               if (!autostopped) {
-                       spin_unlock_irq (&ahcd->lock);
-                       (void) ahcd_init (ahcd);
-                       status = admhc_restart (ahcd);
-                       spin_lock_irq (&ahcd->lock);
-               }
-               return status;
-       }
-       if (status != -EINPROGRESS)
-               return status;
-       if (autostopped)
-               goto skip_resume;
-       spin_unlock_irq (&ahcd->lock);
-
-       /* Some controllers (lucent erratum) need extra-long delays */
-       msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
-
-       temp = admhc_readl(ahcd, &ahcd->regs->control);
-       temp &= OHCI_CTRL_HCFS;
-       if (temp != OHCI_USB_RESUME) {
-               admhc_err (ahcd, "controller won't resume\n");
-               spin_lock_irq(&ahcd->lock);
-               return -EBUSY;
-       }
-
-       /* disable old schedule state, reinit from scratch */
-       admhc_writel(ahcd, 0, &ahcd->regs->ed_controlhead);
-       admhc_writel(ahcd, 0, &ahcd->regs->ed_controlcurrent);
-       admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkhead);
-       admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkcurrent);
-       admhc_writel(ahcd, 0, &ahcd->regs->ed_periodcurrent);
-       admhc_writel(ahcd, (u32) ahcd->hcca_dma, &ahcd->ahcd->regs->hcca);
-
-       /* Sometimes PCI D3 suspend trashes frame timings ... */
-       periodic_reinit(ahcd);
-
-       /* the following code is executed with ahcd->lock held and
-        * irqs disabled if and only if autostopped is true
-        */
-
-skip_resume:
-       /* interrupts might have been disabled */
-       admhc_writel(ahcd, OHCI_INTR_INIT, &ahcd->regs->int_enable);
-       if (ahcd->ed_rm_list)
-               admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->int_enable);
-
-       /* Then re-enable operations */
-       admhc_writel(ahcd, OHCI_USB_OPER, &ahcd->regs->control);
-       (void) admhc_readl(ahcd, &ahcd->regs->control);
-       if (!autostopped)
-               msleep (3);
-
-       temp = ahcd->hc_control;
-       temp &= OHCI_CTRL_RWC;
-       temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
-       ahcd->hc_control = temp;
-       admhc_writel(ahcd, temp, &ahcd->regs->control);
-       (void) admhc_readl(ahcd, &ahcd->regs->control);
-
-       /* TRSMRCY */
-       if (!autostopped) {
-               msleep (10);
-               spin_lock_irq (&ahcd->lock);
-       }
-       /* now ahcd->lock is always held and irqs are always disabled */
-
-       /* keep it alive for more than ~5x suspend + resume costs */
-       ahcd->next_statechange = jiffies + STATECHANGE_DELAY;
-
-       /* maybe turn schedules back on */
-       enables = 0;
-       temp = 0;
-       if (!ahcd->ed_rm_list) {
-               if (ahcd->ed_controltail) {
-                       admhc_writel(ahcd,
-                                       find_head (ahcd->ed_controltail)->dma,
-                                       &ahcd->regs->ed_controlhead);
-                       enables |= OHCI_CTRL_CLE;
-                       temp |= OHCI_CLF;
-               }
-               if (ahcd->ed_bulktail) {
-                       admhc_writel(ahcd, find_head (ahcd->ed_bulktail)->dma,
-                               &ahcd->regs->ed_bulkhead);
-                       enables |= OHCI_CTRL_BLE;
-                       temp |= OHCI_BLF;
-               }
-       }
-       if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs)
-               enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
-       if (enables) {
-               admhc_dbg(ahcd, "restarting schedules ... %08x\n", enables);
-               ahcd->hc_control |= enables;
-               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
-               if (temp)
-                       admhc_writel(ahcd, temp, &ahcd->regs->cmdstatus);
-               (void) admhc_readl(ahcd, &ahcd->regs->control);
-       }
-
-       return 0;
-}
-
-static int admhc_bus_suspend(struct usb_hcd *hcd)
-{
-       struct admhcd   *ahcd = hcd_to_admhcd(hcd);
-       int             rc;
-
-       spin_lock_irq(&ahcd->lock);
-
-       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
-               rc = -ESHUTDOWN;
-       else
-               rc = admhc_rh_suspend (ahcd, 0);
-       spin_unlock_irq(&ahcd->lock);
-       return rc;
-}
-
-static int admhc_bus_resume(struct usb_hcd *hcd)
-{
-       struct admhcd           *ahcd = hcd_to_admhcd(hcd);
-       int                     rc;
-
-       if (time_before(jiffies, ahcd->next_statechange))
-               msleep(5);
-
-       spin_lock_irq (&ahcd->lock);
-
-       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
-               rc = -ESHUTDOWN;
-       else
-               rc = admhc_rh_resume (ahcd);
-       spin_unlock_irq(&ahcd->lock);
-
-       /* poll until we know a device is connected or we autostop */
-       if (rc == 0)
-               usb_hcd_poll_rh_status(hcd);
-       return rc;
-}
-
-/* Carry out polling-, autostop-, and autoresume-related state changes */
-static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed,
-               int any_connected)
-{
-       int     poll_rh = 1;
-
-       switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
-
-       case OHCI_USB_OPER:
-               /* keep on polling until we know a device is connected
-                * and RHSC is enabled */
-               if (!ahcd->autostop) {
-                       if (any_connected ||
-                                       !device_may_wakeup(&admhcd_to_hcd(ahcd)
-                                               ->self.root_hub->dev)) {
-                               if (admhc_readl(ahcd, &ahcd->regs->int_enable) &
-                                               OHCI_INTR_RHSC)
-                                       poll_rh = 0;
-                       } else {
-                               ahcd->autostop = 1;
-                               ahcd->next_statechange = jiffies + HZ;
-                       }
-
-               /* if no devices have been attached for one second, autostop */
-               } else {
-                       if (changed || any_connected) {
-                               ahcd->autostop = 0;
-                               ahcd->next_statechange = jiffies +
-                                               STATECHANGE_DELAY;
-                       } else if (time_after_eq(jiffies,
-                                               ahcd->next_statechange)
-                                       && !ahcd->ed_rm_list
-                                       && !(ahcd->hc_control &
-                                               OHCI_SCHED_ENABLES)) {
-                               ahcd_rh_suspend(ahcd, 1);
-                       }
-               }
-               break;
-
-       /* if there is a port change, autostart or ask to be resumed */
-       case OHCI_USB_SUSPEND:
-       case OHCI_USB_RESUME:
-               if (changed) {
-                       if (ahcd->autostop)
-                               admhc_rh_resume(ahcd);
-                       else
-                               usb_hcd_resume_root_hub(admhcd_to_hcd(ahcd));
-               } else {
-                       /* everything is idle, no need for polling */
-                       poll_rh = 0;
-               }
-               break;
-       }
-       return poll_rh;
-}
-
-#else  /* CONFIG_PM */
-
-static inline int admhc_rh_resume(struct admhcd *ahcd)
-{
-       return 0;
-}
-
-/* Carry out polling-related state changes.
- * autostop isn't used when CONFIG_PM is turned off.
- */
-static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed,
-               int any_connected)
-{
-       int     poll_rh = 1;
-
-       /* keep on polling until RHSC is enabled */
-       if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM)
-               poll_rh = 0;
-
-       return poll_rh;
-}
-
-#endif /* CONFIG_PM */
-
 /*-------------------------------------------------------------------------*/
 
 /* build "status change" packet (one or two bytes) from HC registers */
@@ -647,7 +293,7 @@ static int admhc_hub_control (
        struct admhcd   *ahcd = hcd_to_admhcd(hcd);
        int             ports = hcd_to_bus (hcd)->root_hub->maxchild;
        u32             temp;
-       int             retval = 0;
+       int             ret = 0;
 
        if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
                return -ESHUTDOWN;
@@ -753,7 +399,7 @@ static int admhc_hub_control (
                                &ahcd->regs->portstatus[wIndex]);
                        break;
                case USB_PORT_FEAT_RESET:
-                       retval = root_port_reset(ahcd, wIndex);
+                       ret = root_port_reset(ahcd, wIndex);
                        break;
                default:
                        goto error;
@@ -763,8 +409,8 @@ static int admhc_hub_control (
        default:
 error:
                /* "protocol stall" on error */
-               retval = -EPIPE;
+               ret = -EPIPE;
        }
-       return retval;
+       return ret;
 }
 
index 3e9c2f0b92ac9bc08f2f2c9278a9abf17e6173d8..fdacf7c11312c3719d4a603016d32d928d95b5a5 100644 (file)
@@ -27,7 +27,6 @@ static void admhc_hcd_init(struct admhcd *ahcd)
 {
        ahcd->next_statechange = jiffies;
        spin_lock_init(&ahcd->lock);
-       spin_lock_init(&ahcd->dma_lock);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c
new file mode 100644 (file)
index 0000000..bd99776
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * This file is licenced under GPL
+ */
+
+#define OHCI_SCHED_ENABLES \
+       (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
+
+#ifdef CONFIG_PM
+static int admhc_restart(struct admhcd *ahcd);
+
+static int admhc_rh_suspend(struct admhcd *ahcd, int autostop)
+__releases(ahcd->lock)
+__acquires(ahcd->lock)
+{
+       int                     status = 0;
+
+       ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
+       switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
+       case OHCI_USB_RESUME:
+               admhc_dbg(ahcd, "resume/suspend?\n");
+               ahcd->hc_control &= ~OHCI_CTRL_HCFS;
+               ahcd->hc_control |= OHCI_USB_RESET;
+               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
+               (void) admhc_readl(ahcd, &ahcd->regs->control);
+               /* FALL THROUGH */
+       case OHCI_USB_RESET:
+               status = -EBUSY;
+               admhc_dbg(ahcd, "needs reinit!\n");
+               goto done;
+       case OHCI_USB_SUSPEND:
+               if (!ahcd->autostop) {
+                       admhc_dbg(ahcd, "already suspended\n");
+                       goto done;
+               }
+       }
+       admhc_dbg(ahcd, "%s root hub\n",
+                       autostop ? "auto-stop" : "suspend");
+
+       /* First stop any processing */
+       if (!autostop && (ahcd->hc_control & OHCI_SCHED_ENABLES)) {
+               ahcd->hc_control &= ~OHCI_SCHED_ENABLES;
+               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
+               ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
+               admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->intrstatus);
+
+               /* sched disables take effect on the next frame,
+                * then the last WDH could take 6+ msec
+                */
+               admhc_dbg(ahcd, "stopping schedules ...\n");
+               ahcd->autostop = 0;
+               spin_unlock_irq (&ahcd->lock);
+               msleep (8);
+               spin_lock_irq(&ahcd->lock);
+       }
+       dl_done_list (ahcd);
+       finish_unlinks (ahcd, admhc_frame_no(ahcd));
+
+       /* maybe resume can wake root hub */
+       if (device_may_wakeup(&admhcd_to_hcd(ahcd)->self.root_hub->dev) ||
+                       autostop)
+               ahcd->hc_control |= OHCI_CTRL_RWE;
+       else {
+               admhc_writel(ahcd, OHCI_INTR_RHSC, &ahcd->regs->intrdisable);
+               ahcd->hc_control &= ~OHCI_CTRL_RWE;
+       }
+
+       /* Suspend hub ... this is the "global (to this bus) suspend" mode,
+        * which doesn't imply ports will first be individually suspended.
+        */
+       ahcd->hc_control &= ~OHCI_CTRL_HCFS;
+       ahcd->hc_control |= OHCI_USB_SUSPEND;
+       admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
+       (void) admhc_readl(ahcd, &ahcd->regs->control);
+
+       /* no resumes until devices finish suspending */
+       if (!autostop) {
+               ahcd->next_statechange = jiffies + msecs_to_jiffies (5);
+               ahcd->autostop = 0;
+       }
+
+done:
+       return status;
+}
+
+static inline struct ed *find_head(struct ed *ed)
+{
+       /* for bulk and control lists */
+       while (ed->ed_prev)
+               ed = ed->ed_prev;
+       return ed;
+}
+
+/* caller has locked the root hub */
+static int admhc_rh_resume(struct admhcd *ahcd)
+__releases(ahcd->lock)
+__acquires(ahcd->lock)
+{
+       struct usb_hcd          *hcd = admhcd_to_hcd (ahcd);
+       u32                     temp, enables;
+       int                     status = -EINPROGRESS;
+       int                     autostopped = ahcd->autostop;
+
+       ahcd->autostop = 0;
+       ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
+
+       if (ahcd->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
+               /* this can happen after resuming a swsusp snapshot */
+               if (hcd->state == HC_STATE_RESUMING) {
+                       admhc_dbg(ahcd, "BIOS/SMM active, control %03x\n",
+                                       ahcd->hc_control);
+                       status = -EBUSY;
+               /* this happens when pmcore resumes HC then root */
+               } else {
+                       admhc_dbg(ahcd, "duplicate resume\n");
+                       status = 0;
+               }
+       } else switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
+       case OHCI_USB_SUSPEND:
+               ahcd->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
+               ahcd->hc_control |= OHCI_USB_RESUME;
+               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
+               (void) admhc_readl(ahcd, &ahcd->regs->control);
+               admhc_dbg(ahcd, "%s root hub\n",
+                               autostopped ? "auto-start" : "resume");
+               break;
+       case OHCI_USB_RESUME:
+               /* HCFS changes sometime after INTR_RD */
+               admhc_dbg(ahcd, "%swakeup root hub\n",
+                               autostopped ? "auto-" : "");
+               break;
+       case OHCI_USB_OPER:
+               /* this can happen after resuming a swsusp snapshot */
+               admhc_dbg(ahcd, "snapshot resume? reinit\n");
+               status = -EBUSY;
+               break;
+       default:                /* RESET, we lost power */
+               admhc_dbg(ahcd, "lost power\n");
+               status = -EBUSY;
+       }
+       if (status == -EBUSY) {
+               if (!autostopped) {
+                       spin_unlock_irq (&ahcd->lock);
+                       (void) ahcd_init (ahcd);
+                       status = admhc_restart (ahcd);
+                       spin_lock_irq(&ahcd->lock);
+               }
+               return status;
+       }
+       if (status != -EINPROGRESS)
+               return status;
+       if (autostopped)
+               goto skip_resume;
+       spin_unlock_irq (&ahcd->lock);
+
+       /* Some controllers (lucent erratum) need extra-long delays */
+       msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
+
+       temp = admhc_readl(ahcd, &ahcd->regs->control);
+       temp &= OHCI_CTRL_HCFS;
+       if (temp != OHCI_USB_RESUME) {
+               admhc_err (ahcd, "controller won't resume\n");
+               spin_lock_irq(&ahcd->lock);
+               return -EBUSY;
+       }
+
+       /* disable old schedule state, reinit from scratch */
+       admhc_writel(ahcd, 0, &ahcd->regs->ed_controlhead);
+       admhc_writel(ahcd, 0, &ahcd->regs->ed_controlcurrent);
+       admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkhead);
+       admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkcurrent);
+       admhc_writel(ahcd, 0, &ahcd->regs->ed_periodcurrent);
+       admhc_writel(ahcd, (u32) ahcd->hcca_dma, &ahcd->ahcd->regs->hcca);
+
+       /* Sometimes PCI D3 suspend trashes frame timings ... */
+       periodic_reinit(ahcd);
+
+       /* the following code is executed with ahcd->lock held and
+        * irqs disabled if and only if autostopped is true
+        */
+
+skip_resume:
+       /* interrupts might have been disabled */
+       admhc_writel(ahcd, OHCI_INTR_INIT, &ahcd->regs->int_enable);
+       if (ahcd->ed_rm_list)
+               admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->int_enable);
+
+       /* Then re-enable operations */
+       admhc_writel(ahcd, OHCI_USB_OPER, &ahcd->regs->control);
+       (void) admhc_readl(ahcd, &ahcd->regs->control);
+       if (!autostopped)
+               msleep (3);
+
+       temp = ahcd->hc_control;
+       temp &= OHCI_CTRL_RWC;
+       temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+       ahcd->hc_control = temp;
+       admhc_writel(ahcd, temp, &ahcd->regs->control);
+       (void) admhc_readl(ahcd, &ahcd->regs->control);
+
+       /* TRSMRCY */
+       if (!autostopped) {
+               msleep (10);
+               spin_lock_irq(&ahcd->lock);
+       }
+       /* now ahcd->lock is always held and irqs are always disabled */
+
+       /* keep it alive for more than ~5x suspend + resume costs */
+       ahcd->next_statechange = jiffies + STATECHANGE_DELAY;
+
+       /* maybe turn schedules back on */
+       enables = 0;
+       temp = 0;
+       if (!ahcd->ed_rm_list) {
+               if (ahcd->ed_controltail) {
+                       admhc_writel(ahcd,
+                                       find_head (ahcd->ed_controltail)->dma,
+                                       &ahcd->regs->ed_controlhead);
+                       enables |= OHCI_CTRL_CLE;
+                       temp |= OHCI_CLF;
+               }
+               if (ahcd->ed_bulktail) {
+                       admhc_writel(ahcd, find_head (ahcd->ed_bulktail)->dma,
+                               &ahcd->regs->ed_bulkhead);
+                       enables |= OHCI_CTRL_BLE;
+                       temp |= OHCI_BLF;
+               }
+       }
+       if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs)
+               enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
+       if (enables) {
+               admhc_dbg(ahcd, "restarting schedules ... %08x\n", enables);
+               ahcd->hc_control |= enables;
+               admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
+               if (temp)
+                       admhc_writel(ahcd, temp, &ahcd->regs->cmdstatus);
+               (void) admhc_readl(ahcd, &ahcd->regs->control);
+       }
+
+       return 0;
+}
+
+static int admhc_bus_suspend(struct usb_hcd *hcd)
+{
+       struct admhcd   *ahcd = hcd_to_admhcd(hcd);
+       int             rc;
+
+       spin_lock_irq(&ahcd->lock);
+
+       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+               rc = -ESHUTDOWN;
+       else
+               rc = admhc_rh_suspend(ahcd, 0);
+       spin_unlock_irq(&ahcd->lock);
+       return rc;
+}
+
+static int admhc_bus_resume(struct usb_hcd *hcd)
+{
+       struct admhcd           *ahcd = hcd_to_admhcd(hcd);
+       int                     rc;
+
+       if (time_before(jiffies, ahcd->next_statechange))
+               msleep(5);
+
+       spin_lock_irq(&ahcd->lock);
+
+       if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
+               rc = -ESHUTDOWN;
+       else
+               rc = admhc_rh_resume(ahcd);
+       spin_unlock_irq(&ahcd->lock);
+
+       /* poll until we know a device is connected or we autostop */
+       if (rc == 0)
+               usb_hcd_poll_rh_status(hcd);
+       return rc;
+}
+
+/* Carry out polling-, autostop-, and autoresume-related state changes */
+static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed,
+               int any_connected)
+{
+       int     poll_rh = 1;
+
+       switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
+
+       case OHCI_USB_OPER:
+               /* keep on polling until we know a device is connected
+                * and RHSC is enabled */
+               if (!ahcd->autostop) {
+                       if (any_connected ||
+                                       !device_may_wakeup(&admhcd_to_hcd(ahcd)
+                                               ->self.root_hub->dev)) {
+                               if (admhc_readl(ahcd, &ahcd->regs->int_enable) &
+                                               OHCI_INTR_RHSC)
+                                       poll_rh = 0;
+                       } else {
+                               ahcd->autostop = 1;
+                               ahcd->next_statechange = jiffies + HZ;
+                       }
+
+               /* if no devices have been attached for one second, autostop */
+               } else {
+                       if (changed || any_connected) {
+                               ahcd->autostop = 0;
+                               ahcd->next_statechange = jiffies +
+                                               STATECHANGE_DELAY;
+                       } else if (time_after_eq(jiffies,
+                                               ahcd->next_statechange)
+                                       && !ahcd->ed_rm_list
+                                       && !(ahcd->hc_control &
+                                               OHCI_SCHED_ENABLES)) {
+                               ahcd_rh_suspend(ahcd, 1);
+                       }
+               }
+               break;
+
+       /* if there is a port change, autostart or ask to be resumed */
+       case OHCI_USB_SUSPEND:
+       case OHCI_USB_RESUME:
+               if (changed) {
+                       if (ahcd->autostop)
+                               admhc_rh_resume(ahcd);
+                       else
+                               usb_hcd_resume_root_hub(admhcd_to_hcd(ahcd));
+               } else {
+                       /* everything is idle, no need for polling */
+                       poll_rh = 0;
+               }
+               break;
+       }
+       return poll_rh;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* must not be called from interrupt context */
+static int admhc_restart(struct admhcd *ahcd)
+{
+       int temp;
+       int i;
+       struct urb_priv *priv;
+
+       /* mark any devices gone, so they do nothing till khubd disconnects.
+        * recycle any "live" eds/tds (and urbs) right away.
+        * later, khubd disconnect processing will recycle the other state,
+        * (either as disconnect/reconnect, or maybe someday as a reset).
+        */
+       spin_lock_irq(&ahcd->lock);
+       admhc_disable(ahcd);
+       usb_root_hub_lost_power(admhcd_to_hcd(ahcd)->self.root_hub);
+       if (!list_empty(&ahcd->pending))
+               admhc_dbg(ahcd, "abort schedule...\n");
+               list_for_each_entry(priv, &ahcd->pending, pending) {
+               struct urb      *urb = priv->td[0]->urb;
+               struct ed       *ed = priv->ed;
+
+               switch (ed->state) {
+               case ED_OPER:
+                       ed->state = ED_UNLINK;
+                       ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE);
+                       ed_deschedule (ahcd, ed);
+
+                       ed->ed_next = ahcd->ed_rm_list;
+                       ed->ed_prev = NULL;
+                       ahcd->ed_rm_list = ed;
+                       /* FALLTHROUGH */
+               case ED_UNLINK:
+                       break;
+               default:
+                       admhc_dbg(ahcd, "bogus ed %p state %d\n",
+                                       ed, ed->state);
+               }
+
+               spin_lock(&urb->lock);
+               urb->status = -ESHUTDOWN;
+               spin_unlock(&urb->lock);
+       }
+       finish_unlinks(ahcd, 0);
+       spin_unlock_irq(&ahcd->lock);
+
+       /* paranoia, in case that didn't work: */
+
+       /* empty the interrupt branches */
+       for (i = 0; i < NUM_INTS; i++) ahcd->load[i] = 0;
+       for (i = 0; i < NUM_INTS; i++) ahcd->hcca->int_table[i] = 0;
+
+       /* no EDs to remove */
+       ahcd->ed_rm_list = NULL;
+
+       /* empty control and bulk lists */
+       ahcd->ed_controltail = NULL;
+       ahcd->ed_bulktail    = NULL;
+
+       if ((temp = admhc_run(ahcd)) < 0) {
+               admhc_err(ahcd, "can't restart, %d\n", temp);
+               return temp;
+       } else {
+               /* here we "know" root ports should always stay powered,
+                * and that if we try to turn them back on the root hub
+                * will respond to CSC processing.
+                */
+               i = ahcd->num_ports;
+               while (i--)
+                       admhc_writel(ahcd, RH_PS_PSS,
+                               &ahcd->regs->portstatus[i]);
+               admhc_dbg(ahcd, "restart complete\n");
+       }
+       return 0;
+}
+
+#else  /* CONFIG_PM */
+
+static inline int admhc_rh_resume(struct admhcd *ahcd)
+{
+       return 0;
+}
+
+/* Carry out polling-related state changes.
+ * autostop isn't used when CONFIG_PM is turned off.
+ */
+static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed,
+               int any_connected)
+{
+       int     poll_rh = 1;
+
+       /* keep on polling until RHSC is enabled */
+       if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM)
+               poll_rh = 0;
+
+       return poll_rh;
+}
+
+#endif /* CONFIG_PM */
+
index 2eafecc4fa309913bd9e9e984e0f55b7569a4168..a9e002e7d36e2dd6f1d5b3cc3568a8dba581d8e6 100644 (file)
@@ -153,7 +153,6 @@ static int ed_schedule(struct admhcd *ahcd, struct ed *ed)
 
        ed->state = ED_IDLE;
 
-       admhc_dma_lock(ahcd);
        ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP);
 
        old_tail = ahcd->ed_tails[ed->type];
@@ -169,7 +168,6 @@ static int ed_schedule(struct admhcd *ahcd, struct ed *ed)
        old_tail->hwNextED = cpu_to_hc32(ahcd, ed->dma);
 
        ahcd->ed_tails[ed->type] = ed;
-       admhc_dma_unlock(ahcd);
 
        admhc_intr_enable(ahcd, ADMHC_INTR_SOFI);
 
@@ -181,9 +179,7 @@ static void ed_deschedule(struct admhcd *ahcd, struct ed *ed)
        admhc_dump_ed(ahcd, "ED-DESCHED", ed, 0);
 
        /* remove this ED from the HC list */
-       admhc_dma_lock(ahcd);
        ed->ed_prev->hwNextED = ed->hwNextED;
-       admhc_dma_unlock(ahcd);
 
        /* and remove it from our list */
        ed->ed_prev->ed_next = ed->ed_next;
@@ -203,9 +199,7 @@ static void ed_start_deschedule(struct admhcd *ahcd, struct ed *ed)
 {
        admhc_dump_ed(ahcd, "ED-UNLINK", ed, 0);
 
-       admhc_dma_lock(ahcd);
        ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP);
-       admhc_dma_unlock(ahcd);
 
        ed->state = ED_UNLINK;
 
@@ -573,11 +567,9 @@ static int ed_next_urb(struct admhcd *ahcd, struct ed *ed)
 
        up->td[up->td_cnt-1]->hwNextTD = cpu_to_hc32(ahcd, ed->dummy->td_dma);
 
-       admhc_dma_lock(ahcd);
        carry = hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_C;
        ed->hwHeadP = cpu_to_hc32(ahcd, up->td[0]->td_dma | carry);
        ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP);
-       admhc_dma_unlock(ahcd);
 
        return 1;
 }
index 370722547e2f8a5b5d38c0c0fd2aa047d44873d4..bdfdbc713c13ac3e84780e5db7fcb43755d8038d 100644 (file)
@@ -369,8 +369,6 @@ struct urb_priv {
 
 struct admhcd {
        spinlock_t              lock;
-       spinlock_t              dma_lock;
-       u32                     dma_state;
 
        /*
         * I/O memory used to communicate with the HC (dma-consistent)
@@ -438,22 +436,6 @@ static inline struct usb_hcd *admhcd_to_hcd(const struct admhcd *ahcd)
 #define STUB_DEBUG_FILES
 #endif /* DEBUG */
 
-#if 0
-#define admhc_dbg(ahcd, fmt, args...) \
-       dev_dbg(admhcd_to_hcd(ahcd)->self.controller , fmt , ## args )
-#define admhc_err(ahcd, fmt, args...) \
-       dev_err(admhcd_to_hcd(ahcd)->self.controller , fmt , ## args )
-#define ahcd_info(ahcd, fmt, args...) \
-       dev_info(admhcd_to_hcd(ahcd)->self.controller , fmt , ## args )
-#define admhc_warn(ahcd, fmt, args...) \
-       dev_warn(admhcd_to_hcd(ahcd)->self.controller , fmt , ## args )
-
-#ifdef ADMHC_VERBOSE_DEBUG
-#      define admhc_vdbg admhc_dbg
-#else
-#      define admhc_vdbg(ahcd, fmt, args...) do { } while (0)
-#endif
-#else
 #define admhc_dbg(ahcd, fmt, args...) \
        printk(KERN_DEBUG "adm5120-hcd: " fmt , ## args )
 #define admhc_err(ahcd, fmt, args...) \
@@ -468,7 +450,6 @@ static inline struct usb_hcd *admhcd_to_hcd(const struct admhcd *ahcd)
 #else
 #      define admhc_vdbg(ahcd, fmt, args...) do { } while (0)
 #endif
-#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -564,14 +545,6 @@ static inline void admhc_writel(const struct admhcd *ahcd,
 #endif
 }
 
-static inline void admhc_writel_flush(const struct admhcd *ahcd)
-{
-#if 0  /* TODO: needed? */
-       (void) admhc_readl(ahcd, &ahcd->regs->control);
-#endif
-}
-
-
 /*-------------------------------------------------------------------------*/
 
 /* cpu to ahcd */
@@ -659,13 +632,12 @@ static inline void admhc_disable(struct admhcd *ahcd)
 }
 
 #define        FI                      0x2edf          /* 12000 bits per frame (-1) */
-#define        FSLDP(fi)               (0x7fff & ((6 * ((fi) - 210)) / 7))
+#define        FSLDP(fi)               (0x7fff & ((6 * ((fi) - 1200)) / 7))
 #define        FIT                     ADMHC_SFI_FIT
 #define LSTHRESH               0x628           /* lowspeed bit threshold */
 
 static inline void periodic_reinit(struct admhcd *ahcd)
 {
-       u32     fi = ahcd->fminterval & ADMHC_SFI_FI_MASK;
        u32     fit = admhc_readl(ahcd, &ahcd->regs->fminterval) & FIT;
 
        /* TODO: adjust FSLargestDataPacket value too? */
@@ -724,7 +696,7 @@ static inline void admhc_dma_enable(struct admhcd *ahcd)
 
        t |= ADMHC_HC_DMAE;
        admhc_writel(ahcd, t, &ahcd->regs->host_control);
-       admhc_dbg(ahcd,"DMA enabled\n");
+       admhc_vdbg(ahcd,"DMA enabled\n");
 }
 
 static inline void admhc_dma_disable(struct admhcd *ahcd)
@@ -737,24 +709,5 @@ static inline void admhc_dma_disable(struct admhcd *ahcd)
 
        t &= ~ADMHC_HC_DMAE;
        admhc_writel(ahcd, t, &ahcd->regs->host_control);
-       admhc_dbg(ahcd,"DMA disabled\n");
-}
-
-static inline void admhc_dma_lock(struct admhcd *ahcd)
-{
-       spin_lock(ahcd->dma_lock);
-
-       ahcd->dma_state = admhc_readl(ahcd, &ahcd->regs->host_control);
-       admhc_writel(ahcd, 0, &ahcd->regs->hosthead);
-       admhc_writel(ahcd, ahcd->dma_state & ~ADMHC_HC_DMAE,
-                               &ahcd->regs->host_control);
-       admhc_dbg(ahcd,"DMA locked\n");
-}
-
-static inline void admhc_dma_unlock(struct admhcd *ahcd)
-{
-       admhc_writel(ahcd, (u32)ahcd->ed_head->dma, &ahcd->regs->hosthead);
-       admhc_writel(ahcd, ahcd->dma_state, &ahcd->regs->host_control);
-       admhc_dbg(ahcd,"DMA unlocked\n");
-       spin_unlock(ahcd->dma_lock);
+       admhc_vdbg(ahcd,"DMA disabled\n");
 }