Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 083522d7 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Greg Kroah-Hartman
Browse files

USB: Implement support for EHCI with big endian MMIO



This patch implements supports for EHCI controllers whose MMIO
registers are big endian and enables that functionality for
the Toshiba SCC chip. It does _not_ add support for big endian
in-memory data structures as this is not needed for that chip
and I hope it will never be.

The guts of the patch are to convert readl(...) to
ehci_readl(ehci, ...) and similarly for register writes.

Signed-off-by: default avatarKou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: default avatarGeoff Levand <geoffrey.levand@am.sony.com>
Acked-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 11d1a4aa
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@ config USB_EHCI_TT_NEWSCHED

	  If unsure, say N.

config USB_EHCI_BIG_ENDIAN_MMIO
	bool
	depends on USB_EHCI_HCD
	default n

config USB_ISP116X_HCD
	tristate "ISP116X HCD support"
	depends on USB
+12 −12
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@
 */
static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
{
	u32	params = readl (&ehci->caps->hcs_params);
	u32	params = ehci_readl(ehci, &ehci->caps->hcs_params);

	ehci_dbg (ehci,
		"%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n",
@@ -87,7 +87,7 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {}
 * */
static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
{
	u32	params = readl (&ehci->caps->hcc_params);
	u32	params = ehci_readl(ehci, &ehci->caps->hcc_params);

	if (HCC_ISOC_CACHE (params)) {
		ehci_dbg (ehci,
@@ -653,7 +653,7 @@ show_registers (struct class_device *class_dev, char *buf)
	}

	/* Capability Registers */
	i = HC_VERSION(readl (&ehci->caps->hc_capbase));
	i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
	temp = scnprintf (next, size,
		"bus %s, device %s (driver " DRIVER_VERSION ")\n"
		"%s\n"
@@ -673,7 +673,7 @@ show_registers (struct class_device *class_dev, char *buf)
		unsigned	count = 256/4;

		pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
		offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
		offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params));
		while (offset && count--) {
			pci_read_config_dword (pdev, offset, &cap);
			switch (cap & 0xff) {
@@ -704,50 +704,50 @@ show_registers (struct class_device *class_dev, char *buf)
#endif

	// FIXME interpret both types of params
	i = readl (&ehci->caps->hcs_params);
	i = ehci_readl(ehci, &ehci->caps->hcs_params);
	temp = scnprintf (next, size, "structural params 0x%08x\n", i);
	size -= temp;
	next += temp;

	i = readl (&ehci->caps->hcc_params);
	i = ehci_readl(ehci, &ehci->caps->hcc_params);
	temp = scnprintf (next, size, "capability params 0x%08x\n", i);
	size -= temp;
	next += temp;

	/* Operational Registers */
	temp = dbg_status_buf (scratch, sizeof scratch, label,
			readl (&ehci->regs->status));
			ehci_readl(ehci, &ehci->regs->status));
	temp = scnprintf (next, size, fmt, temp, scratch);
	size -= temp;
	next += temp;

	temp = dbg_command_buf (scratch, sizeof scratch, label,
			readl (&ehci->regs->command));
			ehci_readl(ehci, &ehci->regs->command));
	temp = scnprintf (next, size, fmt, temp, scratch);
	size -= temp;
	next += temp;

	temp = dbg_intr_buf (scratch, sizeof scratch, label,
			readl (&ehci->regs->intr_enable));
			ehci_readl(ehci, &ehci->regs->intr_enable));
	temp = scnprintf (next, size, fmt, temp, scratch);
	size -= temp;
	next += temp;

	temp = scnprintf (next, size, "uframe %04x\n",
			readl (&ehci->regs->frame_index));
			ehci_readl(ehci, &ehci->regs->frame_index));
	size -= temp;
	next += temp;

	for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {
		temp = dbg_port_buf (scratch, sizeof scratch, label, i,
				readl (&ehci->regs->port_status [i - 1]));
				ehci_readl(ehci, &ehci->regs->port_status [i - 1]));
		temp = scnprintf (next, size, fmt, temp, scratch);
		size -= temp;
		next += temp;
		if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {
			temp = scnprintf (next, size,
					"    debug control %08x\n",
					readl (&ehci->debug->control));
					ehci_readl(ehci, &ehci->debug->control));
			size -= temp;
			next += temp;
		}
