ehci-hub.c 28.9 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
D
David Brownell 已提交
2
 * Copyright (C) 2001-2004 by David Brownell
3
 *
L
Linus Torvalds 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* this file is part of ehci-hcd.c */

/*-------------------------------------------------------------------------*/

/*
 * EHCI Root Hub ... the nonsharable stuff
 *
 * Registers don't need cpu_to_le32, that happens transparently
 */

/*-------------------------------------------------------------------------*/
30
#include <linux/usb/otg.h>
L
Linus Torvalds 已提交
31

32 33
#define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)

34 35
#ifdef	CONFIG_PM

A
Alan Stern 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
static int ehci_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength
);

/* After a power loss, ports that were owned by the companion must be
 * reset so that the companion can still own them.
 */
static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
{
	u32 __iomem	*reg;
	u32		status;
	int		port;
	__le32		buf;
	struct usb_hcd	*hcd = ehci_to_hcd(ehci);

	if (!ehci->owned_ports)
		return;

	/* Give the connections some time to appear */
	msleep(20);

	port = HCS_N_PORTS(ehci->hcs_params);
	while (port--) {
		if (test_bit(port, &ehci->owned_ports)) {
			reg = &ehci->regs->port_status[port];
66
			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
A
Alan Stern 已提交
67 68 69 70

			/* Port already owned by companion? */
			if (status & PORT_OWNER)
				clear_bit(port, &ehci->owned_ports);
71 72
			else if (test_bit(port, &ehci->companion_ports))
				ehci_writel(ehci, status & ~PORT_PE, reg);
A
Alan Stern 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
			else
				ehci_hub_control(hcd, SetPortFeature,
						USB_PORT_FEAT_RESET, port + 1,
						NULL, 0);
		}
	}

	if (!ehci->owned_ports)
		return;
	msleep(90);		/* Wait for resets to complete */

	port = HCS_N_PORTS(ehci->hcs_params);
	while (port--) {
		if (test_bit(port, &ehci->owned_ports)) {
			ehci_hub_control(hcd, GetPortStatus,
					0, port + 1,
					(char *) &buf, sizeof(buf));

			/* The companion should now own the port,
			 * but if something went wrong the port must not
			 * remain enabled.
			 */
			reg = &ehci->regs->port_status[port];
			status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
			if (status & PORT_OWNER)
				ehci_writel(ehci, status | PORT_CSC, reg);
			else {
				ehci_dbg(ehci, "failed handover port %d: %x\n",
						port + 1, status);
				ehci_writel(ehci, status & ~PORT_PE, reg);
			}
		}
	}

	ehci->owned_ports = 0;
}

110
static int ehci_port_change(struct ehci_hcd *ehci)
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
{
	int i = HCS_N_PORTS(ehci->hcs_params);

	/* First check if the controller indicates a change event */

	if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)
		return 1;

	/*
	 * Not all controllers appear to update this while going from D3 to D0,
	 * so check the individual port status registers as well
	 */

	while (i--)
		if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC)
			return 1;

	return 0;
}

131
static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
132
		bool suspending, bool do_wakeup)
133 134 135
{
	int		port;
	u32		temp;
136
	unsigned long	flags;
137 138 139 140 141 142

	/* If remote wakeup is enabled for the root hub but disabled
	 * for the controller, we must adjust all the port wakeup flags
	 * when the controller is suspended or resumed.  In all other
	 * cases they don't need to be changed.
	 */
143
	if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup)
144 145
		return;

146 147
	spin_lock_irqsave(&ehci->lock, flags);

148 149 150 151
	/* clear phy low-power mode before changing wakeup flags */
	if (ehci->has_hostpc) {
		port = HCS_N_PORTS(ehci->hcs_params);
		while (port--) {
152
			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
153 154 155 156

			temp = ehci_readl(ehci, hostpc_reg);
			ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
		}
157
		spin_unlock_irqrestore(&ehci->lock, flags);
158
		msleep(5);
159
		spin_lock_irqsave(&ehci->lock, flags);
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
	}

	port = HCS_N_PORTS(ehci->hcs_params);
	while (port--) {
		u32 __iomem	*reg = &ehci->regs->port_status[port];
		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
		u32		t2 = t1 & ~PORT_WAKE_BITS;

		/* If we are suspending the controller, clear the flags.
		 * If we are resuming the controller, set the wakeup flags.
		 */
		if (!suspending) {
			if (t1 & PORT_CONNECT)
				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
			else
				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
		}
		ehci_vdbg(ehci, "port %d, %08x -> %08x\n",
				port + 1, t1, t2);
		ehci_writel(ehci, t2, reg);
	}

	/* enter phy low-power mode again */
	if (ehci->has_hostpc) {
		port = HCS_N_PORTS(ehci->hcs_params);
		while (port--) {
186
			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
187 188 189 190 191

			temp = ehci_readl(ehci, hostpc_reg);
			ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
		}
	}
192 193

	/* Does the root hub have a port wakeup pending? */
194
	if (!suspending && ehci_port_change(ehci))
