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 | |
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')
-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 447f488f5d..7924c74f95 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 6efb69f7c0..67c1aa5eb1 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 83ca4549a5..ce7b28da7a 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 e5bc1789d1..5dd20dbe85 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 71cdd22628..8a9b9d9209 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 */ |