aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-pci.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-27 22:52:28 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:48 -0400
commit66d4eadd8d067269ea8fead1a50fe87c2979a80d (patch)
treeb0324868818058161e528bd194f6888456924fd4 /drivers/usb/host/xhci-pci.c
parent74c6874199af98e602bb7c5fb1beb9cffda98729 (diff)
USB: xhci: BIOS handoff and HW initialization.
Add PCI initialization code to take control of the xHCI host controller away from the BIOS, halt, and reset the host controller. The xHCI spec says that BIOSes must give up the host controller within 5 seconds. Add some host controller glue functions to handle hardware initialization and memory allocation for the host controller. The current xHCI prototypes use PCI interrupts, but the xHCI spec requires MSI-X interrupts. Add code to support MSI-X interrupts, but use the PCI interrupts for now. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-pci.c')
-rw-r--r--drivers/usb/host/xhci-pci.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
new file mode 100644
index 000000000000..4015082adf60
--- /dev/null
+++ b/drivers/usb/host/xhci-pci.c
@@ -0,0 +1,150 @@
1/*
2 * xHCI host controller driver PCI Bus Glue.
3 *
4 * Copyright (C) 2008 Intel Corp.
5 *
6 * Author: Sarah Sharp
7 * Some code borrowed from the Linux EHCI driver.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/pci.h>
24
25#include "xhci.h"
26
27static const char hcd_name[] = "xhci_hcd";
28
29/* called after powerup, by probe or system-pm "wakeup" */
30static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
31{
32 /*
33 * TODO: Implement finding debug ports later.
34 * TODO: see if there are any quirks that need to be added to handle
35 * new extended capabilities.
36 */
37
38 /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
39 if (!pci_set_mwi(pdev))
40 xhci_dbg(xhci, "MWI active\n");
41
42 xhci_dbg(xhci, "Finished xhci_pci_reinit\n");
43 return 0;
44}
45
46/* called during probe() after chip reset completes */
47static int xhci_pci_setup(struct usb_hcd *hcd)
48{
49 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
50 struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
51 int retval;
52
53 xhci->cap_regs = hcd->regs;
54 xhci->op_regs = hcd->regs +
55 HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
56 xhci->run_regs = hcd->regs +
57 (xhci_readl(xhci, &xhci->cap_regs->run_regs_off) & RTSOFF_MASK);
58 /* Cache read-only capability registers */
59 xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1);
60 xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2);
61 xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
62 xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
63 xhci_print_registers(xhci);
64
65 /* Make sure the HC is halted. */
66 retval = xhci_halt(xhci);
67 if (retval)
68 return retval;
69
70 xhci_dbg(xhci, "Resetting HCD\n");
71 /* Reset the internal HC memory state and registers. */
72 retval = xhci_reset(xhci);
73 if (retval)
74 return retval;
75 xhci_dbg(xhci, "Reset complete\n");
76
77 xhci_dbg(xhci, "Calling HCD init\n");
78 /* Initialize HCD and host controller data structures. */
79 retval = xhci_init(hcd);
80 if (retval)
81 return retval;
82 xhci_dbg(xhci, "Called HCD init\n");
83
84 pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
85 xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
86
87 /* Find any debug ports */
88 return xhci_pci_reinit(xhci, pdev);
89}
90
91static const struct hc_driver xhci_pci_hc_driver = {
92 .description = hcd_name,
93 .product_desc = "xHCI Host Controller",
94 .hcd_priv_size = sizeof(struct xhci_hcd),
95
96 /*
97 * generic hardware linkage
98 */
99 .flags = HCD_MEMORY | HCD_USB3,
100
101 /*
102 * basic lifecycle operations
103 */
104 .reset = xhci_pci_setup,
105 .start = xhci_run,
106 /* suspend and resume implemented later */
107 .stop = xhci_stop,
108 .shutdown = xhci_shutdown,
109
110 /*
111 * scheduling support
112 */
113 .get_frame_number = xhci_get_frame,
114
115 /* Implement root hub support later. */
116};
117
118/*-------------------------------------------------------------------------*/
119
120/* PCI driver selection metadata; PCI hotplugging uses this */
121static const struct pci_device_id pci_ids[] = { {
122 /* handle any USB 3.0 xHCI controller */
123 PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0),
124 .driver_data = (unsigned long) &xhci_pci_hc_driver,
125 },
126 { /* end: all zeroes */ }
127};
128MODULE_DEVICE_TABLE(pci, pci_ids);
129
130/* pci driver glue; this is a "new style" PCI driver module */
131static struct pci_driver xhci_pci_driver = {
132 .name = (char *) hcd_name,
133 .id_table = pci_ids,
134
135 .probe = usb_hcd_pci_probe,
136 .remove = usb_hcd_pci_remove,
137 /* suspend and resume implemented later */
138
139 .shutdown = usb_hcd_pci_shutdown,
140};
141
142int xhci_register_pci()
143{
144 return pci_register_driver(&xhci_pci_driver);
145}
146
147void xhci_unregister_pci()
148{
149 pci_unregister_driver(&xhci_pci_driver);
150}