195
		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
196 197

	spin_unlock_irqrestore(&ehci->lock, flags);
198 199
}

200
static int ehci_bus_suspend (struct usb_hcd *hcd)
L
Linus Torvalds 已提交
201 202 203
{
	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
	int			port;
204
	int			mask;
205
	int			changed;
L
Linus Torvalds 已提交
206

207 208
	ehci_dbg(ehci, "suspend root hub\n");

L
Linus Torvalds 已提交
209 210 211 212 213
	if (time_before (jiffies, ehci->next_statechange))
		msleep(5);

	spin_lock_irq (&ehci->lock);

214 215 216 217 218 219
	/* Once the controller is stopped, port resumes that are already
	 * in progress won't complete.  Hence if remote wakeup is enabled
	 * for the root hub and any ports are in the middle of a resume or
	 * remote wakeup, we must fail the suspend.
	 */
	if (hcd->self.root_hub->do_remote_wakeup) {
220 221 222 223
		if (ehci->resuming_ports) {
			spin_unlock_irq(&ehci->lock);
			ehci_dbg(ehci, "suspend failed because a port is resuming\n");
			return -EBUSY;
224 225 226
		}
	}

L
Linus Torvalds 已提交
227
	/* stop schedules, clean any completed work */
228
	ehci_quiesce(ehci);
229
	ehci_work(ehci);
L
Linus Torvalds 已提交
230

231 232 233 234 235 236
	/* Unlike other USB host controller types, EHCI doesn't have
	 * any notion of "global" or bus-wide suspend.  The driver has
	 * to manually suspend all the active unsuspended ports, and
	 * then manually resume them in the bus_resume() routine.
	 */
	ehci->bus_suspended = 0;
A
Alan Stern 已提交
237
	ehci->owned_ports = 0;
238
	changed = 0;
239
	port = HCS_N_PORTS(ehci->hcs_params);
L
Linus Torvalds 已提交
240 241
	while (port--) {
		u32 __iomem	*reg = &ehci->regs->port_status [port];
242
		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
243
		u32		t2 = t1 & ~PORT_WAKE_BITS;
L
Linus Torvalds 已提交
244

245
		/* keep track of which ports we suspend */
A
Alan Stern 已提交
246 247 248
		if (t1 & PORT_OWNER)
			set_bit(port, &ehci->owned_ports);
		else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
L
Linus Torvalds 已提交
249
			t2 |= PORT_SUSPEND;
250 251 252
			set_bit(port, &ehci->bus_suspended);
		}

253
		/* enable remote wakeup on all ports, if told to do so */
254 255 256 257 258 259
		if (hcd->self.root_hub->do_remote_wakeup) {
			/* only enable appropriate wake bits, otherwise the
			 * hardware can not go phy low power mode. If a race
			 * condition happens here(connection change during bits
			 * set), the port change detection will finally fix it.
			 */
260
			if (t1 & PORT_CONNECT)
261
				t2 |= PORT_WKOC_E | PORT_WKDISC_E;
262
			else
263
				t2 |= PORT_WKOC_E | PORT_WKCONN_E;
264
		}
L
Linus Torvalds 已提交
265 266 267 268

		if (t1 != t2) {
			ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
				port + 1, t1, t2);
269
			ehci_writel(ehci, t2, reg);
270 271 272
			changed = 1;
		}
	}
273

274 275 276 277 278 279 280
	if (changed && ehci->has_hostpc) {
		spin_unlock_irq(&ehci->lock);
		msleep(5);	/* 5 ms for HCD to enter low-power mode */
		spin_lock_irq(&ehci->lock);

		port = HCS_N_PORTS(ehci->hcs_params);
		while (port--) {
281
			u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[port];
282 283 284 285 286 287
			u32		t3;

			t3 = ehci_readl(ehci, hostpc_reg);
			ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
			t3 = ehci_readl(ehci, hostpc_reg);
			ehci_dbg(ehci, "Port %d phy low-power mode %s\n",
288 289
					port, (t3 & HOSTPC_PHCD) ?
					"succeeded" : "failed");
L
Linus Torvalds 已提交
290 291 292
		}
	}

293 294 295 296
	/* Apparently some devices need a >= 1-uframe delay here */
	if (ehci->bus_suspended)
		udelay(150);

L
Linus Torvalds 已提交
297 298
	/* turn off now-idle HC */
	ehci_halt (ehci);
299
	ehci->rh_state = EHCI_RH_SUSPENDED;
L
Linus Torvalds 已提交
300

301
	end_unlink_async(ehci);
302
	unlink_empty_async(ehci);
303
	ehci_handle_intr_unlinks(ehci);
304
	end_free_itds(ehci);
305

306 307
	/* allow remote wakeup */
	mask = INTR_MASK;
308
	if (!hcd->self.root_hub->do_remote_wakeup)
309
		mask &= ~STS_PCD;
310 311
	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
	ehci_readl(ehci, &ehci->regs->intr_enable);
312

L
Linus Torvalds 已提交
313
	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
