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