[adm5120] checkin a new, experimental USB driver
[15.05/openwrt.git] / target / linux / adm5120 / files / drivers / usb / host / adm5120-hub.c
1 /*
2  * OHCI HCD (Host Controller Driver) for USB.
3  *
4  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
5  * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
6  *
7  * This file is licenced under GPL
8  */
9
10 /*-------------------------------------------------------------------------*/
11
12 /*
13  * OHCI Root Hub ... the nonsharable stuff
14  */
15
16 #define dbg_port(hc,label,num,value) \
17         admhc_dbg(hc, \
18                 "%s port%d " \
19                 "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
20                 label, num, temp, \
21                 (temp & ADMHC_PS_PRSC) ? " PRSC" : "", \
22                 (temp & ADMHC_PS_OCIC) ? " OCIC" : "", \
23                 (temp & ADMHC_PS_PSSC) ? " PSSC" : "", \
24                 (temp & ADMHC_PS_PESC) ? " PESC" : "", \
25                 (temp & ADMHC_PS_CSC) ? " CSC" : "", \
26                 \
27                 (temp & ADMHC_PS_LSDA) ? " LSDA" : "", \
28                 (temp & ADMHC_PS_PPS) ? " PPS" : "", \
29                 (temp & ADMHC_PS_PRS) ? " PRS" : "", \
30                 (temp & ADMHC_PS_POCI) ? " POCI" : "", \
31                 (temp & ADMHC_PS_PSS) ? " PSS" : "", \
32                 \
33                 (temp & ADMHC_PS_PES) ? " PES" : "", \
34                 (temp & ADMHC_PS_CCS) ? " CCS" : "" \
35                 );
36
37 #define dbg_port_write(hc,label,num,value) \
38         admhc_dbg(hc, \
39                 "%s port%d " \
40                 "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
41                 label, num, temp, \
42                 (temp & ADMHC_PS_PRSC) ? " PRSC" : "", \
43                 (temp & ADMHC_PS_OCIC) ? " OCIC" : "", \
44                 (temp & ADMHC_PS_PSSC) ? " PSSC" : "", \
45                 (temp & ADMHC_PS_PESC) ? " PESC" : "", \
46                 (temp & ADMHC_PS_CSC) ? " CSC" : "", \
47                 \
48                 (temp & ADMHC_PS_CPP) ? " CPP" : "", \
49                 (temp & ADMHC_PS_SPP) ? " SPP" : "", \
50                 (temp & ADMHC_PS_SPR) ? " SPR" : "", \
51                 (temp & ADMHC_PS_CPS) ? " CPS" : "", \
52                 (temp & ADMHC_PS_SPS) ? " SPS" : "", \
53                 \
54                 (temp & ADMHC_PS_SPE) ? " SPE" : "", \
55                 (temp & ADMHC_PS_CPE) ? " CPE" : "" \
56                 );
57
58 /*-------------------------------------------------------------------------*/
59
60 /* hcd->hub_irq_enable() */
61 static void admhc_rhsc_enable(struct usb_hcd *hcd)
62 {
63         struct admhcd   *ahcd = hcd_to_admhcd(hcd);
64
65         spin_lock_irq(&ahcd->lock);
66         if (!ahcd->autostop)
67                 del_timer(&hcd->rh_timer);      /* Prevent next poll */
68         admhc_intr_enable(ahcd, ADMHC_INTR_INSM);
69         spin_unlock_irq(&ahcd->lock);
70 }
71
72 #define OHCI_SCHED_ENABLES \
73         (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
74
75 #ifdef  CONFIG_PM
76 static int admhc_restart(struct admhcd *ahcd);
77
78 static int admhc_rh_suspend(struct admhcd *ahcd, int autostop)
79 __releases(ahcd->lock)
80 __acquires(ahcd->lock)
81 {
82         int                     status = 0;
83
84         ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
85         switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
86         case OHCI_USB_RESUME:
87                 admhc_dbg(ahcd, "resume/suspend?\n");
88                 ahcd->hc_control &= ~OHCI_CTRL_HCFS;
89                 ahcd->hc_control |= OHCI_USB_RESET;
90                 admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
91                 (void) admhc_readl(ahcd, &ahcd->regs->control);
92                 /* FALL THROUGH */
93         case OHCI_USB_RESET:
94                 status = -EBUSY;
95                 admhc_dbg(ahcd, "needs reinit!\n");
96                 goto done;
97         case OHCI_USB_SUSPEND:
98                 if (!ahcd->autostop) {
99                         admhc_dbg(ahcd, "already suspended\n");
100                         goto done;
101                 }
102         }
103         admhc_dbg(ahcd, "%s root hub\n",
104                         autostop ? "auto-stop" : "suspend");
105
106         /* First stop any processing */
107         if (!autostop && (ahcd->hc_control & OHCI_SCHED_ENABLES)) {
108                 ahcd->hc_control &= ~OHCI_SCHED_ENABLES;
109                 admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
110                 ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
111                 admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->intrstatus);
112
113                 /* sched disables take effect on the next frame,
114                  * then the last WDH could take 6+ msec
115                  */
116                 admhc_dbg(ahcd, "stopping schedules ...\n");
117                 ahcd->autostop = 0;
118                 spin_unlock_irq (&ahcd->lock);
119                 msleep (8);
120                 spin_lock_irq (&ahcd->lock);
121         }
122         dl_done_list (ahcd);
123         finish_unlinks (ahcd, admhc_frame_no(ahcd));
124
125         /* maybe resume can wake root hub */
126         if (device_may_wakeup(&admhcd_to_hcd(ahcd)->self.root_hub->dev) ||
127                         autostop)
128                 ahcd->hc_control |= OHCI_CTRL_RWE;
129         else {
130                 admhc_writel(ahcd, OHCI_INTR_RHSC, &ahcd->regs->intrdisable);
131                 ahcd->hc_control &= ~OHCI_CTRL_RWE;
132         }
133
134         /* Suspend hub ... this is the "global (to this bus) suspend" mode,
135          * which doesn't imply ports will first be individually suspended.
136          */
137         ahcd->hc_control &= ~OHCI_CTRL_HCFS;
138         ahcd->hc_control |= OHCI_USB_SUSPEND;
139         admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
140         (void) admhc_readl(ahcd, &ahcd->regs->control);
141
142         /* no resumes until devices finish suspending */
143         if (!autostop) {
144                 ahcd->next_statechange = jiffies + msecs_to_jiffies (5);
145                 ahcd->autostop = 0;
146         }
147
148 done:
149         return status;
150 }
151
152 static inline struct ed *find_head(struct ed *ed)
153 {
154         /* for bulk and control lists */
155         while (ed->ed_prev)
156                 ed = ed->ed_prev;
157         return ed;
158 }
159
160 /* caller has locked the root hub */
161 static int admhc_rh_resume(struct admhcd *ahcd)
162 __releases(ahcd->lock)
163 __acquires(ahcd->lock)
164 {
165         struct usb_hcd          *hcd = admhcd_to_hcd (ahcd);
166         u32                     temp, enables;
167         int                     status = -EINPROGRESS;
168         int                     autostopped = ahcd->autostop;
169
170         ahcd->autostop = 0;
171         ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control);
172
173         if (ahcd->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
174                 /* this can happen after resuming a swsusp snapshot */
175                 if (hcd->state == HC_STATE_RESUMING) {
176                         admhc_dbg(ahcd, "BIOS/SMM active, control %03x\n",
177                                         ahcd->hc_control);
178                         status = -EBUSY;
179                 /* this happens when pmcore resumes HC then root */
180                 } else {
181                         admhc_dbg(ahcd, "duplicate resume\n");
182                         status = 0;
183                 }
184         } else switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
185         case OHCI_USB_SUSPEND:
186                 ahcd->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
187                 ahcd->hc_control |= OHCI_USB_RESUME;
188                 admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
189                 (void) admhc_readl(ahcd, &ahcd->regs->control);
190                 admhc_dbg(ahcd, "%s root hub\n",
191                                 autostopped ? "auto-start" : "resume");
192                 break;
193         case OHCI_USB_RESUME:
194                 /* HCFS changes sometime after INTR_RD */
195                 admhc_dbg(ahcd, "%swakeup root hub\n",
196                                 autostopped ? "auto-" : "");
197                 break;
198         case OHCI_USB_OPER:
199                 /* this can happen after resuming a swsusp snapshot */
200                 admhc_dbg(ahcd, "snapshot resume? reinit\n");
201                 status = -EBUSY;
202                 break;
203         default:                /* RESET, we lost power */
204                 admhc_dbg(ahcd, "lost power\n");
205                 status = -EBUSY;
206         }
207         if (status == -EBUSY) {
208                 if (!autostopped) {
209                         spin_unlock_irq (&ahcd->lock);
210                         (void) ahcd_init (ahcd);
211                         status = admhc_restart (ahcd);
212                         spin_lock_irq (&ahcd->lock);
213                 }
214                 return status;
215         }
216         if (status != -EINPROGRESS)
217                 return status;
218         if (autostopped)
219                 goto skip_resume;
220         spin_unlock_irq (&ahcd->lock);
221
222         /* Some controllers (lucent erratum) need extra-long delays */
223         msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
224
225         temp = admhc_readl(ahcd, &ahcd->regs->control);
226         temp &= OHCI_CTRL_HCFS;
227         if (temp != OHCI_USB_RESUME) {
228                 admhc_err (ahcd, "controller won't resume\n");
229                 spin_lock_irq(&ahcd->lock);
230                 return -EBUSY;
231         }
232
233         /* disable old schedule state, reinit from scratch */
234         admhc_writel(ahcd, 0, &ahcd->regs->ed_controlhead);
235         admhc_writel(ahcd, 0, &ahcd->regs->ed_controlcurrent);
236         admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkhead);
237         admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkcurrent);
238         admhc_writel(ahcd, 0, &ahcd->regs->ed_periodcurrent);
239         admhc_writel(ahcd, (u32) ahcd->hcca_dma, &ahcd->ahcd->regs->hcca);
240
241         /* Sometimes PCI D3 suspend trashes frame timings ... */
242         periodic_reinit(ahcd);
243
244         /* the following code is executed with ahcd->lock held and
245          * irqs disabled if and only if autostopped is true
246          */
247
248 skip_resume:
249         /* interrupts might have been disabled */
250         admhc_writel(ahcd, OHCI_INTR_INIT, &ahcd->regs->int_enable);
251         if (ahcd->ed_rm_list)
252                 admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->int_enable);
253
254         /* Then re-enable operations */
255         admhc_writel(ahcd, OHCI_USB_OPER, &ahcd->regs->control);
256         (void) admhc_readl(ahcd, &ahcd->regs->control);
257         if (!autostopped)
258                 msleep (3);
259
260         temp = ahcd->hc_control;
261         temp &= OHCI_CTRL_RWC;
262         temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
263         ahcd->hc_control = temp;
264         admhc_writel(ahcd, temp, &ahcd->regs->control);
265         (void) admhc_readl(ahcd, &ahcd->regs->control);
266
267         /* TRSMRCY */
268         if (!autostopped) {
269                 msleep (10);
270                 spin_lock_irq (&ahcd->lock);
271         }
272         /* now ahcd->lock is always held and irqs are always disabled */
273
274         /* keep it alive for more than ~5x suspend + resume costs */
275         ahcd->next_statechange = jiffies + STATECHANGE_DELAY;
276
277         /* maybe turn schedules back on */
278         enables = 0;
279         temp = 0;
280         if (!ahcd->ed_rm_list) {
281                 if (ahcd->ed_controltail) {
282                         admhc_writel(ahcd,
283                                         find_head (ahcd->ed_controltail)->dma,
284                                         &ahcd->regs->ed_controlhead);
285                         enables |= OHCI_CTRL_CLE;
286                         temp |= OHCI_CLF;
287                 }
288                 if (ahcd->ed_bulktail) {
289                         admhc_writel(ahcd, find_head (ahcd->ed_bulktail)->dma,
290                                 &ahcd->regs->ed_bulkhead);
291                         enables |= OHCI_CTRL_BLE;
292                         temp |= OHCI_BLF;
293                 }
294         }
295         if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs)
296                 enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
297         if (enables) {
298                 admhc_dbg(ahcd, "restarting schedules ... %08x\n", enables);
299                 ahcd->hc_control |= enables;
300                 admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control);
301                 if (temp)
302                         admhc_writel(ahcd, temp, &ahcd->regs->cmdstatus);
303                 (void) admhc_readl(ahcd, &ahcd->regs->control);
304         }
305
306         return 0;
307 }
308
309 static int admhc_bus_suspend(struct usb_hcd *hcd)
310 {
311         struct admhcd   *ahcd = hcd_to_admhcd(hcd);
312         int             rc;
313
314         spin_lock_irq(&ahcd->lock);
315
316         if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
317                 rc = -ESHUTDOWN;
318         else
319                 rc = admhc_rh_suspend (ahcd, 0);
320         spin_unlock_irq(&ahcd->lock);
321         return rc;
322 }
323
324 static int admhc_bus_resume(struct usb_hcd *hcd)
325 {
326         struct admhcd           *ahcd = hcd_to_admhcd(hcd);
327         int                     rc;
328
329         if (time_before(jiffies, ahcd->next_statechange))
330                 msleep(5);
331
332         spin_lock_irq (&ahcd->lock);
333
334         if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
335                 rc = -ESHUTDOWN;
336         else
337                 rc = admhc_rh_resume (ahcd);
338         spin_unlock_irq(&ahcd->lock);
339
340         /* poll until we know a device is connected or we autostop */
341         if (rc == 0)
342                 usb_hcd_poll_rh_status(hcd);
343         return rc;
344 }
345
346 /* Carry out polling-, autostop-, and autoresume-related state changes */
347 static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed,
348                 int any_connected)
349 {
350         int     poll_rh = 1;
351
352         switch (ahcd->hc_control & OHCI_CTRL_HCFS) {
353
354         case OHCI_USB_OPER:
355                 /* keep on polling until we know a device is connected
356                  * and RHSC is enabled */
357                 if (!ahcd->autostop) {
358                         if (any_connected ||
359                                         !device_may_wakeup(&admhcd_to_hcd(ahcd)
360                                                 ->self.root_hub->dev)) {
361                                 if (admhc_readl(ahcd, &ahcd->regs->int_enable) &
362                                                 OHCI_INTR_RHSC)
363                                         poll_rh = 0;
364                         } else {
365                                 ahcd->autostop = 1;
366                                 ahcd->next_statechange = jiffies + HZ;
367                         }
368
369                 /* if no devices have been attached for one second, autostop */
370                 } else {
371                         if (changed || any_connected) {
372                                 ahcd->autostop = 0;
373                                 ahcd->next_statechange = jiffies +
374                                                 STATECHANGE_DELAY;
375                         } else if (time_after_eq(jiffies,
376                                                 ahcd->next_statechange)
377                                         && !ahcd->ed_rm_list
378                                         && !(ahcd->hc_control &
379                                                 OHCI_SCHED_ENABLES)) {
380                                 ahcd_rh_suspend(ahcd, 1);
381                         }
382                 }
383                 break;
384
385         /* if there is a port change, autostart or ask to be resumed */
386         case OHCI_USB_SUSPEND:
387         case OHCI_USB_RESUME:
388                 if (changed) {
389                         if (ahcd->autostop)
390                                 admhc_rh_resume(ahcd);
391                         else
392                                 usb_hcd_resume_root_hub(admhcd_to_hcd(ahcd));
393                 } else {
394                         /* everything is idle, no need for polling */
395                         poll_rh = 0;
396                 }
397                 break;
398         }
399         return poll_rh;
400 }
401
402 #else   /* CONFIG_PM */
403
404 static inline int admhc_rh_resume(struct admhcd *ahcd)
405 {
406         return 0;
407 }
408
409 /* Carry out polling-related state changes.
410  * autostop isn't used when CONFIG_PM is turned off.
411  */
412 static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed,
413                 int any_connected)
414 {
415         int     poll_rh = 1;
416
417         /* keep on polling until RHSC is enabled */
418         if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM)
419                 poll_rh = 0;
420
421         return poll_rh;
422 }
423
424 #endif  /* CONFIG_PM */
425
426 /*-------------------------------------------------------------------------*/
427
428 /* build "status change" packet (one or two bytes) from HC registers */
429
430 static int
431 admhc_hub_status_data(struct usb_hcd *hcd, char *buf)
432 {
433         struct admhcd   *ahcd = hcd_to_admhcd(hcd);
434         int             i, changed = 0, length = 1;
435         int             any_connected = 0;
436         unsigned long   flags;
437         u32             status;
438
439         spin_lock_irqsave(&ahcd->lock, flags);
440         if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
441                 goto done;
442
443         /* init status */
444         status = admhc_get_rhdesc(ahcd);
445         if (status & (ADMHC_RH_LPSC | ADMHC_RH_OCIC))
446                 buf [0] = changed = 1;
447         else
448                 buf [0] = 0;
449         if (ahcd->num_ports > 7) {
450                 buf [1] = 0;
451                 length++;
452         }
453
454         /* look at each port */
455         for (i = 0; i < ahcd->num_ports; i++) {
456                 status = admhc_get_portstatus(ahcd, i);
457
458                 /* can't autostop if ports are connected */
459                 any_connected |= (status & ADMHC_PS_CCS);
460
461                 if (status & (ADMHC_PS_CSC | ADMHC_PS_PESC | ADMHC_PS_PSSC
462                                 | ADMHC_PS_OCIC | ADMHC_PS_PRSC)) {
463                         changed = 1;
464                         if (i < 7)
465                             buf [0] |= 1 << (i + 1);
466                         else
467                             buf [1] |= 1 << (i - 7);
468                 }
469         }
470
471         hcd->poll_rh = admhc_root_hub_state_changes(ahcd, changed,
472                         any_connected);
473
474 done:
475         spin_unlock_irqrestore(&ahcd->lock, flags);
476
477         return changed ? length : 0;
478 }
479
480 /*-------------------------------------------------------------------------*/
481
482 static void admhc_hub_descriptor(struct admhcd *ahcd,
483                 struct usb_hub_descriptor *desc)
484 {
485         u32             rh = admhc_get_rhdesc(ahcd);
486         u16             temp;
487
488         desc->bDescriptorType = USB_DT_HUB;     /* Hub-descriptor */
489         desc->bPwrOn2PwrGood = ADMHC_POTPGT/2;  /* use default value */
490         desc->bHubContrCurrent = 0x00;  /* 0mA */
491
492         desc->bNbrPorts = ahcd->num_ports;
493         temp = 1 + (ahcd->num_ports / 8);
494         desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp;
495
496         /* FIXME */
497         temp = 0;
498         if (rh & ADMHC_RH_NPS)          /* no power switching? */
499             temp |= 0x0002;
500         if (rh & ADMHC_RH_PSM)          /* per-port power switching? */
501             temp |= 0x0001;
502         if (rh & ADMHC_RH_NOCP)         /* no overcurrent reporting? */
503             temp |= 0x0010;
504         else if (rh & ADMHC_RH_OCPM)    /* per-port overcurrent reporting? */
505             temp |= 0x0008;
506         desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ahcd, temp);
507
508         /* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
509         desc->bitmap [0] = 0;
510         desc->bitmap [0] = ~0;
511 }
512
513 /*-------------------------------------------------------------------------*/
514
515 #ifdef  CONFIG_USB_OTG
516
517 static int admhc_start_port_reset(struct usb_hcd *hcd, unsigned port)
518 {
519         struct admhcd   *ahcd = hcd_to_admhcd(hcd);
520         u32                     status;
521
522         if (!port)
523                 return -EINVAL;
524         port--;
525
526         /* start port reset before HNP protocol times out */
527         status = admhc_readl(ahcd, &ahcd->regs->portstatus[port]);
528         if (!(status & ADMHC_PS_CCS))
529                 return -ENODEV;
530
531         /* khubd will finish the reset later */
532         admhc_writel(ahcd, ADMHC_PS_PRS, &ahcd->regs->portstatus[port]);
533         return 0;
534 }
535
536 static void start_hnp(struct admhcd *ahcd);
537
538 #else
539
540 #define admhc_start_port_reset          NULL
541
542 #endif
543
544 /*-------------------------------------------------------------------------*/
545
546
547 /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
548  * not necessarily continuous ... to guard against resume signaling.
549  * The short timeout is safe for non-root hubs, and is backward-compatible
550  * with earlier Linux hosts.
551  */
552 #ifdef  CONFIG_USB_SUSPEND
553 #define PORT_RESET_MSEC         50
554 #else
555 #define PORT_RESET_MSEC         10
556 #endif
557
558 /* this timer value might be vendor-specific ... */
559 #define PORT_RESET_HW_MSEC      10
560
561 /* wrap-aware logic morphed from <linux/jiffies.h> */
562 #define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
563
564 /* called from some task, normally khubd */
565 static inline int root_port_reset(struct admhcd *ahcd, unsigned port)
566 {
567 #if 0
568         /* FIXME: revert to this when frame numbers are updated */
569         __hc32 __iomem *portstat = &ahcd->regs->portstatus[port];
570         u32     temp;
571         u16     now = admhc_readl(ahcd, &ahcd->regs->fmnumber);
572         u16     reset_done = now + PORT_RESET_MSEC;
573
574         /* build a "continuous enough" reset signal, with up to
575          * 3msec gap between pulses.  scheduler HZ==100 must work;
576          * this might need to be deadline-scheduled.
577          */
578         do {
579                 /* spin until any current reset finishes */
580                 for (;;) {
581                         temp = admhc_readl(ahcd, portstat);
582                         /* handle e.g. CardBus eject */
583                         if (temp == ~(u32)0)
584                                 return -ESHUTDOWN;
585                         if (!(temp & ADMHC_PS_PRS))
586                                 break;
587                         udelay (500);
588                 }
589
590                 if (!(temp & ADMHC_PS_CCS))
591                         break;
592                 if (temp & ADMHC_PS_PRSC)
593                         admhc_writel(ahcd, ADMHC_PS_PRSC, portstat);
594
595                 /* start the next reset, sleep till it's probably done */
596                 admhc_writel(ahcd, ADMHC_PS_PRS, portstat);
597                 msleep(PORT_RESET_HW_MSEC);
598                 now = admhc_readl(ahcd, &ahcd->regs->fmnumber);
599         } while (tick_before(now, reset_done));
600         /* caller synchronizes using PRSC */
601 #else
602         __hc32 __iomem *portstat = &ahcd->regs->portstatus[port];
603         u32     temp;
604         unsigned long   reset_done = jiffies + msecs_to_jiffies(PORT_RESET_MSEC);
605
606         /* build a "continuous enough" reset signal, with up to
607          * 3msec gap between pulses.  scheduler HZ==100 must work;
608          * this might need to be deadline-scheduled.
609          */
610         do {
611                 /* spin until any current reset finishes */
612                 for (;;) {
613                         temp = admhc_readl(ahcd, portstat);
614                         /* handle e.g. CardBus eject */
615                         if (temp == ~(u32)0)
616                                 return -ESHUTDOWN;
617                         if (!(temp & ADMHC_PS_PRS))
618                                 break;
619                         udelay (500);
620                 }
621
622                 if (!(temp & ADMHC_PS_CCS))
623                         break;
624
625                 if (temp & ADMHC_PS_PRSC)
626                         admhc_writel(ahcd, ADMHC_PS_PRSC, portstat);
627
628                 /* start the next reset, sleep till it's probably done */
629                 admhc_writel(ahcd, ADMHC_PS_PRS, portstat);
630                 msleep(PORT_RESET_HW_MSEC);
631         } while (time_before(jiffies, reset_done));
632
633         admhc_writel(ahcd, ADMHC_PS_SPE | ADMHC_PS_CSC, portstat);
634         msleep(100);
635 #endif
636         return 0;
637 }
638
639 static int admhc_hub_control (
640         struct usb_hcd  *hcd,
641         u16             typeReq,
642         u16             wValue,
643         u16             wIndex,
644         char            *buf,
645         u16             wLength
646 ) {
647         struct admhcd   *ahcd = hcd_to_admhcd(hcd);
648         int             ports = hcd_to_bus (hcd)->root_hub->maxchild;
649         u32             temp;
650         int             retval = 0;
651
652         if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
653                 return -ESHUTDOWN;
654
655         switch (typeReq) {
656         case ClearHubFeature:
657                 switch (wValue) {
658                 case C_HUB_OVER_CURRENT:
659 #if 0                   /* FIXME */
660                         admhc_writel(ahcd, ADMHC_RH_OCIC,
661                                         &ahcd->regs->roothub.status);
662 #endif
663                 case C_HUB_LOCAL_POWER:
664                         break;
665                 default:
666                         goto error;
667                 }
668                 break;
669         case ClearPortFeature:
670                 if (!wIndex || wIndex > ports)
671                         goto error;
672                 wIndex--;
673
674                 switch (wValue) {
675                 case USB_PORT_FEAT_ENABLE:
676                         temp = ADMHC_PS_CPE;
677                         break;
678                 case USB_PORT_FEAT_SUSPEND:
679                         temp = ADMHC_PS_CPS;
680                         break;
681                 case USB_PORT_FEAT_POWER:
682                         temp = ADMHC_PS_CPP;
683                         break;
684                 case USB_PORT_FEAT_C_CONNECTION:
685                         temp = ADMHC_PS_CSC;
686                         break;
687                 case USB_PORT_FEAT_C_ENABLE:
688                         temp = ADMHC_PS_PESC;
689                         break;
690                 case USB_PORT_FEAT_C_SUSPEND:
691                         temp = ADMHC_PS_PSSC;
692                         break;
693                 case USB_PORT_FEAT_C_OVER_CURRENT:
694                         temp = ADMHC_PS_OCIC;
695                         break;
696                 case USB_PORT_FEAT_C_RESET:
697                         temp = ADMHC_PS_PRSC;
698                         break;
699                 default:
700                         goto error;
701                 }
702                 admhc_writel(ahcd, temp, &ahcd->regs->portstatus[wIndex]);
703                 break;
704         case GetHubDescriptor:
705                 admhc_hub_descriptor(ahcd, (struct usb_hub_descriptor *) buf);
706                 break;
707         case GetHubStatus:
708                 temp = admhc_get_rhdesc(ahcd);
709                 temp &= ~(ADMHC_RH_CRWE | ADMHC_RH_DRWE);
710                 put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
711                 break;
712         case GetPortStatus:
713                 if (!wIndex || wIndex > ports)
714                         goto error;
715                 wIndex--;
716                 temp = admhc_get_portstatus(ahcd, wIndex);
717                 put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
718
719                 dbg_port(ahcd, "GetPortStatus", wIndex, temp);
720                 break;
721         case SetHubFeature:
722                 switch (wValue) {
723                 case C_HUB_OVER_CURRENT:
724                         // FIXME:  this can be cleared, yes?
725                 case C_HUB_LOCAL_POWER:
726                         break;
727                 default:
728                         goto error;
729                 }
730                 break;
731         case SetPortFeature:
732                 if (!wIndex || wIndex > ports)
733                         goto error;
734                 wIndex--;
735
736                 switch (wValue) {
737                 case USB_PORT_FEAT_ENABLE:
738                         admhc_writel(ahcd, ADMHC_PS_SPE,
739                                 &ahcd->regs->portstatus[wIndex]);
740                         break;
741                 case USB_PORT_FEAT_SUSPEND:
742 #ifdef  CONFIG_USB_OTG
743                         if (hcd->self.otg_port == (wIndex + 1)
744                                         && hcd->self.b_hnp_enable)
745                                 start_hnp(ahcd);
746                         else
747 #endif
748                         admhc_writel(ahcd, ADMHC_PS_SPS,
749                                 &ahcd->regs->portstatus[wIndex]);
750                         break;
751                 case USB_PORT_FEAT_POWER:
752                         admhc_writel(ahcd, ADMHC_PS_SPP,
753                                 &ahcd->regs->portstatus[wIndex]);
754                         break;
755                 case USB_PORT_FEAT_RESET:
756                         retval = root_port_reset(ahcd, wIndex);
757                         break;
758                 default:
759                         goto error;
760                 }
761                 break;
762
763         default:
764 error:
765                 /* "protocol stall" on error */
766                 retval = -EPIPE;
767         }
768         return retval;
769 }
770