Basically this is getting ready to remove what seems to be some
cargo cult logic that's been carried around since 2.2.early ...
that logic tries to prevent usbcore from seeing anything except
ganged power switching.

The patch doesn't change the default, but it does add a way to
provide more correct hub feature reports (matching what the board
manufacturer programmed):  distrust_firmware=N module option.

I've tested this on several systems and it behaves just fine,
so I suspect someday we can change the default to 'N' from 'Y'.

- Dave
This replaces an undocumented/experimental "power_switching" flag with a
more useful one that lets the driver rely on the boot firmware to report
such capabilities.

The driver still defaults to munging those informational flags (as it has
since 2.2!), so usbcore usually won't try to power-switch with OHCI, but
now we have a simple way to default to the behavior specified by the board
manufacturer.

Also corrects a misprint in the debug 'registers' dump:  a bit was shifted
right by one nibble, so every controller was reported as supporting the
legacy i8042 emulation registers.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>


--- 1.37/drivers/usb/host/ohci-dbg.c	Sat Dec 18 07:22:52 2004
+++ edited/drivers/usb/host/ohci-dbg.c	Thu Jan 20 10:38:48 2005
@@ -138,7 +138,7 @@
 	ohci_dbg_sw (controller, next, size,
 		"OHCI %d.%d, %s legacy support registers\n",
 		0x03 & (temp >> 4), (temp & 0x0f),
-		(temp & 0x10) ? "with" : "NO");
+		(temp & 0x0100) ? "with" : "NO");
 
 	temp = ohci_readl (controller, &regs->control);
 	ohci_dbg_sw (controller, next, size,
--- 1.67/drivers/usb/host/ohci-hcd.c	Wed Jan 12 18:08:34 2005
+++ edited/drivers/usb/host/ohci-hcd.c	Thu Jan 20 10:23:52 2005
@@ -148,10 +148,11 @@
 #include "ohci-q.c"
 
 
-/* Some boards don't support per-port power switching */
-static int power_switching = 0;
-module_param (power_switching, bool, 0);
-MODULE_PARM_DESC (power_switching, "true (not default) to switch port power");
+/* Some boards misreport power switching/overcurrent */
+static int distrust_firmware = 1;
+module_param (distrust_firmware, bool, 0);
+MODULE_PARM_DESC (distrust_firmware,
+	"true to distrust firmware power/overcurrent setup");
 
 /* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */
 static int no_handshake = 0;
@@ -532,8 +533,9 @@
 	// flush the writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
 	msleep(temp);
-	if (power_switching) {
-		unsigned ports = roothub_a (ohci) & RH_A_NDP; 
+	temp = roothub_a (ohci);
+	if (!(temp & RH_A_NPS)) {
+		unsigned ports = temp & RH_A_NDP; 
 
 		/* power down each port */
 		for (temp = 0; temp < ports; temp++)
@@ -624,21 +626,16 @@
 		/* NSC 87560 and maybe others */
 		temp |= RH_A_NOCP;
 		temp &= ~(RH_A_POTPGT | RH_A_NPS);
-	} else if (power_switching) {
-		/* act like most external hubs:  use per-port power
-		 * switching and overcurrent reporting.
-		 */
-		temp &= ~(RH_A_NPS | RH_A_NOCP);
-		temp |= RH_A_PSM | RH_A_OCPM;
-	} else {
+		ohci_writel (ohci, temp, &ohci->regs->roothub.a);
+	} else if ((ohci->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
 		/* hub power always on; required for AMD-756 and some
 		 * Mac platforms.  ganged overcurrent reporting, if any.
 		 */
 		temp |= RH_A_NPS;
+		ohci_writel (ohci, temp, &ohci->regs->roothub.a);
 	}
-	ohci_writel (ohci, temp, &ohci->regs->roothub.a);
 	ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);
-	ohci_writel (ohci, power_switching ? RH_B_PPCM : 0,
+	ohci_writel (ohci, (temp & RH_A_NPS) ? 0 : RH_B_PPCM,
 						&ohci->regs->roothub.b);
 	// flush those writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
@@ -646,7 +643,7 @@
 	spin_unlock_irq (&ohci->lock);
 
 	// POTPGT delay is bits 24-31, in 2 ms units.
-	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+	mdelay ((temp >> 23) & 0x1fe);
 	bus = &ohci_to_hcd(ohci)->self;
 	ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
 

Reply via email to