+4 −4
Original line number Diff line number Diff line
@@ -177,7 +177,7 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
	case FSL_USB2_PHY_NONE:
		break;
	}
	writel(portsc, &ehci->regs->port_status[port_offset]);
	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
}

static void mpc83xx_usb_setup(struct usb_hcd *hcd)
@@ -214,7 +214,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
	}

	/* put controller in host mode. */
	writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
	ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
@@ -238,12 +238,12 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
	/* EHCI registers start at offset 0x100 */
	ehci->caps = hcd->regs + 0x100;
	ehci->regs = hcd->regs + 0x100 +
	    HC_LENGTH(readl(&ehci->caps->hc_capbase));
	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
	dbg_hcs_params(ehci, "reset");
	dbg_hcc_params(ehci, "reset");

	/* cache this readonly data; minimize chip reads */
	ehci->hcs_params = readl(&ehci->caps->hcs_params);
	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

	retval = ehci_halt(ehci);
	if (retval)
+50 −42
Original line number Diff line number Diff line
@@ -157,12 +157,13 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 * before driver shutdown. But it also seems to be caused by bugs in cardbus
 * bridge shutdown:  shutting down the bridge before the devices using it.
 */
static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec)
static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
		      u32 mask, u32 done, int usec)
{
	u32	result;

	do {
		result = readl (ptr);
		result = ehci_readl(ehci, ptr);
		if (result == ~(u32)0)		/* card removed */
			return -ENODEV;
		result &= mask;
@@ -177,18 +178,19 @@ static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec)
/* force HC to halt state from unknown (EHCI spec section 2.3) */
static int ehci_halt (struct ehci_hcd *ehci)
{
	u32	temp = readl (&ehci->regs->status);
	u32	temp = ehci_readl(ehci, &ehci->regs->status);

	/* disable any irqs left enabled by previous code */
	writel (0, &ehci->regs->intr_enable);
	ehci_writel(ehci, 0, &ehci->regs->intr_enable);

	if ((temp & STS_HALT) != 0)
		return 0;

	temp = readl (&ehci->regs->command);
	temp = ehci_readl(ehci, &ehci->regs->command);
	temp &= ~CMD_RUN;
	writel (temp, &ehci->regs->command);
	return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
	ehci_writel(ehci, temp, &ehci->regs->command);
	return handshake (ehci, &ehci->regs->status,
			  STS_HALT, STS_HALT, 16 * 125);
}

/* put TDI/ARC silicon into EHCI mode */
@@ -198,23 +200,24 @@ static void tdi_reset (struct ehci_hcd *ehci)
	u32		tmp;

	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
	tmp = readl (reg_ptr);
	tmp = ehci_readl(ehci, reg_ptr);
	tmp |= 0x3;
	writel (tmp, reg_ptr);
	ehci_writel(ehci, tmp, reg_ptr);
}

/* reset a non-running (STS_HALT == 1) controller */
static int ehci_reset (struct ehci_hcd *ehci)
{
	int	retval;
	u32	command = readl (&ehci->regs->command);
	u32	command = ehci_readl(ehci, &ehci->regs->command);

	command |= CMD_RESET;
	dbg_cmd (ehci, "reset", command);
	writel (command, &ehci->regs->command);
	ehci_writel(ehci, command, &ehci->regs->command);
	ehci_to_hcd(ehci)->state = HC_STATE_HALT;
	ehci->next_statechange = jiffies;
	retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
	retval = handshake (ehci, &ehci->regs->command,
			    CMD_RESET, 0, 250 * 1000);

	if (retval)
		return retval;
@@ -236,21 +239,21 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
#endif

	/* wait for any schedule enables/disables to take effect */
	temp = readl (&ehci->regs->command) << 10;
	temp = ehci_readl(ehci, &ehci->regs->command) << 10;
	temp &= STS_ASS | STS_PSS;
	if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
	if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
				temp, 16 * 125) != 0) {
		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
		return;
	}

	/* then disable anything that's still active */
	temp = readl (&ehci->regs->command);
	temp = ehci_readl(ehci, &ehci->regs->command);
	temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
	writel (temp, &ehci->regs->command);
	ehci_writel(ehci, temp, &ehci->regs->command);

	/* hardware can take 16 microframes to turn off ... */
	if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
	if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
				0, 16 * 125) != 0) {
		ehci_to_hcd(ehci)->state = HC_STATE_HALT;
		return;
@@ -277,11 +280,11 @@ static void ehci_watchdog (unsigned long param)

	/* lost IAA irqs wedge things badly; seen with a vt8235 */
	if (ehci->reclaim) {
		u32		status = readl (&ehci->regs->status);
		u32		status = ehci_readl(ehci, &ehci->regs->status);
		if (status & STS_IAA) {
			ehci_vdbg (ehci, "lost IAA\n");
			COUNT (ehci->stats.lost_iaa);
			writel (STS_IAA, &ehci->regs->status);
			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
			ehci->reclaim_ready = 1;
		}
	}
@@ -309,7 +312,7 @@ ehci_shutdown (struct usb_hcd *hcd)
	(void) ehci_halt (ehci);

	/* make BIOS/etc use companion controller during reboot */
	writel (0, &ehci->regs->configured_flag);
	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
}

