aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2009-08-20 16:39:50 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:38 -0400
commit093344e1362cbf9525a5da09a565f357d8102f3b (patch)
treeb5e7fe63e9a69799c73e25a37e58d69be331463c /drivers/usb
parent87a5d15154ae2389251e6ad99216a846b905375c (diff)
USB: ehci-dbgp: Execute early BIOS hand off
The PCI quirk code executes a BIOS hand off to obtain full control of the EHCI host controller, the self contained ehci-dbgp driver must do the same thing using the early PCI API, else the BIOS can cause a fatal fault. Signed-off-by: Jason Wessel <jason.wessel@windriver.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: dbrownell@users.sourceforge.net Cc: Yinghai Lu <yinghai@kernel.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/early/ehci-dbgp.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 8de709ac0f55..7deae97fe50f 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -435,6 +435,53 @@ static void __init detect_set_debug_port(void)
435 } 435 }
436} 436}
437 437
438/* The code in early_ehci_bios_handoff() is derived from the usb pci
439 * quirk initialization, but altered so as to use the early PCI
440 * routines. */
441#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
442#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
443static void __init early_ehci_bios_handoff(void)
444{
445 u32 hcc_params = readl(&ehci_caps->hcc_params);
446 int offset = (hcc_params >> 8) & 0xff;
447 u32 cap;
448 int msec;
449
450 if (!offset)
451 return;
452
453 cap = read_pci_config(ehci_dev.bus, ehci_dev.slot,
454 ehci_dev.func, offset);
455 dbgp_printk("dbgp: ehci BIOS state %08x\n", cap);
456
457 if ((cap & 0xff) == 1 && (cap & EHCI_USBLEGSUP_BIOS)) {
458 dbgp_printk("dbgp: BIOS handoff\n");
459 write_pci_config_byte(ehci_dev.bus, ehci_dev.slot,
460 ehci_dev.func, offset + 3, 1);
461 }
462
463 /* if boot firmware now owns EHCI, spin till it hands it over. */
464 msec = 1000;
465 while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
466 mdelay(10);
467 msec -= 10;
468 cap = read_pci_config(ehci_dev.bus, ehci_dev.slot,
469 ehci_dev.func, offset);
470 }
471
472 if (cap & EHCI_USBLEGSUP_BIOS) {
473 /* well, possibly buggy BIOS... try to shut it down,
474 * and hope nothing goes too wrong */
475 dbgp_printk("dbgp: BIOS handoff failed: %08x\n", cap);
476 write_pci_config_byte(ehci_dev.bus, ehci_dev.slot,
477 ehci_dev.func, offset + 2, 0);
478 }
479
480 /* just in case, always disable EHCI SMIs */
481 write_pci_config_byte(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
482 offset + EHCI_USBLEGCTLSTS, 0);
483}
484
438static int __init ehci_setup(void) 485static int __init ehci_setup(void)
439{ 486{
440 struct usb_debug_descriptor dbgp_desc; 487 struct usb_debug_descriptor dbgp_desc;
@@ -446,6 +493,8 @@ static int __init ehci_setup(void)
446 int port_map_tried; 493 int port_map_tried;
447 int playtimes = 3; 494 int playtimes = 3;
448 495
496 early_ehci_bios_handoff();
497
449try_next_time: 498try_next_time:
450 port_map_tried = 0; 499 port_map_tried = 0;
451 500