diff options
Diffstat (limited to 'drivers/usb/host/xhci-pci.c')
| -rw-r--r-- | drivers/usb/host/xhci-pci.c | 98 |
1 files changed, 90 insertions, 8 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 00908282936..4a9d55e80f7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
| @@ -50,18 +50,44 @@ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) | |||
| 50 | /* called during probe() after chip reset completes */ | 50 | /* called during probe() after chip reset completes */ |
| 51 | static int xhci_pci_setup(struct usb_hcd *hcd) | 51 | static int xhci_pci_setup(struct usb_hcd *hcd) |
| 52 | { | 52 | { |
| 53 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 53 | struct xhci_hcd *xhci; |
| 54 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 54 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
| 55 | int retval; | 55 | int retval; |
| 56 | u32 temp; | 56 | u32 temp; |
| 57 | 57 | ||
| 58 | hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; | 58 | hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2; |
| 59 | 59 | ||
| 60 | xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); | 60 | if (usb_hcd_is_primary_hcd(hcd)) { |
| 61 | if (!xhci) | 61 | xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); |
| 62 | return -ENOMEM; | 62 | if (!xhci) |
| 63 | *((struct xhci_hcd **) hcd->hcd_priv) = xhci; | 63 | return -ENOMEM; |
| 64 | xhci->main_hcd = hcd; | 64 | *((struct xhci_hcd **) hcd->hcd_priv) = xhci; |
| 65 | xhci->main_hcd = hcd; | ||
| 66 | /* Mark the first roothub as being USB 2.0. | ||
| 67 | * The xHCI driver will register the USB 3.0 roothub. | ||
| 68 | */ | ||
| 69 | hcd->speed = HCD_USB2; | ||
| 70 | hcd->self.root_hub->speed = USB_SPEED_HIGH; | ||
| 71 | /* | ||
| 72 | * USB 2.0 roothub under xHCI has an integrated TT, | ||
| 73 | * (rate matching hub) as opposed to having an OHCI/UHCI | ||
| 74 | * companion controller. | ||
| 75 | */ | ||
| 76 | hcd->has_tt = 1; | ||
| 77 | } else { | ||
| 78 | /* xHCI private pointer was set in xhci_pci_probe for the second | ||
| 79 | * registered roothub. | ||
| 80 | */ | ||
| 81 | xhci = hcd_to_xhci(hcd); | ||
| 82 | temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params); | ||
| 83 | if (HCC_64BIT_ADDR(temp)) { | ||
| 84 | xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n"); | ||
| 85 | dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)); | ||
| 86 | } else { | ||
| 87 | dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)); | ||
| 88 | } | ||
| 89 | return 0; | ||
| 90 | } | ||
| 65 | 91 | ||
| 66 | xhci->cap_regs = hcd->regs; | 92 | xhci->cap_regs = hcd->regs; |
| 67 | xhci->op_regs = hcd->regs + | 93 | xhci->op_regs = hcd->regs + |
| @@ -128,11 +154,67 @@ error: | |||
| 128 | return retval; | 154 | return retval; |
| 129 | } | 155 | } |
| 130 | 156 | ||
| 157 | /* | ||
| 158 | * We need to register our own PCI probe function (instead of the USB core's | ||
| 159 | * function) in order to create a second roothub under xHCI. | ||
| 160 | */ | ||
| 161 | static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
| 162 | { | ||
| 163 | int retval; | ||
| 164 | struct xhci_hcd *xhci; | ||
| 165 | struct hc_driver *driver; | ||
| 166 | struct usb_hcd *hcd; | ||
| 167 | |||
| 168 | driver = (struct hc_driver *)id->driver_data; | ||
| 169 | /* Register the USB 2.0 roothub. | ||
| 170 | * FIXME: USB core must know to register the USB 2.0 roothub first. | ||
| 171 | * This is sort of silly, because we could just set the HCD driver flags | ||
| 172 | * to say USB 2.0, but I'm not sure what the implications would be in | ||
| 173 | * the other parts of the HCD code. | ||
| 174 | */ | ||
| 175 | retval = usb_hcd_pci_probe(dev, id); | ||
| 176 | |||
| 177 | if (retval) | ||
| 178 | return retval; | ||
| 179 | |||
| 180 | /* USB 2.0 roothub is stored in the PCI device now. */ | ||
| 181 | hcd = dev_get_drvdata(&dev->dev); | ||
| 182 | xhci = hcd_to_xhci(hcd); | ||
| 183 | xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev, | ||
| 184 | pci_name(dev), hcd); | ||
| 185 | if (!xhci->shared_hcd) { | ||
| 186 | retval = -ENOMEM; | ||
| 187 | goto dealloc_usb2_hcd; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset) | ||
| 191 | * is called by usb_add_hcd(). | ||
| 192 | */ | ||
| 193 | *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; | ||
| 194 | |||
| 195 | retval = usb_add_hcd(xhci->shared_hcd, dev->irq, | ||
| 196 | IRQF_DISABLED | IRQF_SHARED); | ||
| 197 | if (retval) | ||
| 198 | goto put_usb3_hcd; | ||
| 199 | /* Roothub already marked as USB 3.0 speed */ | ||
| 200 | return 0; | ||
| 201 | |||
| 202 | put_usb3_hcd: | ||
| 203 | usb_put_hcd(xhci->shared_hcd); | ||
| 204 | dealloc_usb2_hcd: | ||
| 205 | usb_hcd_pci_remove(dev); | ||
| 206 | return retval; | ||
| 207 | } | ||
| 208 | |||
| 131 | static void xhci_pci_remove(struct pci_dev *dev) | 209 | static void xhci_pci_remove(struct pci_dev *dev) |
| 132 | { | 210 | { |
| 133 | struct xhci_hcd *xhci; | 211 | struct xhci_hcd *xhci; |
| 134 | 212 | ||
| 135 | xhci = hcd_to_xhci(pci_get_drvdata(dev)); | 213 | xhci = hcd_to_xhci(pci_get_drvdata(dev)); |
| 214 | if (xhci->shared_hcd) { | ||
| 215 | usb_remove_hcd(xhci->shared_hcd); | ||
| 216 | usb_put_hcd(xhci->shared_hcd); | ||
| 217 | } | ||
| 136 | usb_hcd_pci_remove(dev); | 218 | usb_hcd_pci_remove(dev); |
| 137 | kfree(xhci); | 219 | kfree(xhci); |
| 138 | } | 220 | } |
| @@ -170,7 +252,7 @@ static const struct hc_driver xhci_pci_hc_driver = { | |||
| 170 | * generic hardware linkage | 252 | * generic hardware linkage |
| 171 | */ | 253 | */ |
| 172 | .irq = xhci_irq, | 254 | .irq = xhci_irq, |
| 173 | .flags = HCD_MEMORY | HCD_USB3, | 255 | .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED, |
| 174 | 256 | ||
| 175 | /* | 257 | /* |
| 176 | * basic lifecycle operations | 258 | * basic lifecycle operations |
| @@ -231,7 +313,7 @@ static struct pci_driver xhci_pci_driver = { | |||
| 231 | .name = (char *) hcd_name, | 313 | .name = (char *) hcd_name, |
| 232 | .id_table = pci_ids, | 314 | .id_table = pci_ids, |
| 233 | 315 | ||
| 234 | .probe = usb_hcd_pci_probe, | 316 | .probe = xhci_pci_probe, |
| 235 | .remove = xhci_pci_remove, | 317 | .remove = xhci_pci_remove, |
| 236 | /* suspend and resume implemented later */ | 318 | /* suspend and resume implemented later */ |
| 237 | 319 | ||
