diff options
author | David Brownell <david-b@pacbell.net> | 2005-08-31 14:52:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-09-12 15:23:46 -0400 |
commit | fdd13b36c4a501d8787a27e54635fbd943f2685d (patch) | |
tree | eebcc2fc677b5b625235e2e0797b5f9ab6d74905 /drivers/usb | |
parent | e0fd3cbc50a8c925e8e7d8448df689015362c458 (diff) |
[PATCH] USB: OHCI relies less on NDP register
Some OHCI implementations have differences in the way the NDP register
(in roothub_a) reports the number of ports present. This patch allows the
platform specific code to optionally supply the number of ports. The
driver just reads the value at init (if not supplied) instead of reading
it every time its needed (except for an AMD756 bug workaround).
It also sets the value correctly for the ARM pxa27x architecture.
Signed-Off-By: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ohci-dbg.c | 9 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hub.c | 22 | ||||
-rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 1 |
5 files changed, 25 insertions, 20 deletions
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 ( | |||
228 | char **next, | 228 | char **next, |
229 | unsigned *size) | 229 | unsigned *size) |
230 | { | 230 | { |
231 | u32 temp, ndp, i; | 231 | u32 temp, i; |
232 | 232 | ||
233 | temp = roothub_a (controller); | 233 | temp = roothub_a (controller); |
234 | if (temp == ~(u32)0) | 234 | if (temp == ~(u32)0) |
235 | return; | 235 | return; |
236 | ndp = (temp & RH_A_NDP); | ||
237 | 236 | ||
238 | if (verbose) { | 237 | if (verbose) { |
239 | ohci_dbg_sw (controller, next, size, | 238 | ohci_dbg_sw (controller, next, size, |
240 | "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, | 239 | "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp, |
241 | ((temp & RH_A_POTPGT) >> 24) & 0xff, | 240 | ((temp & RH_A_POTPGT) >> 24) & 0xff, |
242 | (temp & RH_A_NOCP) ? " NOCP" : "", | 241 | (temp & RH_A_NOCP) ? " NOCP" : "", |
243 | (temp & RH_A_OCPM) ? " OCPM" : "", | 242 | (temp & RH_A_OCPM) ? " OCPM" : "", |
244 | (temp & RH_A_DT) ? " DT" : "", | 243 | (temp & RH_A_DT) ? " DT" : "", |
245 | (temp & RH_A_NPS) ? " NPS" : "", | 244 | (temp & RH_A_NPS) ? " NPS" : "", |
246 | (temp & RH_A_PSM) ? " PSM" : "", | 245 | (temp & RH_A_PSM) ? " PSM" : "", |
247 | ndp | 246 | (temp & RH_A_NDP), controller->num_ports |
248 | ); | 247 | ); |
249 | temp = roothub_b (controller); | 248 | temp = roothub_b (controller); |
250 | ohci_dbg_sw (controller, next, size, | 249 | ohci_dbg_sw (controller, next, size, |
@@ -266,7 +265,7 @@ ohci_dump_roothub ( | |||
266 | ); | 265 | ); |
267 | } | 266 | } |
268 | 267 | ||
269 | for (i = 0; i < ndp; i++) { | 268 | for (i = 0; i < controller->num_ports; i++) { |
270 | temp = roothub_portstatus (controller, i); | 269 | temp = roothub_portstatus (controller, i); |
271 | dbg_port_sw (controller, i, temp, next, size); | 270 | dbg_port_sw (controller, i, temp, next, size); |
272 | } | 271 | } |
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) | |||
484 | // flush the writes | 484 | // flush the writes |
485 | (void) ohci_readl (ohci, &ohci->regs->control); | 485 | (void) ohci_readl (ohci, &ohci->regs->control); |
486 | 486 | ||
487 | /* Read the number of ports unless overridden */ | ||
488 | if (ohci->num_ports == 0) | ||
489 | ohci->num_ports = roothub_a(ohci) & RH_A_NDP; | ||
490 | |||
487 | if (ohci->hcca) | 491 | if (ohci->hcca) |
488 | return 0; | 492 | return 0; |
489 | 493 | ||
@@ -560,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
560 | msleep(temp); | 564 | msleep(temp); |
561 | temp = roothub_a (ohci); | 565 | temp = roothub_a (ohci); |
562 | if (!(temp & RH_A_NPS)) { | 566 | if (!(temp & RH_A_NPS)) { |
563 | unsigned ports = temp & RH_A_NDP; | ||
564 | |||
565 | /* power down each port */ | 567 | /* power down each port */ |
566 | for (temp = 0; temp < ports; temp++) | 568 | for (temp = 0; temp < ohci->num_ports; temp++) |
567 | ohci_writel (ohci, RH_PS_LSDA, | 569 | ohci_writel (ohci, RH_PS_LSDA, |
568 | &ohci->regs->roothub.portstatus [temp]); | 570 | &ohci->regs->roothub.portstatus [temp]); |
569 | } | 571 | } |
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
861 | * and that if we try to turn them back on the root hub | 863 | * and that if we try to turn them back on the root hub |
862 | * will respond to CSC processing. | 864 | * will respond to CSC processing. |
863 | */ | 865 | */ |
864 | i = roothub_a (ohci) & RH_A_NDP; | 866 | i = ohci->num_ports; |
865 | while (i--) | 867 | while (i--) |
866 | ohci_writel (ohci, RH_PS_PSS, | 868 | ohci_writel (ohci, RH_PS_PSS, |
867 | &ohci->regs->roothub.portstatus [temp]); | 869 | &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) | |||
184 | if (status != -EINPROGRESS) | 184 | if (status != -EINPROGRESS) |
185 | return status; | 185 | return status; |
186 | 186 | ||
187 | temp = roothub_a (ohci) & RH_A_NDP; | 187 | temp = ohci->num_ports; |
188 | enables = 0; | 188 | enables = 0; |
189 | while (temp--) { | 189 | while (temp--) { |
190 | u32 stat = ohci_readl (ohci, | 190 | u32 stat = ohci_readl (ohci, |
@@ -304,7 +304,7 @@ static int | |||
304 | ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | 304 | ohci_hub_status_data (struct usb_hcd *hcd, char *buf) |
305 | { | 305 | { |
306 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 306 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
307 | int ports, i, changed = 0, length = 1; | 307 | int i, changed = 0, length = 1; |
308 | int can_suspend = hcd->can_wakeup; | 308 | int can_suspend = hcd->can_wakeup; |
309 | unsigned long flags; | 309 | unsigned long flags; |
310 | 310 | ||
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
319 | goto done; | 319 | goto done; |
320 | } | 320 | } |
321 | 321 | ||
322 | ports = roothub_a (ohci) & RH_A_NDP; | 322 | /* undocumented erratum seen on at least rev D */ |
323 | if (ports > MAX_ROOT_PORTS) { | 323 | if ((ohci->flags & OHCI_QUIRK_AMD756) |
324 | ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, | 324 | && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { |
325 | ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n", | ||
325 | ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); | 326 | ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); |
326 | /* retry later; "should not happen" */ | 327 | /* retry later; "should not happen" */ |
327 | goto done; | 328 | goto done; |
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
332 | buf [0] = changed = 1; | 333 | buf [0] = changed = 1; |
333 | else | 334 | else |
334 | buf [0] = 0; | 335 | buf [0] = 0; |
335 | if (ports > 7) { | 336 | if (ohci->num_ports > 7) { |
336 | buf [1] = 0; | 337 | buf [1] = 0; |
337 | length++; | 338 | length++; |
338 | } | 339 | } |
339 | 340 | ||
340 | /* look at each port */ | 341 | /* look at each port */ |
341 | for (i = 0; i < ports; i++) { | 342 | for (i = 0; i < ohci->num_ports; i++) { |
342 | u32 status = roothub_portstatus (ohci, i); | 343 | u32 status = roothub_portstatus (ohci, i); |
343 | 344 | ||
344 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | 345 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC |
@@ -395,15 +396,14 @@ ohci_hub_descriptor ( | |||
395 | struct usb_hub_descriptor *desc | 396 | struct usb_hub_descriptor *desc |
396 | ) { | 397 | ) { |
397 | u32 rh = roothub_a (ohci); | 398 | u32 rh = roothub_a (ohci); |
398 | int ports = rh & RH_A_NDP; | ||
399 | u16 temp; | 399 | u16 temp; |
400 | 400 | ||
401 | desc->bDescriptorType = 0x29; | 401 | desc->bDescriptorType = 0x29; |
402 | desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; | 402 | desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; |
403 | desc->bHubContrCurrent = 0; | 403 | desc->bHubContrCurrent = 0; |
404 | 404 | ||
405 | desc->bNbrPorts = ports; | 405 | desc->bNbrPorts = ohci->num_ports; |
406 | temp = 1 + (ports / 8); | 406 | temp = 1 + (ohci->num_ports / 8); |
407 | desc->bDescLength = 7 + 2 * temp; | 407 | desc->bDescLength = 7 + 2 * temp; |
408 | 408 | ||
409 | temp = 0; | 409 | temp = 0; |
@@ -421,7 +421,7 @@ ohci_hub_descriptor ( | |||
421 | rh = roothub_b (ohci); | 421 | rh = roothub_b (ohci); |
422 | memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); | 422 | memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); |
423 | desc->bitmap [0] = rh & RH_B_DR; | 423 | desc->bitmap [0] = rh & RH_B_DR; |
424 | if (ports > 7) { | 424 | if (ohci->num_ports > 7) { |
425 | desc->bitmap [1] = (rh & RH_B_DR) >> 8; | 425 | desc->bitmap [1] = (rh & RH_B_DR) >> 8; |
426 | desc->bitmap [2] = 0xff; | 426 | desc->bitmap [2] = 0xff; |
427 | } else | 427 | } 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) | |||
258 | 258 | ||
259 | ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); | 259 | ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); |
260 | 260 | ||
261 | /* The value of NDP in roothub_a is incorrect on this hardware */ | ||
262 | ohci->num_ports = 3; | ||
263 | |||
261 | if ((ret = ohci_init(ohci)) < 0) | 264 | if ((ret = ohci_init(ohci)) < 0) |
262 | return ret; | 265 | return ret; |
263 | 266 | ||
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 { | |||
383 | /* | 383 | /* |
384 | * driver state | 384 | * driver state |
385 | */ | 385 | */ |
386 | int num_ports; | ||
386 | int load [NUM_INTS]; | 387 | int load [NUM_INTS]; |
387 | u32 hc_control; /* copy of hc control reg */ | 388 | u32 hc_control; /* copy of hc control reg */ |
388 | unsigned long next_statechange; /* suspend/resume */ | 389 | unsigned long next_statechange; /* suspend/resume */ |