A
Alan Stern 已提交
314 315
	ehci->enabled_hrtimer_events = 0;
	ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
L
Linus Torvalds 已提交
316
	spin_unlock_irq (&ehci->lock);
317

A
Alan Stern 已提交
318
	hrtimer_cancel(&ehci->hrtimer);
L
Linus Torvalds 已提交
319 320 321 322 323
	return 0;
}


/* caller has locked the root hub, and should reset/reinit on error */
324
static int ehci_bus_resume (struct usb_hcd *hcd)
L
Linus Torvalds 已提交
325 326 327
{
	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
	u32			temp;
A
Alan Stern 已提交
328
	u32			power_okay;
L
Linus Torvalds 已提交
329
	int			i;
330
	unsigned long		resume_needed = 0;
L
Linus Torvalds 已提交
331 332 333 334

	if (time_before (jiffies, ehci->next_statechange))
		msleep(5);
	spin_lock_irq (&ehci->lock);
335
	if (!HCD_HW_ACCESSIBLE(hcd)) {
336 337 338
		spin_unlock_irq(&ehci->lock);
		return -ESHUTDOWN;
	}
L
Linus Torvalds 已提交
339

340
	if (unlikely(ehci->debug)) {
341
		if (!dbgp_reset_prep())
342 343 344 345 346
			ehci->debug = NULL;
		else
			dbgp_external_startup();
	}

D
David Brownell 已提交
347 348 349 350 351 352
	/* Ideally and we've got a real resume here, and no port's power
	 * was lost.  (For PCI, that means Vaux was maintained.)  But we
	 * could instead be restoring a swsusp snapshot -- so that BIOS was
	 * the last user of the controller, not reset/pm hardware keeping
	 * state we gave to it.
	 */
A
Alan Stern 已提交
353 354 355
	power_okay = ehci_readl(ehci, &ehci->regs->intr_enable);
	ehci_dbg(ehci, "resume root hub%s\n",
			power_okay ? "" : " after power loss");
D
David Brownell 已提交
356

357 358 359
	/* at least some APM implementations will try to deliver
	 * IRQs right away, so delay them until we're ready.
	 */
360
	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
361 362

	/* re-init operational registers */
363 364 365
	ehci_writel(ehci, 0, &ehci->regs->segment);
	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
	ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
L
Linus Torvalds 已提交
366 367

	/* restore CMD_RUN, framelist size, and irq threshold */
368
	ehci->command |= CMD_RUN;
369
	ehci_writel(ehci, ehci->command, &ehci->regs->command);
370
	ehci->rh_state = EHCI_RH_RUNNING;
L
Linus Torvalds 已提交
371

372 373
	/* Some controller/firmware combinations need a delay during which
	 * they set up the port statuses.  See Bugzilla #8190. */
374 375 376
	spin_unlock_irq(&ehci->lock);
	msleep(8);
	spin_lock_irq(&ehci->lock);
377

378 379 380 381 382
	/* clear phy low-power mode before resume */
	if (ehci->bus_suspended && ehci->has_hostpc) {
		i = HCS_N_PORTS(ehci->hcs_params);
		while (i--) {
			if (test_bit(i, &ehci->bus_suspended)) {
383 384
				u32 __iomem	*hostpc_reg =
							&ehci->regs->hostpc[i];
385 386 387 388 389 390 391 392 393 394 395

				temp = ehci_readl(ehci, hostpc_reg);
				ehci_writel(ehci, temp & ~HOSTPC_PHCD,
						hostpc_reg);
			}
		}
		spin_unlock_irq(&ehci->lock);
		msleep(5);
		spin_lock_irq(&ehci->lock);
	}

396
	/* manually resume the ports we suspended during bus_suspend() */
L
Linus Torvalds 已提交
397 398
	i = HCS_N_PORTS (ehci->hcs_params);
	while (i--) {
399
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
400
		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
401
		if (test_bit(i, &ehci->bus_suspended) &&
402
				(temp & PORT_SUSPEND)) {
L
Linus Torvalds 已提交
403
			temp |= PORT_RESUME;
404
			set_bit(i, &resume_needed);
405
		}
406
		ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
L
Linus Torvalds 已提交
407
	}
408 409 410 411 412 413 414 415

	/* msleep for 20ms only if code is trying to resume port */
	if (resume_needed) {
		spin_unlock_irq(&ehci->lock);
		msleep(20);
		spin_lock_irq(&ehci->lock);
	}

L
Linus Torvalds 已提交
416 417
	i = HCS_N_PORTS (ehci->hcs_params);
	while (i--) {
418
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
419
		if (test_bit(i, &resume_needed)) {
420
			temp &= ~(PORT_RWC_BITS | PORT_RESUME);
421
			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
422 423
			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
		}
L
Linus Torvalds 已提交
424 425 426 427 428
	}

	ehci->next_statechange = jiffies + msecs_to_jiffies(5);

	/* Now we can safely re-enable irqs */
429
	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
430
	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
L
Linus Torvalds 已提交
431 432

	spin_unlock_irq (&ehci->lock);
433
	ehci_handover_companion_ports(ehci);
L
Linus Torvalds 已提交
434 435 436 437 438
	return 0;
}