static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -379,11 +382,11 @@ static void ehci_stop (struct usb_hcd *hcd)
		ehci_quiesce (ehci);

	ehci_reset (ehci);
	writel (0, &ehci->regs->intr_enable);
	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
	spin_unlock_irq(&ehci->lock);

	/* let companion controllers work when we aren't */
	writel (0, &ehci->regs->configured_flag);
	ehci_writel(ehci, 0, &ehci->regs->configured_flag);

	remove_debug_files (ehci);

@@ -402,7 +405,8 @@ static void ehci_stop (struct usb_hcd *hcd)
		ehci->stats.complete, ehci->stats.unlink);
#endif

	dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
	dbg_status (ehci, "ehci_stop completed",
		    ehci_readl(ehci, &ehci->regs->status));
}

/* one-time init, only for memory state */
@@ -428,7 +432,7 @@ static int ehci_init(struct usb_hcd *hcd)
		return retval;

	/* controllers may cache some of the periodic schedule ... */
	hcc_params = readl(&ehci->caps->hcc_params);
	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
	if (HCC_ISOC_CACHE(hcc_params))		// full frame cache
		ehci->i_thresh = 8;
	else					// N microframes cached
@@ -501,8 +505,8 @@ static int ehci_run (struct usb_hcd *hcd)
		ehci_mem_cleanup(ehci);
		return retval;
	}
	writel(ehci->periodic_dma, &ehci->regs->frame_list);
	writel((u32)ehci->async->qh_dma, &ehci->regs->async_next);
	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);

	/*
	 * hcc_params controls whether ehci->regs->segment must (!!!)
@@ -516,9 +520,9 @@ static int ehci_run (struct usb_hcd *hcd)
	 * Scsi_Host.highmem_io, and so forth.  It's readonly to all
	 * host side drivers though.
	 */
	hcc_params = readl(&ehci->caps->hcc_params);
	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
	if (HCC_64BIT_ADDR(hcc_params)) {
		writel(0, &ehci->regs->segment);
		ehci_writel(ehci, 0, &ehci->regs->segment);
#if 0
// this is deeply broken on almost all architectures
		if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK))
@@ -531,7 +535,7 @@ static int ehci_run (struct usb_hcd *hcd)
	// root hub will detect new devices (why?); NEC doesn't
	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
	ehci->command |= CMD_RUN;
	writel (ehci->command, &ehci->regs->command);
	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	dbg_cmd (ehci, "init", ehci->command);

	/*
@@ -541,17 +545,18 @@ static int ehci_run (struct usb_hcd *hcd)
	 * and there's no companion controller unless maybe for USB OTG.)
	 */
	hcd->state = HC_STATE_RUNNING;
	writel (FLAG_CF, &ehci->regs->configured_flag);
	readl (&ehci->regs->command);	/* unblock posted writes */
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

	temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
	temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
	ehci_info (ehci,
		"USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
		temp >> 8, temp & 0xff, DRIVER_VERSION,
		ignore_oc ? ", overcurrent ignored" : "");

	writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
	ehci_writel(ehci, INTR_MASK,
		    &ehci->regs->intr_enable); /* Turn On Interrupts */

	/* GRR this is run-once init(), being done every time the HC starts.
	 * So long as they're part of class devices, we can't do it init()
@@ -572,7 +577,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)

	spin_lock (&ehci->lock);

	status = readl (&ehci->regs->status);
	status = ehci_readl(ehci, &ehci->regs->status);

	/* e.g. cardbus physical eject */
	if (status == ~(u32) 0) {
@@ -587,8 +592,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
	}

	/* clear (just) interrupts */
	writel (status, &ehci->regs->status);
	readl (&ehci->regs->command);	/* unblock posted write */
	ehci_writel(ehci, status, &ehci->regs->status);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted write */
	bh = 0;

