vserver 2.0 rc7
[linux-2.6.git] / drivers / usb / host / ehci-hub.c
1 /*
2  * Copyright (c) 2001-2002 by David Brownell
3  * 
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.
8  *
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
12  * for more details.
13  *
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.
17  */
18
19 /* this file is part of ehci-hcd.c */
20
21 /*-------------------------------------------------------------------------*/
22
23 /*
24  * EHCI Root Hub ... the nonsharable stuff
25  *
26  * Registers don't need cpu_to_le32, that happens transparently
27  */
28
29 /*-------------------------------------------------------------------------*/
30
31 #ifdef  CONFIG_PM
32
33 static int ehci_hub_suspend (struct usb_hcd *hcd)
34 {
35         struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
36         int                     port;
37
38         if (time_before (jiffies, ehci->next_statechange))
39                 msleep(5);
40
41         port = HCS_N_PORTS (ehci->hcs_params);
42         spin_lock_irq (&ehci->lock);
43
44         /* stop schedules, clean any completed work */
45         if (HC_IS_RUNNING(hcd->state)) {
46                 ehci_quiesce (ehci);
47                 hcd->state = HC_STATE_QUIESCING;
48         }
49         ehci->command = readl (&ehci->regs->command);
50         if (ehci->reclaim)
51                 ehci->reclaim_ready = 1;
52         ehci_work(ehci, NULL);
53
54         /* suspend any active/unsuspended ports, maybe allow wakeup */
55         while (port--) {
56                 u32 __iomem     *reg = &ehci->regs->port_status [port];
57                 u32             t1 = readl (reg);
58                 u32             t2 = t1;
59
60                 if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
61                         t2 |= PORT_SUSPEND;
62                 if (hcd->remote_wakeup)
63                         t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
64                 else
65                         t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
66
67                 if (t1 != t2) {
68                         ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
69                                 port + 1, t1, t2);
70                         writel (t2, reg);
71                 }
72         }
73
74         /* turn off now-idle HC */
75         del_timer_sync (&ehci->watchdog);
76         ehci_halt (ehci);
77         hcd->state = HC_STATE_SUSPENDED;
78
79         ehci->next_statechange = jiffies + msecs_to_jiffies(10);
80         spin_unlock_irq (&ehci->lock);
81         return 0;
82 }
83
84
85 /* caller has locked the root hub, and should reset/reinit on error */
86 static int ehci_hub_resume (struct usb_hcd *hcd)
87 {
88         struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
89         u32                     temp;
90         int                     i;
91         int                     intr_enable;
92
93         if (time_before (jiffies, ehci->next_statechange))
94                 msleep(5);
95         spin_lock_irq (&ehci->lock);
96
97         /* re-init operational registers in case we lost power */
98         if (readl (&ehci->regs->intr_enable) == 0) {
99                 /* at least some APM implementations will try to deliver
100                  * IRQs right away, so delay them until we're ready.
101                  */
102                 intr_enable = 1;
103                 writel (0, &ehci->regs->segment);
104                 writel (ehci->periodic_dma, &ehci->regs->frame_list);
105                 writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
106         } else
107                 intr_enable = 0;
108         ehci_dbg(ehci, "resume root hub%s\n",
109                         intr_enable ? " after power loss" : "");
110
111         /* restore CMD_RUN, framelist size, and irq threshold */
112         writel (ehci->command, &ehci->regs->command);
113
114         /* take ports out of suspend */
115         i = HCS_N_PORTS (ehci->hcs_params);
116         while (i--) {
117                 temp = readl (&ehci->regs->port_status [i]);
118                 temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
119                 if (temp & PORT_SUSPEND) {
120                         ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
121                         temp |= PORT_RESUME;
122                 }
123                 writel (temp, &ehci->regs->port_status [i]);
124         }
125         i = HCS_N_PORTS (ehci->hcs_params);
126         mdelay (20);
127         while (i--) {
128                 temp = readl (&ehci->regs->port_status [i]);
129                 if ((temp & PORT_SUSPEND) == 0)
130                         continue;
131                 temp &= ~PORT_RESUME;
132                 writel (temp, &ehci->regs->port_status [i]);
133                 ehci_vdbg (ehci, "resumed port %d\n", i + 1);
134         }
135         (void) readl (&ehci->regs->command);
136
137         /* maybe re-activate the schedule(s) */
138         temp = 0;
139         if (ehci->async->qh_next.qh)
140                 temp |= CMD_ASE;
141         if (ehci->periodic_sched)
142                 temp |= CMD_PSE;
143         if (temp) {
144                 ehci->command |= temp;
145                 writel (ehci->command, &ehci->regs->command);
146         }
147
148         ehci->next_statechange = jiffies + msecs_to_jiffies(5);
149         hcd->state = HC_STATE_RUNNING;
150
151         /* Now we can safely re-enable irqs */
152         if (intr_enable)
153                 writel (INTR_MASK, &ehci->regs->intr_enable);
154
155         spin_unlock_irq (&ehci->lock);
156         return 0;
157 }
158
159 #else
160
161 #define ehci_hub_suspend        NULL
162 #define ehci_hub_resume         NULL
163
164 #endif  /* CONFIG_PM */
165
166 /*-------------------------------------------------------------------------*/
167
168 static int check_reset_complete (
169         struct ehci_hcd *ehci,
170         int             index,
171         int             port_status
172 ) {
173         if (!(port_status & PORT_CONNECT)) {
174                 ehci->reset_done [index] = 0;
175                 return port_status;
176         }
177
178         /* if reset finished and it's still not enabled -- handoff */
179         if (!(port_status & PORT_PE)) {
180
181                 /* with integrated TT, there's nobody to hand it to! */
182                 if (ehci_is_TDI(ehci)) {
183                         ehci_dbg (ehci,
184                                 "Failed to enable port %d on root hub TT\n",
185                                 index+1);
186                         return port_status;
187                 }
188
189                 ehci_dbg (ehci, "port %d full speed --> companion\n",
190                         index + 1);
191
192                 // what happens if HCS_N_CC(params) == 0 ?
193                 port_status |= PORT_OWNER;
194                 writel (port_status, &ehci->regs->port_status [index]);
195
196         } else
197                 ehci_dbg (ehci, "port %d high speed\n", index + 1);
198
199         return port_status;
200 }
201
202 /*-------------------------------------------------------------------------*/
203
204
205 /* build "status change" packet (one or two bytes) from HC registers */
206
207 static int
208 ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
209 {
210         struct ehci_hcd *ehci = hcd_to_ehci (hcd);
211         u32             temp, status = 0;
212         int             ports, i, retval = 1;
213         unsigned long   flags;
214
215         /* if !USB_SUSPEND, root hub timers won't get shut down ... */
216         if (!HC_IS_RUNNING(hcd->state))
217                 return 0;
218
219         /* init status to no-changes */
220         buf [0] = 0;
221         ports = HCS_N_PORTS (ehci->hcs_params);
222         if (ports > 7) {
223                 buf [1] = 0;
224                 retval++;
225         }
226         
227         /* no hub change reports (bit 0) for now (power, ...) */
228
229         /* port N changes (bit N)? */
230         spin_lock_irqsave (&ehci->lock, flags);
231         for (i = 0; i < ports; i++) {
232                 temp = readl (&ehci->regs->port_status [i]);
233                 if (temp & PORT_OWNER) {
234                         /* don't report this in GetPortStatus */
235                         if (temp & PORT_CSC) {
236                                 temp &= ~PORT_CSC;
237                                 writel (temp, &ehci->regs->port_status [i]);
238                         }
239                         continue;
240                 }
241                 if (!(temp & PORT_CONNECT))
242                         ehci->reset_done [i] = 0;
243                 if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
244                                 // PORT_STAT_C_SUSPEND?
245                                 || ((temp & PORT_RESUME) != 0
246                                         && time_after (jiffies,
247                                                 ehci->reset_done [i]))) {
248                         if (i < 7)
249                             buf [0] |= 1 << (i + 1);
250                         else
251                             buf [1] |= 1 << (i - 7);
252                         status = STS_PCD;
253                 }
254         }
255         /* FIXME autosuspend idle root hubs */
256         spin_unlock_irqrestore (&ehci->lock, flags);
257         return status ? retval : 0;
258 }
259
260 /*-------------------------------------------------------------------------*/
261
262 static void
263 ehci_hub_descriptor (
264         struct ehci_hcd                 *ehci,
265         struct usb_hub_descriptor       *desc
266 ) {
267         int             ports = HCS_N_PORTS (ehci->hcs_params);
268         u16             temp;
269
270         desc->bDescriptorType = 0x29;
271         desc->bPwrOn2PwrGood = 10;      /* ehci 1.0, 2.3.9 says 20ms max */
272         desc->bHubContrCurrent = 0;
273
274         desc->bNbrPorts = ports;
275         temp = 1 + (ports / 8);
276         desc->bDescLength = 7 + 2 * temp;
277
278         /* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
279         memset (&desc->bitmap [0], 0, temp);
280         memset (&desc->bitmap [temp], 0xff, temp);
281
282         temp = 0x0008;                  /* per-port overcurrent reporting */
283         if (HCS_PPC (ehci->hcs_params))
284                 temp |= 0x0001;         /* per-port power control */
285         else
286                 temp |= 0x0002;         /* no power switching */
287 #if 0
288 // re-enable when we support USB_PORT_FEAT_INDICATOR below.
289         if (HCS_INDICATOR (ehci->hcs_params))
290                 temp |= 0x0080;         /* per-port indicators (LEDs) */
291 #endif
292         desc->wHubCharacteristics = (__force __u16)cpu_to_le16 (temp);
293 }
294
295 /*-------------------------------------------------------------------------*/
296
297 #define PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
298
299 static int ehci_hub_control (
300         struct usb_hcd  *hcd,
301         u16             typeReq,
302         u16             wValue,
303         u16             wIndex,
304         char            *buf,
305         u16             wLength
306 ) {
307         struct ehci_hcd *ehci = hcd_to_ehci (hcd);
308         int             ports = HCS_N_PORTS (ehci->hcs_params);
309         u32             temp, status;
310         unsigned long   flags;
311         int             retval = 0;
312
313         /*
314          * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
315          * HCS_INDICATOR may say we can change LEDs to off/amber/green.
316          * (track current state ourselves) ... blink for diagnostics,
317          * power, "this is the one", etc.  EHCI spec supports this.
318          */
319
320         spin_lock_irqsave (&ehci->lock, flags);
321         switch (typeReq) {
322         case ClearHubFeature:
323                 switch (wValue) {
324                 case C_HUB_LOCAL_POWER:
325                 case C_HUB_OVER_CURRENT:
326                         /* no hub-wide feature/status flags */
327                         break;
328                 default:
329                         goto error;
330                 }
331                 break;
332         case ClearPortFeature:
333                 if (!wIndex || wIndex > ports)
334                         goto error;
335                 wIndex--;
336                 temp = readl (&ehci->regs->port_status [wIndex]);
337                 if (temp & PORT_OWNER)
338                         break;
339
340                 switch (wValue) {
341                 case USB_PORT_FEAT_ENABLE:
342                         writel (temp & ~PORT_PE,
343                                 &ehci->regs->port_status [wIndex]);
344                         break;
345                 case USB_PORT_FEAT_C_ENABLE:
346                         writel (temp | PORT_PEC,
347                                 &ehci->regs->port_status [wIndex]);
348                         break;
349                 case USB_PORT_FEAT_SUSPEND:
350                         if (temp & PORT_RESET)
351                                 goto error;
352                         if (temp & PORT_SUSPEND) {
353                                 if ((temp & PORT_PE) == 0)
354                                         goto error;
355                                 /* resume signaling for 20 msec */
356                                 writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME,
357                                         &ehci->regs->port_status [wIndex]);
358                                 ehci->reset_done [wIndex] = jiffies
359                                                 + msecs_to_jiffies (20);
360                         }
361                         break;
362                 case USB_PORT_FEAT_C_SUSPEND:
363                         /* we auto-clear this feature */
364                         break;
365                 case USB_PORT_FEAT_POWER:
366                         if (HCS_PPC (ehci->hcs_params))
367                                 writel (temp & ~PORT_POWER,
368                                         &ehci->regs->port_status [wIndex]);
369                         break;
370                 case USB_PORT_FEAT_C_CONNECTION:
371                         writel (temp | PORT_CSC,
372                                 &ehci->regs->port_status [wIndex]);
373                         break;
374                 case USB_PORT_FEAT_C_OVER_CURRENT:
375                         writel (temp | PORT_OCC,
376                                 &ehci->regs->port_status [wIndex]);
377                         break;
378                 case USB_PORT_FEAT_C_RESET:
379                         /* GetPortStatus clears reset */
380                         break;
381                 default:
382                         goto error;
383                 }
384                 readl (&ehci->regs->command);   /* unblock posted write */
385                 break;
386         case GetHubDescriptor:
387                 ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
388                         buf);
389                 break;
390         case GetHubStatus:
391                 /* no hub-wide feature/status flags */
392                 memset (buf, 0, 4);
393                 //cpu_to_le32s ((u32 *) buf);
394                 break;
395         case GetPortStatus:
396                 if (!wIndex || wIndex > ports)
397                         goto error;
398                 wIndex--;
399                 status = 0;
400                 temp = readl (&ehci->regs->port_status [wIndex]);
401
402                 // wPortChange bits
403                 if (temp & PORT_CSC)
404                         status |= 1 << USB_PORT_FEAT_C_CONNECTION;
405                 if (temp & PORT_PEC)
406                         status |= 1 << USB_PORT_FEAT_C_ENABLE;
407                 if (temp & PORT_OCC)
408                         status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
409
410                 /* whoever resumes must GetPortStatus to complete it!! */
411                 if ((temp & PORT_RESUME)
412                                 && time_after (jiffies,
413                                         ehci->reset_done [wIndex])) {
414                         status |= 1 << USB_PORT_FEAT_C_SUSPEND;
415                         ehci->reset_done [wIndex] = 0;
416
417                         /* stop resume signaling */
418                         temp = readl (&ehci->regs->port_status [wIndex]);
419                         writel (temp & ~PORT_RESUME,
420                                 &ehci->regs->port_status [wIndex]);
421                         retval = handshake (
422                                         &ehci->regs->port_status [wIndex],
423                                         PORT_RESUME, 0, 2000 /* 2msec */);
424                         if (retval != 0) {
425                                 ehci_err (ehci, "port %d resume error %d\n",
426                                         wIndex + 1, retval);
427                                 goto error;
428                         }
429                         temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
430                 }
431
432                 /* whoever resets must GetPortStatus to complete it!! */
433                 if ((temp & PORT_RESET)
434                                 && time_after (jiffies,
435                                         ehci->reset_done [wIndex])) {
436                         status |= 1 << USB_PORT_FEAT_C_RESET;
437                         ehci->reset_done [wIndex] = 0;
438
439                         /* force reset to complete */
440                         writel (temp & ~PORT_RESET,
441                                         &ehci->regs->port_status [wIndex]);
442                         /* REVISIT:  some hardware needs 550+ usec to clear
443                          * this bit; seems too long to spin routinely...
444                          */
445                         retval = handshake (
446                                         &ehci->regs->port_status [wIndex],
447                                         PORT_RESET, 0, 750);
448                         if (retval != 0) {
449                                 ehci_err (ehci, "port %d reset error %d\n",
450                                         wIndex + 1, retval);
451                                 goto error;
452                         }
453
454                         /* see what we found out */
455                         temp = check_reset_complete (ehci, wIndex,
456                                 readl (&ehci->regs->port_status [wIndex]));
457                 }
458
459                 // don't show wPortStatus if it's owned by a companion hc
460                 if (!(temp & PORT_OWNER)) {
461                         if (temp & PORT_CONNECT) {
462                                 status |= 1 << USB_PORT_FEAT_CONNECTION;
463                                 // status may be from integrated TT
464                                 status |= ehci_port_speed(ehci, temp);
465                         }
466                         if (temp & PORT_PE)
467                                 status |= 1 << USB_PORT_FEAT_ENABLE;
468                         if (temp & (PORT_SUSPEND|PORT_RESUME))
469                                 status |= 1 << USB_PORT_FEAT_SUSPEND;
470                         if (temp & PORT_OC)
471                                 status |= 1 << USB_PORT_FEAT_OVER_CURRENT;
472                         if (temp & PORT_RESET)
473                                 status |= 1 << USB_PORT_FEAT_RESET;
474                         if (temp & PORT_POWER)
475                                 status |= 1 << USB_PORT_FEAT_POWER;
476                 }
477
478 #ifndef EHCI_VERBOSE_DEBUG
479         if (status & ~0xffff)   /* only if wPortChange is interesting */
480 #endif
481                 dbg_port (ehci, "GetStatus", wIndex + 1, temp);
482                 // we "know" this alignment is good, caller used kmalloc()...
483                 *((__le32 *) buf) = cpu_to_le32 (status);
484                 break;
485         case SetHubFeature:
486                 switch (wValue) {
487                 case C_HUB_LOCAL_POWER:
488                 case C_HUB_OVER_CURRENT:
489                         /* no hub-wide feature/status flags */
490                         break;
491                 default:
492                         goto error;
493                 }
494                 break;
495         case SetPortFeature:
496                 if (!wIndex || wIndex > ports)
497                         goto error;
498                 wIndex--;
499                 temp = readl (&ehci->regs->port_status [wIndex]);
500                 if (temp & PORT_OWNER)
501                         break;
502
503                 switch (wValue) {
504                 case USB_PORT_FEAT_SUSPEND:
505                         if ((temp & PORT_PE) == 0
506                                         || (temp & PORT_RESET) != 0)
507                                 goto error;
508                         if (hcd->remote_wakeup)
509                                 temp |= PORT_WAKE_BITS;
510                         writel (temp | PORT_SUSPEND,
511                                 &ehci->regs->port_status [wIndex]);
512                         break;
513                 case USB_PORT_FEAT_POWER:
514                         if (HCS_PPC (ehci->hcs_params))
515                                 writel (temp | PORT_POWER,
516                                         &ehci->regs->port_status [wIndex]);
517                         break;
518                 case USB_PORT_FEAT_RESET:
519                         if (temp & PORT_RESUME)
520                                 goto error;
521                         /* line status bits may report this as low speed,
522                          * which can be fine if this root hub has a
523                          * transaction translator built in.
524                          */
525                         if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
526                                         && !ehci_is_TDI(ehci)
527                                         && PORT_USB11 (temp)) {
528                                 ehci_dbg (ehci,
529                                         "port %d low speed --> companion\n",
530                                         wIndex + 1);
531                                 temp |= PORT_OWNER;
532                         } else {
533                                 ehci_vdbg (ehci, "port %d reset\n", wIndex + 1);
534                                 temp |= PORT_RESET;
535                                 temp &= ~PORT_PE;
536
537                                 /*
538                                  * caller must wait, then call GetPortStatus
539                                  * usb 2.0 spec says 50 ms resets on root
540                                  */
541                                 ehci->reset_done [wIndex] = jiffies
542                                                 + msecs_to_jiffies (50);
543                         }
544                         writel (temp, &ehci->regs->port_status [wIndex]);
545                         break;
546                 default:
547                         goto error;
548                 }
549                 readl (&ehci->regs->command);   /* unblock posted writes */
550                 break;
551
552         default:
553 error:
554                 /* "stall" on error */
555                 retval = -EPIPE;
556         }
557         spin_unlock_irqrestore (&ehci->lock, flags);
558         return retval;
559 }