|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 2/3] drivers/char: search all buses for xhci
On (at least some) AMD systems, XHCI isn't on bus 0 (in my case, it was
bus 4). Search all of them.
Signed-off-by: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
---
xen/drivers/char/xhci-dbc.c | 84 +++++++++++++++++++++++++++++---------
1 file changed, 66 insertions(+), 18 deletions(-)
diff --git a/xen/drivers/char/xhci-dbc.c b/xen/drivers/char/xhci-dbc.c
index 60b781f87202..62b0ce88b6bf 100644
--- a/xen/drivers/char/xhci-dbc.c
+++ b/xen/drivers/char/xhci-dbc.c
@@ -286,39 +286,87 @@ static void *dbc_sys_map_xhc(uint64_t phys, size_t size)
return fix_to_virt(FIX_XHCI_END);
}
+static void xhci_bios_handoff(struct dbc *dbc)
+{
+ const uint32_t __iomem *xcap;
+ uint32_t xcap_val;
+ uint32_t next;
+ uint32_t id = 0;
+ const void __iomem *mmio = dbc->xhc_mmio;
+ const uint32_t __iomem *hccp1 = mmio + 0x10;
+ const uint32_t LEGACY_ID = 0x1;
+ int ttl = 48;
+ int timeout = 10000;
+
+ xcap = mmio;
+ /*
+ * This is initially an offset to the first capability. All the offsets
+ * (both in HCCP1 and then next capability pointer) are dword-based.
+ */
+ next = (readl(hccp1) & 0xFFFF0000) >> 16;
+
+ while ( id != LEGACY_ID && next && ttl-- )
+ {
+ xcap += next;
+ xcap_val = readl(xcap);
+ id = xcap_val & 0xFF;
+ next = (xcap_val & 0xFF00) >> 8;
+ }
+
+ if ( id != LEGACY_ID )
+ return;
+
+ xcap_val = readl(xcap);
+#define XHCI_HC_BIOS_OWNED (1U << 16)
+#define XHCI_HC_OS_OWNED (1U << 24)
+ if (xcap_val & XHCI_HC_BIOS_OWNED) {
+ dbc_error("bios owned\n");
+ writeb(1, (uint8_t*)xcap + 3);
+ while ((readl(xcap) & (XHCI_HC_BIOS_OWNED | XHCI_HC_OS_OWNED)) !=
XHCI_HC_OS_OWNED)
+ {
+ cpu_relax();
+ if (!--timeout)
+ break;
+ }
+ if (!timeout)
+ dbc_error("handoff timeout\n");
+ xcap_val = readl(xcap + 1);
+ xcap_val &= ((0x7 << 1) + (0xff << 5) + (0x7 << 17)); //
XHCI_LEGACY_DISABLE_SMI
+ xcap_val |= (0x7 << 29); // XHCI_LEGACY_SMI_EVENTS
+ writel(xcap_val, xcap + 1);
+ }
+}
+
static bool __init dbc_init_xhc(struct dbc *dbc)
{
uint32_t bar0;
uint64_t bar1;
uint64_t bar_val;
uint64_t bar_size;
- uint64_t devfn;
+ unsigned int bus, devfn;
uint16_t cmd;
size_t xhc_mmio_size;
if ( dbc->sbdf.sbdf == 0 )
{
- /*
- * Search PCI bus 0 for the xHC. All the host controllers supported so
- * far are part of the chipset and are on bus 0.
- */
- for ( devfn = 0; devfn < 256; devfn++ )
- {
- pci_sbdf_t sbdf = PCI_SBDF(0, 0, devfn);
- uint8_t hdr = pci_conf_read8(sbdf, PCI_HEADER_TYPE);
-
- if ( hdr == 0 || hdr == 0x80 )
+ for ( bus = 0; bus < 0x100; bus++ )
+ for ( devfn = 0; devfn < 256; devfn++ )
{
- if ( (pci_conf_read32(sbdf, PCI_CLASS_REVISION) >> 8) ==
- DBC_XHC_CLASSC )
+ pci_sbdf_t sbdf = PCI_SBDF(0, bus, devfn);
+ uint8_t hdr = pci_conf_read8(sbdf, PCI_HEADER_TYPE);
+
+ if ( hdr == 0 || hdr == 0x80 )
{
- if ( dbc->xhc_num-- )
- continue;
- dbc->sbdf = sbdf;
- break;
+ if ( (pci_conf_read32(sbdf, PCI_CLASS_REVISION) >> 8) ==
+ DBC_XHC_CLASSC )
+ {
+ if ( dbc->xhc_num-- )
+ continue;
+ dbc->sbdf = sbdf;
+ break;
+ }
}
}
- }
}
else
{
--
git-series 0.9.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |