diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 447f488f5d93..7924c74f958e 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -228,23 +228,22 @@ ohci_dump_roothub (
 	char **next,
 	unsigned *size)
 {
-	u32			temp, ndp, i;
+	u32			temp, i;
 
 	temp = roothub_a (controller);
 	if (temp == ~(u32)0)
 		return;
-	ndp = (temp & RH_A_NDP);
 
 	if (verbose) {
 		ohci_dbg_sw (controller, next, size,
-			"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+			"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
 			((temp & RH_A_POTPGT) >> 24) & 0xff,
 			(temp & RH_A_NOCP) ? " NOCP" : "",
 			(temp & RH_A_OCPM) ? " OCPM" : "",
 			(temp & RH_A_DT) ? " DT" : "",
 			(temp & RH_A_NPS) ? " NPS" : "",
 			(temp & RH_A_PSM) ? " PSM" : "",
-			ndp
+			(temp & RH_A_NDP), controller->num_ports
 			);
 		temp = roothub_b (controller);
 		ohci_dbg_sw (controller, next, size,
@@ -266,7 +265,7 @@ ohci_dump_roothub (
 			);
 	}
 
-	for (i = 0; i < ndp; i++) {
+	for (i = 0; i < controller->num_ports; i++) {
 		temp = roothub_portstatus (controller, i);
 		dbg_port_sw (controller, i, temp, next, size);
 	}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 6efb69f7c075..67c1aa5eb1c1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -484,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
 	// flush the writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
 
+	/* Read the number of ports unless overridden */
+	if (ohci->num_ports == 0)
+		ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
+
 	if (ohci->hcca)
 		return 0;
 
@@ -560,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
 	msleep(temp);
 	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++)
+		for (temp = 0; temp < ohci->num_ports; temp++)
 			ohci_writel (ohci, RH_PS_LSDA,
 				&ohci->regs->roothub.portstatus [temp]);
 	}
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
 		 * and that if we try to turn them back on the root hub
 		 * will respond to CSC processing.
 		 */
-		i = roothub_a (ohci) & RH_A_NDP;
+		i = ohci->num_ports;
 		while (i--)
 			ohci_writel (ohci, RH_PS_PSS,
 				&ohci->regs->roothub.portstatus [temp]);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 83ca4549a50e..ce7b28da7a15 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
 	if (status != -EINPROGRESS)
 		return status;
 
-	temp = roothub_a (ohci) & RH_A_NDP;
+	temp = ohci->num_ports;
 	enables = 0;
 	while (temp--) {
 		u32 stat = ohci_readl (ohci,
@@ -304,7 +304,7 @@ static int
 ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports, i, changed = 0, length = 1;
+	int		i, changed = 0, length = 1;
 	int		can_suspend = hcd->can_wakeup;
 	unsigned long	flags;
 
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 		goto done;
 	}
 
-	ports = roothub_a (ohci) & RH_A_NDP; 
-	if (ports > MAX_ROOT_PORTS) {
-		ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
+	/* undocumented erratum seen on at least rev D */
+	if ((ohci->flags & OHCI_QUIRK_AMD756)
+			&& (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+		ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
 			  ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
 		/* retry later; "should not happen" */
 		goto done;
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 		buf [0] = changed = 1;
 	else
 		buf [0] = 0;
-	if (ports > 7) {
+	if (ohci->num_ports > 7) {
 		buf [1] = 0;
 		length++;
 	}
 
 	/* look at each port */
-	for (i = 0; i < ports; i++) {
+	for (i = 0; i < ohci->num_ports; i++) {
 		u32	status = roothub_portstatus (ohci, i);
 
 		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -395,15 +396,14 @@ ohci_hub_descriptor (
 	struct usb_hub_descriptor	*desc
 ) {
 	u32		rh = roothub_a (ohci);
-	int		ports = rh & RH_A_NDP; 
 	u16		temp;
 
 	desc->bDescriptorType = 0x29;
 	desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
 	desc->bHubContrCurrent = 0;
 
-	desc->bNbrPorts = ports;
-	temp = 1 + (ports / 8);
+	desc->bNbrPorts = ohci->num_ports;
+	temp = 1 + (ohci->num_ports / 8);
 	desc->bDescLength = 7 + 2 * temp;
 
 	temp = 0;
@@ -421,7 +421,7 @@ ohci_hub_descriptor (
 	rh = roothub_b (ohci);
 	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
 	desc->bitmap [0] = rh & RH_B_DR;
-	if (ports > 7) {
+	if (ohci->num_ports > 7) {
 		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
 		desc->bitmap [2] = 0xff;
 	} else
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e5bc1789d18a..5dd20dbe852d 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -258,6 +258,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
 
 	ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
 
+	/* The value of NDP in roothub_a is incorrect on this hardware */
+	ohci->num_ports = 3;
+
 	if ((ret = ohci_init(ohci)) < 0)
 		return ret;
 
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 71cdd2262860..8a9b9d9209e9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -383,6 +383,7 @@ struct ohci_hcd {
 	/*
 	 * driver state
 	 */
+	int			num_ports;
 	int			load [NUM_INTS];
 	u32 			hc_control;	/* copy of hc control reg */
 	unsigned long		next_statechange;	/* suspend/resume */