2 * Copyright (c) 2001-2002 by David Brownell
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* this file is part of ehci-hcd.c */
21 /*-------------------------------------------------------------------------*/
24 * EHCI Root Hub ... the nonsharable stuff
26 * Registers don't need cpu_to_le32, that happens transparently
29 /*-------------------------------------------------------------------------*/
33 static int ehci_hub_suspend (struct usb_hcd *hcd)
35 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
38 if (time_before (jiffies, ehci->next_statechange))
41 port = HCS_N_PORTS (ehci->hcs_params);
42 spin_lock_irq (&ehci->lock);
44 /* stop schedules, clean any completed work */
45 if (HC_IS_RUNNING(hcd->state)) {
47 hcd->state = HC_STATE_QUIESCING;
49 ehci->command = readl (&ehci->regs->command);
51 ehci->reclaim_ready = 1;
52 ehci_work(ehci, NULL);
54 /* suspend any active/unsuspended ports, maybe allow wakeup */
56 u32 __iomem *reg = &ehci->regs->port_status [port];
60 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
62 if (hcd->remote_wakeup)
63 t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
65 t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
68 ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
74 /* turn off now-idle HC */
76 hcd->state = HC_STATE_SUSPENDED;
78 ehci->next_statechange = jiffies + msecs_to_jiffies(10);
79 spin_unlock_irq (&ehci->lock);
84 /* caller has locked the root hub, and should reset/reinit on error */
85 static int ehci_hub_resume (struct usb_hcd *hcd)
87 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
92 if (time_before (jiffies, ehci->next_statechange))
94 spin_lock_irq (&ehci->lock);
96 /* re-init operational registers in case we lost power */
97 if (readl (&ehci->regs->intr_enable) == 0) {
98 /* at least some APM implementations will try to deliver
99 * IRQs right away, so delay them until we're ready.
102 writel (0, &ehci->regs->segment);
103 writel (ehci->periodic_dma, &ehci->regs->frame_list);
104 writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
107 ehci_dbg(ehci, "resume root hub%s\n",
108 intr_enable ? " after power loss" : "");
110 /* restore CMD_RUN, framelist size, and irq threshold */
111 writel (ehci->command, &ehci->regs->command);
113 /* take ports out of suspend */
114 i = HCS_N_PORTS (ehci->hcs_params);
116 temp = readl (&ehci->regs->port_status [i]);
117 temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
118 if (temp & PORT_SUSPEND) {
119 ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
122 writel (temp, &ehci->regs->port_status [i]);
124 i = HCS_N_PORTS (ehci->hcs_params);
127 temp = readl (&ehci->regs->port_status [i]);
128 if ((temp & PORT_SUSPEND) == 0)
130 temp &= ~PORT_RESUME;
131 writel (temp, &ehci->regs->port_status [i]);
132 ehci_vdbg (ehci, "resumed port %d\n", i + 1);
134 (void) readl (&ehci->regs->command);
136 /* maybe re-activate the schedule(s) */
138 if (ehci->async->qh_next.qh)
140 if (ehci->periodic_sched)
143 ehci->command |= temp;
144 writel (ehci->command, &ehci->regs->command);
147 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
148 hcd->state = HC_STATE_RUNNING;
150 /* Now we can safely re-enable irqs */
152 writel (INTR_MASK, &ehci->regs->intr_enable);
154 spin_unlock_irq (&ehci->lock);
160 #define ehci_hub_suspend NULL
161 #define ehci_hub_resume NULL
163 #endif /* CONFIG_PM */
165 /*-------------------------------------------------------------------------*/
167 static int check_reset_complete (
168 struct ehci_hcd *ehci,
172 if (!(port_status & PORT_CONNECT)) {
173 ehci->reset_done [index] = 0;
177 /* if reset finished and it's still not enabled -- handoff */
178 if (!(port_status & PORT_PE)) {
180 /* with integrated TT, there's nobody to hand it to! */
181 if (ehci_is_TDI(ehci)) {
183 "Failed to enable port %d on root hub TT\n",
188 ehci_dbg (ehci, "port %d full speed --> companion\n",
191 // what happens if HCS_N_CC(params) == 0 ?
192 port_status |= PORT_OWNER;
193 writel (port_status, &ehci->regs->port_status [index]);
196 ehci_dbg (ehci, "port %d high speed\n", index + 1);
201 /*-------------------------------------------------------------------------*/
204 /* build "status change" packet (one or two bytes) from HC registers */
207 ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
209 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
210 u32 temp, status = 0;
211 int ports, i, retval = 1;
214 /* if !USB_SUSPEND, root hub timers won't get shut down ... */
215 if (!HC_IS_RUNNING(hcd->state))
218 /* init status to no-changes */
220 ports = HCS_N_PORTS (ehci->hcs_params);
226 /* no hub change reports (bit 0) for now (power, ...) */
228 /* port N changes (bit N)? */
229 spin_lock_irqsave (&ehci->lock, flags);
230 for (i = 0; i < ports; i++) {
231 temp = readl (&ehci->regs->port_status [i]);
232 if (temp & PORT_OWNER) {
233 /* don't report this in GetPortStatus */
234 if (temp & PORT_CSC) {
236 writel (temp, &ehci->regs->port_status [i]);
240 if (!(temp & PORT_CONNECT))
241 ehci->reset_done [i] = 0;
242 if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
243 // PORT_STAT_C_SUSPEND?
244 || ((temp & PORT_RESUME) != 0
245 && time_after (jiffies,
246 ehci->reset_done [i]))) {
248 buf [0] |= 1 << (i + 1);
250 buf [1] |= 1 << (i - 7);
254 /* FIXME autosuspend idle root hubs */
255 spin_unlock_irqrestore (&ehci->lock, flags);
256 return status ? retval : 0;
259 /*-------------------------------------------------------------------------*/
262 ehci_hub_descriptor (
263 struct ehci_hcd *ehci,
264 struct usb_hub_descriptor *desc
266 int ports = HCS_N_PORTS (ehci->hcs_params);
269 desc->bDescriptorType = 0x29;
270 desc->bPwrOn2PwrGood = 10; /* ehci 1.0, 2.3.9 says 20ms max */
271 desc->bHubContrCurrent = 0;
273 desc->bNbrPorts = ports;
274 temp = 1 + (ports / 8);
275 desc->bDescLength = 7 + 2 * temp;
277 /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
278 memset (&desc->bitmap [0], 0, temp);
279 memset (&desc->bitmap [temp], 0xff, temp);
281 temp = 0x0008; /* per-port overcurrent reporting */
282 if (HCS_PPC (ehci->hcs_params))
283 temp |= 0x0001; /* per-port power control */
285 temp |= 0x0002; /* no power switching */
287 // re-enable when we support USB_PORT_FEAT_INDICATOR below.
288 if (HCS_INDICATOR (ehci->hcs_params))
289 temp |= 0x0080; /* per-port indicators (LEDs) */
291 desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp);
294 /*-------------------------------------------------------------------------*/
296 #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
298 static int ehci_hub_control (
306 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
307 int ports = HCS_N_PORTS (ehci->hcs_params);
313 * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
314 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
315 * (track current state ourselves) ... blink for diagnostics,
316 * power, "this is the one", etc. EHCI spec supports this.
319 spin_lock_irqsave (&ehci->lock, flags);
321 case ClearHubFeature:
323 case C_HUB_LOCAL_POWER:
324 case C_HUB_OVER_CURRENT:
325 /* no hub-wide feature/status flags */
331 case ClearPortFeature:
332 if (!wIndex || wIndex > ports)
335 temp = readl (&ehci->regs->port_status [wIndex]);
336 if (temp & PORT_OWNER)
340 case USB_PORT_FEAT_ENABLE:
341 writel (temp & ~PORT_PE,
342 &ehci->regs->port_status [wIndex]);
344 case USB_PORT_FEAT_C_ENABLE:
345 writel (temp | PORT_PEC,
346 &ehci->regs->port_status [wIndex]);
348 case USB_PORT_FEAT_SUSPEND:
349 if (temp & PORT_RESET)
351 if (temp & PORT_SUSPEND) {
352 if ((temp & PORT_PE) == 0)
354 /* resume signaling for 20 msec */
355 writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME,
356 &ehci->regs->port_status [wIndex]);
357 ehci->reset_done [wIndex] = jiffies
358 + msecs_to_jiffies (20);
361 case USB_PORT_FEAT_C_SUSPEND:
362 /* we auto-clear this feature */
364 case USB_PORT_FEAT_POWER:
365 if (HCS_PPC (ehci->hcs_params))
366 writel (temp & ~PORT_POWER,
367 &ehci->regs->port_status [wIndex]);
369 case USB_PORT_FEAT_C_CONNECTION:
370 writel (temp | PORT_CSC,
371 &ehci->regs->port_status [wIndex]);
373 case USB_PORT_FEAT_C_OVER_CURRENT:
374 writel (temp | PORT_OCC,
375 &ehci->regs->port_status [wIndex]);
377 case USB_PORT_FEAT_C_RESET:
378 /* GetPortStatus clears reset */
383 readl (&ehci->regs->command); /* unblock posted write */
385 case GetHubDescriptor:
386 ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
390 /* no hub-wide feature/status flags */
392 //cpu_to_le32s ((u32 *) buf);
395 if (!wIndex || wIndex > ports)
399 temp = readl (&ehci->regs->port_status [wIndex]);
403 status |= 1 << USB_PORT_FEAT_C_CONNECTION;
405 status |= 1 << USB_PORT_FEAT_C_ENABLE;
407 status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
409 /* whoever resumes must GetPortStatus to complete it!! */
410 if ((temp & PORT_RESUME)
411 && time_after (jiffies,
412 ehci->reset_done [wIndex])) {
413 status |= 1 << USB_PORT_FEAT_C_SUSPEND;
414 ehci->reset_done [wIndex] = 0;
416 /* stop resume signaling */
417 temp = readl (&ehci->regs->port_status [wIndex]);
418 writel (temp & ~PORT_RESUME,
419 &ehci->regs->port_status [wIndex]);
421 &ehci->regs->port_status [wIndex],
422 PORT_RESUME, 0, 2000 /* 2msec */);
424 ehci_err (ehci, "port %d resume error %d\n",
428 temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
431 /* whoever resets must GetPortStatus to complete it!! */
432 if ((temp & PORT_RESET)
433 && time_after (jiffies,
434 ehci->reset_done [wIndex])) {
435 status |= 1 << USB_PORT_FEAT_C_RESET;
436 ehci->reset_done [wIndex] = 0;
438 /* force reset to complete */
439 writel (temp & ~PORT_RESET,
440 &ehci->regs->port_status [wIndex]);
442 &ehci->regs->port_status [wIndex],
445 ehci_err (ehci, "port %d reset error %d\n",
450 /* see what we found out */
451 temp = check_reset_complete (ehci, wIndex,
452 readl (&ehci->regs->port_status [wIndex]));
455 // don't show wPortStatus if it's owned by a companion hc
456 if (!(temp & PORT_OWNER)) {
457 if (temp & PORT_CONNECT) {
458 status |= 1 << USB_PORT_FEAT_CONNECTION;
459 // status may be from integrated TT
460 status |= ehci_port_speed(ehci, temp);
463 status |= 1 << USB_PORT_FEAT_ENABLE;
464 if (temp & (PORT_SUSPEND|PORT_RESUME))
465 status |= 1 << USB_PORT_FEAT_SUSPEND;
467 status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
468 if (temp & PORT_RESET)
469 status |= 1 << USB_PORT_FEAT_RESET;
470 if (temp & PORT_POWER)
471 status |= 1 << USB_PORT_FEAT_POWER;
474 #ifndef EHCI_VERBOSE_DEBUG
475 if (status & ~0xffff) /* only if wPortChange is interesting */
477 dbg_port (ehci, "GetStatus", wIndex + 1, temp);
478 // we "know" this alignment is good, caller used kmalloc()...
479 *((__le32 *) buf) = cpu_to_le32 (status);
483 case C_HUB_LOCAL_POWER:
484 case C_HUB_OVER_CURRENT:
485 /* no hub-wide feature/status flags */
492 if (!wIndex || wIndex > ports)
495 temp = readl (&ehci->regs->port_status [wIndex]);
496 if (temp & PORT_OWNER)
500 case USB_PORT_FEAT_SUSPEND:
501 if ((temp & PORT_PE) == 0
502 || (temp & PORT_RESET) != 0)
504 if (hcd->remote_wakeup)
505 temp |= PORT_WAKE_BITS;
506 writel (temp | PORT_SUSPEND,
507 &ehci->regs->port_status [wIndex]);
509 case USB_PORT_FEAT_POWER:
510 if (HCS_PPC (ehci->hcs_params))
511 writel (temp | PORT_POWER,
512 &ehci->regs->port_status [wIndex]);
514 case USB_PORT_FEAT_RESET:
515 if (temp & PORT_RESUME)
517 /* line status bits may report this as low speed,
518 * which can be fine if this root hub has a
519 * transaction translator built in.
521 if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
522 && !ehci_is_TDI(ehci)
523 && PORT_USB11 (temp)) {
525 "port %d low speed --> companion\n",
529 ehci_vdbg (ehci, "port %d reset\n", wIndex + 1);
534 * caller must wait, then call GetPortStatus
535 * usb 2.0 spec says 50 ms resets on root
537 ehci->reset_done [wIndex] = jiffies
538 + msecs_to_jiffies (50);
540 writel (temp, &ehci->regs->port_status [wIndex]);
545 readl (&ehci->regs->command); /* unblock posted writes */
550 /* "stall" on error */
553 spin_unlock_irqrestore (&ehci->lock, flags);