#else

439 440
#define ehci_bus_suspend	NULL
#define ehci_bus_resume		NULL
L
Linus Torvalds 已提交
441 442 443

#endif	/* CONFIG_PM */

444 445 446
/*-------------------------------------------------------------------------*/

/*
447
 * Sets the owner of a port
448
 */
449
static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
450 451 452
{
	u32 __iomem		*status_reg;
	u32			port_status;
453
	int 			try;
454

455
	status_reg = &ehci->regs->port_status[portnum];
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477

	/*
	 * The controller won't set the OWNER bit if the port is
	 * enabled, so this loop will sometimes require at least two
	 * iterations: one to disable the port and one to set OWNER.
	 */
	for (try = 4; try > 0; --try) {
		spin_lock_irq(&ehci->lock);
		port_status = ehci_readl(ehci, status_reg);
		if ((port_status & PORT_OWNER) == new_owner
				|| (port_status & (PORT_OWNER | PORT_CONNECT))
					== 0)
			try = 0;
		else {
			port_status ^= PORT_OWNER;
			port_status &= ~(PORT_PE | PORT_RWC_BITS);
			ehci_writel(ehci, port_status, status_reg);
		}
		spin_unlock_irq(&ehci->lock);
		if (try > 1)
			msleep(5);
	}
478 479
}

L
Linus Torvalds 已提交
480 481 482 483 484
/*-------------------------------------------------------------------------*/

static int check_reset_complete (
	struct ehci_hcd	*ehci,
	int		index,
485
	u32 __iomem	*status_reg,
L
Linus Torvalds 已提交
486 487
	int		port_status
) {
488
	if (!(port_status & PORT_CONNECT))
L
Linus Torvalds 已提交
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
		return port_status;

	/* if reset finished and it's still not enabled -- handoff */
	if (!(port_status & PORT_PE)) {

		/* with integrated TT, there's nobody to hand it to! */
		if (ehci_is_TDI(ehci)) {
			ehci_dbg (ehci,
				"Failed to enable port %d on root hub TT\n",
				index+1);
			return port_status;
		}

		ehci_dbg (ehci, "port %d full speed --> companion\n",
			index + 1);

		// what happens if HCS_N_CC(params) == 0 ?
		port_status |= PORT_OWNER;
D
David Brownell 已提交
507
		port_status &= ~PORT_RWC_BITS;
508
		ehci_writel(ehci, port_status, status_reg);
L
Linus Torvalds 已提交
509

510 511 512 513
		/* ensure 440EPX ohci controller state is operational */
		if (ehci->has_amcc_usb23)
			set_ohci_hcfs(ehci, 1);
	} else {
514 515
		ehci_dbg(ehci, "port %d reset complete, port enabled\n",
			index + 1);
516 517 518 519
		/* ensure 440EPx ohci controller state is suspended */
		if (ehci->has_amcc_usb23)
			set_ohci_hcfs(ehci, 0);
	}
L
Linus Torvalds 已提交
520 521 522 523 524 525 526 527 528 529 530 531 532

	return port_status;
}

/*-------------------------------------------------------------------------*/


/* build "status change" packet (one or two bytes) from HC registers */

static int
ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
533
	u32		temp, status;
534
	u32		mask;
L
Linus Torvalds 已提交
535 536
	int		ports, i, retval = 1;
	unsigned long	flags;
537
	u32		ppcd = 0;
L
Linus Torvalds 已提交
538 539 540 541 542 543 544 545

	/* init status to no-changes */
	buf [0] = 0;
	ports = HCS_N_PORTS (ehci->hcs_params);
	if (ports > 7) {
		buf [1] = 0;
		retval++;
	}
546

547 548 549 550 551
	/* Inform the core about resumes-in-progress by returning
	 * a non-zero value even if there are no status changes.
	 */
	status = ehci->resuming_ports;

552 553
	/* Some boards (mostly VIA?) report bogus overcurrent indications,
	 * causing massive log spam unless we completely ignore them.  It
554
	 * may be relevant that VIA VT8235 controllers, where PORT_POWER is
555 556 557 558 559 560 561 562 563
	 * always set, seem to clear PORT_OCC and PORT_CSC when writing to
	 * PORT_POWER; that's surprising, but maybe within-spec.
	 */
	if (!ignore_oc)
		mask = PORT_CSC | PORT_PEC | PORT_OCC;
	else
		mask = PORT_CSC | PORT_PEC;
	// PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND

L
Linus Torvalds 已提交
564 565 566 567
	/* no hub change reports (bit 0) for now (power, ...) */

	/* port N changes (bit N)? */
	spin_lock_irqsave (&ehci->lock, flags);
568 569 570 571 572

	/* get per-port change detect bits */
	if (ehci->has_ppcd)
		ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16;

