aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/adm5120/files/drivers
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2007-11-08 12:28:27 +0000
committerGabor Juhos <juhosg@openwrt.org>2007-11-08 12:28:27 +0000
commit729f4259193979af5c442616e86c0bc25c4b7e7f (patch)
tree83cf38f5a7c5e5368f2329a53cf5213b0a264fcf /target/linux/adm5120/files/drivers
parenteaca6d017264a9501262d76f4d7b8ec494fee1d2 (diff)
downloadupstream-729f4259193979af5c442616e86c0bc25c4b7e7f.tar.gz
upstream-729f4259193979af5c442616e86c0bc25c4b7e7f.tar.bz2
upstream-729f4259193979af5c442616e86c0bc25c4b7e7f.zip
[adm5120] USB driver fixes
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9513 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/adm5120/files/drivers')
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c15
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c152
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c364
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c1
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c440
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120-q.c8
-rw-r--r--target/linux/adm5120/files/drivers/usb/host/adm5120.h53
7 files changed, 477 insertions, 556 deletions
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c
index 208416e03d..60f955279d 100644
--- a/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c
@@ -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,
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c
index fae5aa64fa..4dfd1f4fef 100644
--- a/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c
@@ -45,14 +45,14 @@
#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);
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c
index dc1a4a52d7..48e61e9880 100644
--- a/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c
@@ -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;
}
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c
index 3e9c2f0b92..fdacf7c113 100644
--- a/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c
@@ -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
index 0000000000..bd99776cc1
--- /dev/null
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c
@@ -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 */
+
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c
index 2eafecc4fa..a9e002e7d3 100644
--- a/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c
@@ -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;
}
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120.h b/target/linux/adm5120/files/drivers/usb/host/adm5120.h
index 370722547e..bdfdbc713c 100644
--- a/target/linux/adm5120/files/drivers/usb/host/adm5120.h
+++ b/target/linux/adm5120/files/drivers/usb/host/adm5120.h
@@ -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");
}