#ifdef	EHCI_VERBOSE_DEBUG
@@ -619,11 +624,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
		unsigned	i = HCS_N_PORTS (ehci->hcs_params);

		/* resume root hub? */
		if (!(readl(&ehci->regs->command) & CMD_RUN))
		if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN))
			usb_hcd_resume_root_hub(hcd);

		while (i--) {
			int pstatus = readl (&ehci->regs->port_status [i]);
			int pstatus = ehci_readl(ehci,
						 &ehci->regs->port_status [i]);

			if (pstatus & PORT_OWNER)
				continue;
@@ -643,14 +649,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
	/* PCI errors [4.15.2.4] */
	if (unlikely ((status & STS_FATAL) != 0)) {
		/* bogus "fatal" IRQs appear on some chips... why?  */
		status = readl (&ehci->regs->status);
		dbg_cmd (ehci, "fatal", readl (&ehci->regs->command));
		status = ehci_readl(ehci, &ehci->regs->status);
		dbg_cmd (ehci, "fatal", ehci_readl(ehci,
						   &ehci->regs->command));
		dbg_status (ehci, "fatal", status);
		if (status & STS_HALT) {
			ehci_err (ehci, "fatal error\n");
dead:
			ehci_reset (ehci);
			writel (0, &ehci->regs->configured_flag);
			ehci_writel(ehci, 0, &ehci->regs->configured_flag);
			/* generic layer kills/unlinks all urbs, then
			 * uses ehci_stop to clean up the rest
			 */
@@ -873,7 +880,8 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
static int ehci_get_frame (struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
	return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
	return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) %
		ehci->periodic_size;
}

/*-------------------------------------------------------------------------*/
+63 −55
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
		ehci_quiesce (ehci);
		hcd->state = HC_STATE_QUIESCING;
	}
	ehci->command = readl (&ehci->regs->command);
	ehci->command = ehci_readl(ehci, &ehci->regs->command);
	if (ehci->reclaim)
		ehci->reclaim_ready = 1;
	ehci_work(ehci);
@@ -60,7 +60,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
	ehci->bus_suspended = 0;
	while (port--) {
		u32 __iomem	*reg = &ehci->regs->port_status [port];
		u32		t1 = readl (reg) & ~PORT_RWC_BITS;
		u32		t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
		u32		t2 = t1;

		/* keep track of which ports we suspend */
@@ -79,7 +79,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
		if (t1 != t2) {
			ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
				port + 1, t1, t2);
			writel (t2, reg);
			ehci_writel(ehci, t2, reg);
		}
	}

@@ -92,8 +92,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
	mask = INTR_MASK;
	if (!device_may_wakeup(&hcd->self.root_hub->dev))
		mask &= ~STS_PCD;
	writel(mask, &ehci->regs->intr_enable);
	readl(&ehci->regs->intr_enable);
	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
	ehci_readl(ehci, &ehci->regs->intr_enable);

	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
	spin_unlock_irq (&ehci->lock);