L
Linus Torvalds 已提交
573
	for (i = 0; i < ports; i++) {
574 575 576
		/* leverage per-port change bits feature */
		if (ehci->has_ppcd && !(ppcd & (1 << i)))
			continue;
577
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
578 579 580 581 582 583 584 585

		/*
		 * Return status information even for ports with OWNER set.
		 * Otherwise khubd wouldn't see the disconnect event when a
		 * high-speed device is switched over to the companion
		 * controller by the user.
		 */

586 587 588
		if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend)
				|| (ehci->reset_done[i] && time_after_eq(
					jiffies, ehci->reset_done[i]))) {
L
Linus Torvalds 已提交
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
			if (i < 7)
			    buf [0] |= 1 << (i + 1);
			else
			    buf [1] |= 1 << (i - 7);
			status = STS_PCD;
		}
	}
	/* FIXME autosuspend idle root hubs */
	spin_unlock_irqrestore (&ehci->lock, flags);
	return status ? retval : 0;
}

/*-------------------------------------------------------------------------*/

static void
ehci_hub_descriptor (
	struct ehci_hcd			*ehci,
	struct usb_hub_descriptor	*desc
) {
	int		ports = HCS_N_PORTS (ehci->hcs_params);
	u16		temp;

	desc->bDescriptorType = 0x29;
	desc->bPwrOn2PwrGood = 10;	/* ehci 1.0, 2.3.9 says 20ms max */
	desc->bHubContrCurrent = 0;

	desc->bNbrPorts = ports;
	temp = 1 + (ports / 8);
	desc->bDescLength = 7 + 2 * temp;

	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
J
John Youn 已提交
620 621
	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
L
Linus Torvalds 已提交
622 623 624 625

	temp = 0x0008;			/* per-port overcurrent reporting */
	if (HCS_PPC (ehci->hcs_params))
		temp |= 0x0001;		/* per-port power control */
D
David Brownell 已提交
626 627
	else
		temp |= 0x0002;		/* no power switching */
L
Linus Torvalds 已提交
628 629 630 631 632
#if 0
// re-enable when we support USB_PORT_FEAT_INDICATOR below.
	if (HCS_INDICATOR (ehci->hcs_params))
		temp |= 0x0080;		/* per-port indicators (LEDs) */
#endif
A
Al Viro 已提交
633
	desc->wHubCharacteristics = cpu_to_le16(temp);
L
Linus Torvalds 已提交
634 635 636 637 638 639 640 641 642 643 644 645 646 647
}

/*-------------------------------------------------------------------------*/

static int ehci_hub_control (
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength
) {
	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
	int		ports = HCS_N_PORTS (ehci->hcs_params);
A
Alan Stern 已提交
648 649
	u32 __iomem	*status_reg = &ehci->regs->port_status[
				(wIndex & 0xff) - 1];
650
	u32 __iomem	*hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1];
651
	u32		temp, temp1, status;
L
Linus Torvalds 已提交
652 653
	unsigned long	flags;
	int		retval = 0;
654
	unsigned	selector;
L
Linus Torvalds 已提交
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678

	/*
	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
	 * (track current state ourselves) ... blink for diagnostics,
	 * power, "this is the one", etc.  EHCI spec supports this.
	 */

	spin_lock_irqsave (&ehci->lock, flags);
	switch (typeReq) {
	case ClearHubFeature:
		switch (wValue) {
		case C_HUB_LOCAL_POWER:
		case C_HUB_OVER_CURRENT:
			/* no hub-wide feature/status flags */
			break;
		default:
			goto error;
		}
		break;
	case ClearPortFeature:
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
679
		temp = ehci_readl(ehci, status_reg);
680
		temp &= ~PORT_RWC_BITS;
681 682 683 684 685

		/*
		 * Even if OWNER is set, so the port is owned by the
		 * companion controller, khubd needs to be able to clear
		 * the port-change status bits (especially
686
		 * USB_PORT_STAT_C_CONNECTION).
687
		 */
L
Linus Torvalds 已提交
688 689 690

		switch (wValue) {
		case USB_PORT_FEAT_ENABLE:
691
			ehci_writel(ehci, temp & ~PORT_PE, status_reg);
L
Linus Torvalds 已提交
692 693
			break;
		case USB_PORT_FEAT_C_ENABLE:
694
			ehci_writel(ehci, temp | PORT_PEC, status_reg);
L
Linus Torvalds 已提交
695 696 697 698
			break;
		case USB_PORT_FEAT_SUSPEND:
			if (temp & PORT_RESET)
				goto error;
D
David Brownell 已提交
699 700
			if (ehci->no_selective_suspend)
				break;
701 702 703
#ifdef CONFIG_USB_OTG
			if ((hcd->self.otg_port == (wIndex + 1))
			    && hcd->self.b_hnp_enable) {
704
				otg_start_hnp(hcd->phy->otg);
705 706 707
				break;
			}
#endif
708 709 710 711 712 713
			if (!(temp & PORT_SUSPEND))
				break;
			if ((temp & PORT_PE) == 0)
				goto error;

			/* clear phy low-power mode before resume */
714
			if (ehci->has_hostpc) {
715 716
				temp1 = ehci_readl(ehci, hostpc_reg);
				ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
A
Alek Du 已提交
717
						hostpc_reg);
718 719 720
				spin_unlock_irqrestore(&ehci->lock, flags);
				msleep(5);/* wait to leave low-power mode */
				spin_lock_irqsave(&ehci->lock, flags);
L
Linus Torvalds 已提交
721
			}
722
			/* resume signaling for 20 msec */
723
			temp &= ~PORT_WAKE_BITS;
724 725 726
			ehci_writel(ehci, temp | PORT_RESUME, status_reg);
			ehci->reset_done[wIndex] = jiffies
					+ msecs_to_jiffies(20);
L
Linus Torvalds 已提交
727 728
			break;
		case USB_PORT_FEAT_C_SUSPEND:
729
			clear_bit(wIndex, &ehci->port_c_suspend);
L
Linus Torvalds 已提交
730 731 732
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC (ehci->hcs_params))
733 734
				ehci_writel(ehci, temp & ~PORT_POWER,
						status_reg);
