lkml.org 
[lkml]   [2009]   [Jul]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 03/10] ehci-dbgp: Execute early BIOS hand off
Date
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: Greg KH <gregkh@suse.de>
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>
---
drivers/usb/early/ehci-dbgp.c | 49 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 51ec414..f4bfe31 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)
}
}

+/* The code in early_ehci_bios_handoff() is derived from the usb pci
+ * quirk initialization, but altered so as to use the early PCI
+ * routines. */
+#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
+#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
+static void __init early_ehci_bios_handoff(void)
+{
+ u32 hcc_params = readl(&ehci_caps->hcc_params);
+ int offset = (hcc_params >> 8) & 0xff;
+ u32 cap;
+ int msec;
+
+ if (!offset)
+ return;
+
+ cap = read_pci_config(ehci_dev.bus, ehci_dev.slot,
+ ehci_dev.func, offset);
+ dbgp_printk("dbgp: ehci BIOS state %08x\n", cap);
+
+ if ((cap & 0xff) == 1 && (cap & EHCI_USBLEGSUP_BIOS)) {
+ dbgp_printk("dbgp: BIOS handoff\n");
+ write_pci_config_byte(ehci_dev.bus, ehci_dev.slot,
+ ehci_dev.func, offset + 3, 1);
+ }
+
+ /* if boot firmware now owns EHCI, spin till it hands it over. */
+ msec = 1000;
+ while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
+ mdelay(10);
+ msec -= 10;
+ cap = read_pci_config(ehci_dev.bus, ehci_dev.slot,
+ ehci_dev.func, offset);
+ }
+
+ if (cap & EHCI_USBLEGSUP_BIOS) {
+ /* well, possibly buggy BIOS... try to shut it down,
+ * and hope nothing goes too wrong */
+ dbgp_printk("dbgp: BIOS handoff failed: %08x\n", cap);
+ write_pci_config_byte(ehci_dev.bus, ehci_dev.slot,
+ ehci_dev.func, offset + 2, 0);
+ }
+
+ /* just in case, always disable EHCI SMIs */
+ write_pci_config_byte(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
+ offset + EHCI_USBLEGCTLSTS, 0);
+}
+
static int __init ehci_setup(void)
{
struct usb_debug_descriptor dbgp_desc;
@@ -446,6 +493,8 @@ static int __init ehci_setup(void)
int port_map_tried;
int playtimes = 3;

+ early_ehci_bios_handoff();
+
try_next_time:
port_map_tried = 0;

--
1.6.0.3.523.g304d0


\
 
 \ /
  Last update: 2009-07-31 17:15    [W:0.064 / U:2.808 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site