@@ -118,26 +118,26 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
	 * the last user of the controller, not reset/pm hardware keeping
	 * state we gave to it.
	 */
	temp = readl(&ehci->regs->intr_enable);
	temp = ehci_readl(ehci, &ehci->regs->intr_enable);
	ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");

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

	/* re-init operational registers */
	writel(0, &ehci->regs->segment);
	writel(ehci->periodic_dma, &ehci->regs->frame_list);
	writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
	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);

	/* restore CMD_RUN, framelist size, and irq threshold */
	writel (ehci->command, &ehci->regs->command);
	ehci_writel(ehci, ehci->command, &ehci->regs->command);

	/* manually resume the ports we suspended during bus_suspend() */
	i = HCS_N_PORTS (ehci->hcs_params);
	while (i--) {
		temp = readl (&ehci->regs->port_status [i]);
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
		temp &= ~(PORT_RWC_BITS
			| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
		if (test_bit(i, &ehci->bus_suspended) &&
@@ -145,20 +145,20 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
			ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
			temp |= PORT_RESUME;
		}
		writel (temp, &ehci->regs->port_status [i]);
		ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
	}
	i = HCS_N_PORTS (ehci->hcs_params);
	mdelay (20);
	while (i--) {
		temp = readl (&ehci->regs->port_status [i]);
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
		if (test_bit(i, &ehci->bus_suspended) &&
				(temp & PORT_SUSPEND)) {
			temp &= ~(PORT_RWC_BITS | PORT_RESUME);
			writel (temp, &ehci->regs->port_status [i]);
			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
			ehci_vdbg (ehci, "resumed port %d\n", i + 1);
		}
	}
	(void) readl (&ehci->regs->command);
	(void) ehci_readl(ehci, &ehci->regs->command);

	/* maybe re-activate the schedule(s) */
	temp = 0;
@@ -168,14 +168,14 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
		temp |= CMD_PSE;
	if (temp) {
		ehci->command |= temp;
		writel (ehci->command, &ehci->regs->command);
		ehci_writel(ehci, ehci->command, &ehci->regs->command);
	}

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

	/* Now we can safely re-enable irqs */
	writel(INTR_MASK, &ehci->regs->intr_enable);
	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);

	spin_unlock_irq (&ehci->lock);
	return 0;
@@ -217,7 +217,8 @@ static int check_reset_complete (
		// what happens if HCS_N_CC(params) == 0 ?
		port_status |= PORT_OWNER;
		port_status &= ~PORT_RWC_BITS;
		writel (port_status, &ehci->regs->port_status [index]);
		ehci_writel(ehci, port_status,
			    &ehci->regs->port_status [index]);

	} else
		ehci_dbg (ehci, "port %d high speed\n", index + 1);