L
Linus Torvalds 已提交
735 736
			break;
		case USB_PORT_FEAT_C_CONNECTION:
737 738 739 740 741
			if (ehci->has_lpm) {
				/* clear PORTSC bits on disconnect */
				temp &= ~PORT_LPM;
				temp &= ~PORT_DEV_ADDR;
			}
742
			ehci_writel(ehci, temp | PORT_CSC, status_reg);
L
Linus Torvalds 已提交
743 744
			break;
		case USB_PORT_FEAT_C_OVER_CURRENT:
745
			ehci_writel(ehci, temp | PORT_OCC, status_reg);
L
Linus Torvalds 已提交
746 747 748 749 750 751 752
			break;
		case USB_PORT_FEAT_C_RESET:
			/* GetPortStatus clears reset */
			break;
		default:
			goto error;
		}
753
		ehci_readl(ehci, &ehci->regs->command);	/* unblock posted write */
L
Linus Torvalds 已提交
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
		break;
	case GetHubDescriptor:
		ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
			buf);
		break;
	case GetHubStatus:
		/* no hub-wide feature/status flags */
		memset (buf, 0, 4);
		//cpu_to_le32s ((u32 *) buf);
		break;
	case GetPortStatus:
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
		status = 0;
769
		temp = ehci_readl(ehci, status_reg);
L
Linus Torvalds 已提交
770 771 772

		// wPortChange bits
		if (temp & PORT_CSC)
773
			status |= USB_PORT_STAT_C_CONNECTION << 16;
L
Linus Torvalds 已提交
774
		if (temp & PORT_PEC)
775
			status |= USB_PORT_STAT_C_ENABLE << 16;
776 777

		if ((temp & PORT_OCC) && !ignore_oc){
778
			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
L
Linus Torvalds 已提交
779

780 781 782 783 784 785 786
			/*
			 * Hubs should disable port power on over-current.
			 * However, not all EHCI implementations do this
			 * automatically, even if they _do_ support per-port
			 * power switching; they're allowed to just limit the
			 * current.  khubd will turn the power back on.
			 */
787
			if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
788 789 790
				ehci_writel(ehci,
					temp & ~(PORT_RWC_BITS | PORT_POWER),
					status_reg);
791
				temp = ehci_readl(ehci, status_reg);
792 793 794
			}
		}

L
Linus Torvalds 已提交
795
		/* whoever resumes must GetPortStatus to complete it!! */
796 797 798 799 800 801 802 803 804 805 806
		if (temp & PORT_RESUME) {

			/* Remote Wakeup received? */
			if (!ehci->reset_done[wIndex]) {
				/* resume signaling for 20 msec */
				ehci->reset_done[wIndex] = jiffies
						+ msecs_to_jiffies(20);
				/* check the port again */
				mod_timer(&ehci_to_hcd(ehci)->rh_timer,
						ehci->reset_done[wIndex]);
			}
L
Linus Torvalds 已提交
807

808 809 810
			/* resume completed? */
			else if (time_after_eq(jiffies,
					ehci->reset_done[wIndex])) {
811
				clear_bit(wIndex, &ehci->suspended_ports);
812
				set_bit(wIndex, &ehci->port_c_suspend);
813 814 815 816 817
				ehci->reset_done[wIndex] = 0;

				/* stop resume signaling */
				temp = ehci_readl(ehci, status_reg);
				ehci_writel(ehci,
818 819
					temp & ~(PORT_RWC_BITS | PORT_RESUME),
					status_reg);
820
				clear_bit(wIndex, &ehci->resuming_ports);
821
				retval = handshake(ehci, status_reg,
822
					   PORT_RESUME, 0, 2000 /* 2msec */);
823 824 825 826 827 828 829
				if (retval != 0) {
					ehci_err(ehci,
						"port %d resume error %d\n",
						wIndex + 1, retval);
					goto error;
				}
				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
L
Linus Torvalds 已提交
830 831 832 833 834
			}
		}

		/* whoever resets must GetPortStatus to complete it!! */
		if ((temp & PORT_RESET)
835 836
				&& time_after_eq(jiffies,
					ehci->reset_done[wIndex])) {
837
			status |= USB_PORT_STAT_C_RESET << 16;
L
Linus Torvalds 已提交
838
			ehci->reset_done [wIndex] = 0;
839
			clear_bit(wIndex, &ehci->resuming_ports);
L
Linus Torvalds 已提交
840 841

			/* force reset to complete */
842
			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
843
					status_reg);
844 845 846
			/* REVISIT:  some hardware needs 550+ usec to clear
			 * this bit; seems too long to spin routinely...
			 */
847
			retval = handshake(ehci, status_reg,
848
					PORT_RESET, 0, 1000);
L
Linus Torvalds 已提交
849 850 851 852 853 854 855
			if (retval != 0) {
				ehci_err (ehci, "port %d reset error %d\n",
					wIndex + 1, retval);
				goto error;
			}

			/* see what we found out */
856 857
			temp = check_reset_complete (ehci, wIndex, status_reg,
					ehci_readl(ehci, status_reg));
L
Linus Torvalds 已提交
858 859
		}

860
		if (!(temp & (PORT_RESUME|PORT_RESET))) {
861
			ehci->reset_done[wIndex] = 0;
862 863
			clear_bit(wIndex, &ehci->resuming_ports);
		}
864

865 866 867 868 869 870 871 872 873 874
		/* transfer dedicated ports to the companion hc */
		if ((temp & PORT_CONNECT) &&
				test_bit(wIndex, &ehci->companion_ports)) {
			temp &= ~PORT_RWC_BITS;
			temp |= PORT_OWNER;
			ehci_writel(ehci, temp, status_reg);
			ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1);
			temp = ehci_readl(ehci, status_reg);
		}

875 876 877 878 879 880 881
		/*
		 * Even if OWNER is set, there's no harm letting khubd
		 * see the wPortStatus values (they should all be 0 except
		 * for PORT_POWER anyway).
		 */

		if (temp & PORT_CONNECT) {
882
			status |= USB_PORT_STAT_CONNECTION;
883
			// status may be from integrated TT
884 885 886 887 888
			if (ehci->has_hostpc) {
				temp1 = ehci_readl(ehci, hostpc_reg);
				status |= ehci_port_speed(ehci, temp1);
			} else
				status |= ehci_port_speed(ehci, temp);
L
Linus Torvalds 已提交
889
		}
890
		if (temp & PORT_PE)
891
			status |= USB_PORT_STAT_ENABLE;
892 893 894

		/* maybe the port was unsuspended without our knowledge */
		if (temp & (PORT_SUSPEND|PORT_RESUME)) {
895
			status |= USB_PORT_STAT_SUSPEND;
896 897
		} else if (test_bit(wIndex, &ehci->suspended_ports)) {
			clear_bit(wIndex, &ehci->suspended_ports);
898
			clear_bit(wIndex, &ehci->resuming_ports);
899 900 901 902 903
			ehci->reset_done[wIndex] = 0;
			if (temp & PORT_PE)
				set_bit(wIndex, &ehci->port_c_suspend);
		}

904
		if (temp & PORT_OC)
905
			status |= USB_PORT_STAT_OVERCURRENT;
906
		if (temp & PORT_RESET)
907
			status |= USB_PORT_STAT_RESET;
908
		if (temp & PORT_POWER)
909
			status |= USB_PORT_STAT_POWER;
910
		if (test_bit(wIndex, &ehci->port_c_suspend))
911
			status |= USB_PORT_STAT_C_SUSPEND << 16;
L
Linus Torvalds 已提交
912

D
David Brownell 已提交
913
#ifndef	VERBOSE_DEBUG
L
Linus Torvalds 已提交
914 915 916
	if (status & ~0xffff)	/* only if wPortChange is interesting */
#endif
		dbg_port (ehci, "GetStatus", wIndex + 1, temp);
917
		put_unaligned_le32(status, buf);
L
Linus Torvalds 已提交
918 919 920 921 922 923 924 925 926 927 928 929
		break;
	case SetHubFeature:
		switch (wValue) {
		case C_HUB_LOCAL_POWER:
		case C_HUB_OVER_CURRENT:
			/* no hub-wide feature/status flags */
			break;
		default:
			goto error;
		}
		break;
	case SetPortFeature:
930 931
		selector = wIndex >> 8;
		wIndex &= 0xff;
932 933 934 935 936 937 938 939 940
		if (unlikely(ehci->debug)) {
			/* If the debug port is active any port
			 * feature requests should get denied */
			if (wIndex == HCS_DEBUG_PORT(ehci->hcs_params) &&
			    (readl(&ehci->debug->control) & DBGP_ENABLED)) {
				retval = -ENODEV;
				goto error_exit;
			}
		}
L
Linus Torvalds 已提交
941 942 943
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
944
		temp = ehci_readl(ehci, status_reg);