@@ -268,13 +269,14 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
	/* port N changes (bit N)? */
	spin_lock_irqsave (&ehci->lock, flags);
	for (i = 0; i < ports; i++) {
		temp = readl (&ehci->regs->port_status [i]);
		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
		if (temp & PORT_OWNER) {
			/* don't report this in GetPortStatus */
			if (temp & PORT_CSC) {
				temp &= ~PORT_RWC_BITS;
				temp |= PORT_CSC;
				writel (temp, &ehci->regs->port_status [i]);
				ehci_writel(ehci, temp,
					    &ehci->regs->port_status [i]);
			}
			continue;
		}
@@ -373,17 +375,17 @@ static int ehci_hub_control (
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
		temp = readl (&ehci->regs->port_status [wIndex]);
		temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
		if (temp & PORT_OWNER)
			break;

		switch (wValue) {
		case USB_PORT_FEAT_ENABLE:
			writel (temp & ~PORT_PE,
			ehci_writel(ehci, temp & ~PORT_PE,
				    &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_ENABLE:
			writel((temp & ~PORT_RWC_BITS) | PORT_PEC,
			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC,
				    &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_SUSPEND:
@@ -396,7 +398,7 @@ static int ehci_hub_control (
					goto error;
				/* resume signaling for 20 msec */
				temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
				writel (temp | PORT_RESUME,
				ehci_writel(ehci, temp | PORT_RESUME,
					    &ehci->regs->port_status [wIndex]);
				ehci->reset_done [wIndex] = jiffies
						+ msecs_to_jiffies (20);
@@ -407,15 +409,16 @@ static int ehci_hub_control (
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC (ehci->hcs_params))
				writel (temp & ~(PORT_RWC_BITS | PORT_POWER),
				ehci_writel(ehci,
					  temp & ~(PORT_RWC_BITS | PORT_POWER),
					  &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_CONNECTION:
			writel((temp & ~PORT_RWC_BITS) | PORT_CSC,
			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
				    &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_OVER_CURRENT:
			writel((temp & ~PORT_RWC_BITS) | PORT_OCC,
			ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC,
				    &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_C_RESET:
@@ -424,7 +427,7 @@ static int ehci_hub_control (
		default:
			goto error;
		}
		readl (&ehci->regs->command);	/* unblock posted write */
		ehci_readl(ehci, &ehci->regs->command);	/* unblock posted write */
		break;
	case GetHubDescriptor:
		ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
@@ -440,7 +443,7 @@ static int ehci_hub_control (
			goto error;
		wIndex--;
		status = 0;
		temp = readl (&ehci->regs->port_status [wIndex]);
		temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);

		// wPortChange bits
		if (temp & PORT_CSC)
@@ -458,10 +461,12 @@ static int ehci_hub_control (
			ehci->reset_done [wIndex] = 0;

			/* stop resume signaling */
			temp = readl (&ehci->regs->port_status [wIndex]);
			writel (temp & ~(PORT_RWC_BITS | PORT_RESUME),
			temp = ehci_readl(ehci,
					  &ehci->regs->port_status [wIndex]);
			retval = handshake (
			ehci_writel(ehci,
				    temp & ~(PORT_RWC_BITS | PORT_RESUME),
				    &ehci->regs->port_status [wIndex]);
			retval = handshake(ehci,
					   &ehci->regs->port_status [wIndex],
					   PORT_RESUME, 0, 2000 /* 2msec */);
			if (retval != 0) {
@@ -480,12 +485,12 @@ static int ehci_hub_control (
			ehci->reset_done [wIndex] = 0;

			/* force reset to complete */
			writel (temp & ~(PORT_RWC_BITS | PORT_RESET),
			ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
				    &ehci->regs->port_status [wIndex]);
			/* REVISIT:  some hardware needs 550+ usec to clear
			 * this bit; seems too long to spin routinely...
			 */
			retval = handshake (
			retval = handshake(ehci,
					   &ehci->regs->port_status [wIndex],
					PORT_RESET, 0, 750);
			if (retval != 0) {
@@ -496,7 +501,8 @@ static int ehci_hub_control (

			/* see what we found out */
			temp = check_reset_complete (ehci, wIndex,
				readl (&ehci->regs->port_status [wIndex]));
				ehci_readl(ehci,
					   &ehci->regs->port_status [wIndex]));
		}

		// don't show wPortStatus if it's owned by a companion hc
@@ -541,7 +547,7 @@ static int ehci_hub_control (
		if (!wIndex || wIndex > ports)
			goto error;
		wIndex--;
		temp = readl (&ehci->regs->port_status [wIndex]);
		temp = ehci_readl(ehci, &ehci->regs->port_status [wIndex]);
		if (temp & PORT_OWNER)
			break;

@@ -555,12 +561,12 @@ static int ehci_hub_control (
				goto error;
			if (device_may_wakeup(&hcd->self.root_hub->dev))
				temp |= PORT_WAKE_BITS;
			writel (temp | PORT_SUSPEND,
			ehci_writel(ehci, temp | PORT_SUSPEND,
				    &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_POWER:
			if (HCS_PPC (ehci->hcs_params))
				writel (temp | PORT_POWER,
				ehci_writel(ehci, temp | PORT_POWER,
					    &ehci->regs->port_status [wIndex]);
			break;
		case USB_PORT_FEAT_RESET:
@@ -589,7 +595,8 @@ static int ehci_hub_control (
				ehci->reset_done [wIndex] = jiffies
						+ msecs_to_jiffies (50);
			}
			writel (temp, &ehci->regs->port_status [wIndex]);
			ehci_writel(ehci, temp,
				    &ehci->regs->port_status [wIndex]);
			break;

		/* For downstream facing ports (these):  one hub port is put
@@ -604,13 +611,14 @@ static int ehci_hub_control (
			ehci_quiesce(ehci);
			ehci_halt(ehci);
			temp |= selector << 16;
			writel (temp, &ehci->regs->port_status [wIndex]);
			ehci_writel(ehci, temp,
				    &ehci->regs->port_status [wIndex]);
			break;

		default:
			goto error;
		}
		readl (&ehci->regs->command);	/* unblock posted writes */
		ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
		break;

	default:
Loading