L
Linus Torvalds 已提交
945 946 947
		if (temp & PORT_OWNER)
			break;

D
David Brownell 已提交
948
		temp &= ~PORT_RWC_BITS;
L
Linus Torvalds 已提交
949 950
		switch (wValue) {
		case USB_PORT_FEAT_SUSPEND:
D
David Brownell 已提交
951 952
			if (ehci->no_selective_suspend)
				break;
L
Linus Torvalds 已提交
953 954 955
			if ((temp & PORT_PE) == 0
					|| (temp & PORT_RESET) != 0)
				goto error;
956

957 958 959 960
			/* After above check the port must be connected.
			 * Set appropriate bit thus could put phy into low power
			 * mode if we have hostpc feature
			 */
961 962 963
			temp &= ~PORT_WKCONN_E;
			temp |= PORT_WKDISC_E | PORT_WKOC_E;
			ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
964
			if (ehci->has_hostpc) {
965
				spin_unlock_irqrestore(&ehci->lock, flags);
966
				msleep(5);/* 5ms for HCD enter low pwr mode */
967
				spin_lock_irqsave(&ehci->lock, flags);
968 969 970 971 972 973 974 975
				temp1 = ehci_readl(ehci, hostpc_reg);
				ehci_writel(ehci, temp1 | HOSTPC_PHCD,
					hostpc_reg);
				temp1 = ehci_readl(ehci, hostpc_reg);
				ehci_dbg(ehci, "Port%d phy low pwr mode %s\n",
					wIndex, (temp1 & HOSTPC_PHCD) ?
					"succeeded" : "failed");
			}
976
			set_bit(wIndex, &ehci->suspended_ports);
L
Linus Torvalds 已提交
977 978 979
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC (ehci->hcs_params))
980
				ehci_writel(ehci, temp | PORT_POWER,
981
						status_reg);
L
Linus Torvalds 已提交
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
			break;
		case USB_PORT_FEAT_RESET:
			if (temp & PORT_RESUME)
				goto error;
			/* line status bits may report this as low speed,
			 * which can be fine if this root hub has a
			 * transaction translator built in.
			 */
			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
					&& !ehci_is_TDI(ehci)
					&& PORT_USB11 (temp)) {
				ehci_dbg (ehci,
					"port %d low speed --> companion\n",
					wIndex + 1);
				temp |= PORT_OWNER;
			} else {
				ehci_vdbg (ehci, "port %d reset\n", wIndex + 1);
				temp |= PORT_RESET;
				temp &= ~PORT_PE;

				/*
				 * caller must wait, then call GetPortStatus
				 * usb 2.0 spec says 50 ms resets on root
				 */
				ehci->reset_done [wIndex] = jiffies
						+ msecs_to_jiffies (50);
			}
1009
			ehci_writel(ehci, temp, status_reg);
L
Linus Torvalds 已提交
1010
			break;
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021

		/* For downstream facing ports (these):  one hub port is put
		 * into test mode according to USB2 11.24.2.13, then the hub
		 * must be reset (which for root hub now means rmmod+modprobe,
		 * or else system reboot).  See EHCI 2.3.9 and 4.14 for info
		 * about the EHCI-specific stuff.
		 */
		case USB_PORT_FEAT_TEST:
			if (!selector || selector > 5)
				goto error;
			ehci_quiesce(ehci);
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

			/* Put all enabled ports into suspend */
			while (ports--) {
				u32 __iomem *sreg =
						&ehci->regs->port_status[ports];

				temp = ehci_readl(ehci, sreg) & ~PORT_RWC_BITS;
				if (temp & PORT_PE)
					ehci_writel(ehci, temp | PORT_SUSPEND,
							sreg);
			}
1033
			ehci_halt(ehci);
1034
			temp = ehci_readl(ehci, status_reg);
1035
			temp |= selector << 16;
1036
			ehci_writel(ehci, temp, status_reg);
1037 1038
			break;

L
Linus Torvalds 已提交
1039 1040 1041
		default:
			goto error;
		}
1042
		ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
L
Linus Torvalds 已提交
1043 1044 1045 1046 1047 1048 1049
		break;

	default:
error:
		/* "stall" on error */
		retval = -EPIPE;
	}
1050
error_exit:
L
Linus Torvalds 已提交
1051 1052 1053
	spin_unlock_irqrestore (&ehci->lock, flags);
	return retval;
}
1054

1055 1056
static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
		int portnum)
1057 1058 1059 1060 1061 1062 1063 1064
{
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);

	if (ehci_is_TDI(ehci))
		return;
	set_owner(ehci, --portnum, PORT_OWNER);
}

1065 1066
static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
		int portnum)
1067 1068 1069 1070 1071 1072 1073 1074 1075
{
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	u32 __iomem		*reg;

	if (ehci_is_TDI(ehci))
		return 0;
	reg = &ehci->regs->port_status[portnum - 1];
	return ehci_readl(ehci, reg) & PORT_OWNER;
}