LCOV - code coverage report
Current view: top level - lkbce/drivers/usb/host - xhci-pci.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 39 100.0 %
Date: 2017-01-25 Functions: 4 4 100.0 %

          Line data    Source code
       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             : 
      27             : /* Device for a quirk */
      28             : #define PCI_VENDOR_ID_FRESCO_LOGIC      0x1b73
      29             : #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK  0x1000
      30             : 
      31           1 : static const char hcd_name[] = "xhci_hcd";
      32             : 
      33             : /* called after powerup, by probe or system-pm "wakeup" */
      34             : static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
      35             : {
      36           1 :         /*
      37             :          * TODO: Implement finding debug ports later.
      38             :          * TODO: see if there are any quirks that need to be added to handle
      39             :          * new extended capabilities.
      40             :          */
      41             : 
      42             :         /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
      43           1 :         if (!pci_set_mwi(pdev))
      44             :                 xhci_dbg(xhci, "MWI active\n");
      45             : 
      46             :         xhci_dbg(xhci, "Finished xhci_pci_reinit\n");
      47           1 :         return 0;
      48             : }
      49             : 
      50             : /* called during probe() after chip reset completes */
      51             : static int xhci_pci_setup(struct usb_hcd *hcd)
      52             : {
      53           4 :         struct xhci_hcd         *xhci = hcd_to_xhci(hcd);
      54           3 :         struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
      55           1 :         int                     retval;
      56           1 : 
      57           2 :         hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
      58           1 : 
      59           3 :         xhci->cap_regs = hcd->regs;
      60           4 :         xhci->op_regs = hcd->regs +
      61             :                 HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
      62           3 :         xhci->run_regs = hcd->regs +
      63             :                 (xhci_readl(xhci, &xhci->cap_regs->run_regs_off) & RTSOFF_MASK);
      64             :         /* Cache read-only capability registers */
      65           2 :         xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1);
      66           2 :         xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2);
      67           2 :         xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
      68           2 :         xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
      69           1 :         xhci->hci_version = HC_VERSION(xhci->hcc_params);
      70           2 :         xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
      71           2 :         xhci_print_registers(xhci);
      72             : 
      73             :         /* Look for vendor-specific quirks */
      74           5 :         if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
      75             :                         pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
      76             :                         pdev->revision == 0x0) {
      77           1 :                         xhci->quirks |= XHCI_RESET_EP_QUIRK;
      78             :                         xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
      79             :                                         " endpoint cmd after reset endpoint\n");
      80             :         }
      81             : 
      82             :         /* Make sure the HC is halted. */
      83           2 :         retval = xhci_halt(xhci);
      84           2 :         if (retval)
      85           1 :                 return retval;
      86             : 
      87             :         xhci_dbg(xhci, "Resetting HCD\n");
      88             :         /* Reset the internal HC memory state and registers. */
      89           4 :         retval = xhci_reset(xhci);
      90           2 :         if (retval)
      91           1 :                 return retval;
      92             :         xhci_dbg(xhci, "Reset complete\n");
      93             : 
      94             :         xhci_dbg(xhci, "Calling HCD init\n");
      95             :         /* Initialize HCD and host controller data structures. */
      96           2 :         retval = xhci_init(hcd);
      97           2 :         if (retval)
      98           1 :                 return retval;
      99             :         xhci_dbg(xhci, "Called HCD init\n");
     100             : 
     101           2 :         pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
     102             :         xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
     103             : 
     104             :         /* Find any debug ports */
     105           3 :         return xhci_pci_reinit(xhci, pdev);
     106             : }
     107             : 
     108           1 : static const struct hc_driver xhci_pci_hc_driver = {
     109             :         .description =          hcd_name,
     110             :         .product_desc =         "xHCI Host Controller",
     111             :         .hcd_priv_size =        sizeof(struct xhci_hcd),
     112             : 
     113             :         /*
     114             :          * generic hardware linkage
     115             :          */
     116             :         .irq =                  xhci_irq,
     117             :         .flags =                HCD_MEMORY | HCD_USB3,
     118             : 
     119             :         /*
     120             :          * basic lifecycle operations
     121             :          */
     122             :         .reset =                xhci_pci_setup,
     123             :         .start =                xhci_run,
     124             :         /* suspend and resume implemented later */
     125             :         .stop =                 xhci_stop,
     126             :         .shutdown =             xhci_shutdown,
     127             : 
     128             :         /*
     129             :          * managing i/o requests and associated device resources
     130             :          */
     131             :         .urb_enqueue =          xhci_urb_enqueue,
     132             :         .urb_dequeue =          xhci_urb_dequeue,
     133             :         .alloc_dev =            xhci_alloc_dev,
     134             :         .free_dev =             xhci_free_dev,
     135             :         .add_endpoint =         xhci_add_endpoint,
     136             :         .drop_endpoint =        xhci_drop_endpoint,
     137             :         .endpoint_reset =       xhci_endpoint_reset,
     138             :         .check_bandwidth =      xhci_check_bandwidth,
     139             :         .reset_bandwidth =      xhci_reset_bandwidth,
     140             :         .address_device =       xhci_address_device,
     141             :         .update_hub_device =    xhci_update_hub_device,
     142             : 
     143             :         /*
     144             :          * scheduling support
     145             :          */
     146             :         .get_frame_number =     xhci_get_frame,
     147             : 
     148             :         /* Root hub support */
     149             :         .hub_control =          xhci_hub_control,
     150             :         .hub_status_data =      xhci_hub_status_data,
     151             : };
     152             : 
     153             : /*-------------------------------------------------------------------------*/
     154             : 
     155             : /* PCI driver selection metadata; PCI hotplugging uses this */
     156           1 : static const struct pci_device_id pci_ids[] = { {
     157             :         /* handle any USB 3.0 xHCI controller */
     158             :         PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0),
     159             :         .driver_data =  (unsigned long) &xhci_pci_hc_driver,
     160             :         },
     161             :         { /* end: all zeroes */ }
     162             : };
     163             : MODULE_DEVICE_TABLE(pci, pci_ids);
     164             : 
     165             : /* pci driver glue; this is a "new style" PCI driver module */
     166           1 : static struct pci_driver xhci_pci_driver = {
     167             :         .name =         (char *) hcd_name,
     168             :         .id_table =     pci_ids,
     169             : 
     170             :         .probe =        usb_hcd_pci_probe,
     171             :         .remove =       usb_hcd_pci_remove,
     172             :         /* suspend and resume implemented later */
     173             : 
     174             :         .shutdown =     usb_hcd_pci_shutdown,
     175             : };
     176             : 
     177             : int xhci_register_pci()
     178             : {
     179           4 :         return pci_register_driver(&xhci_pci_driver);
     180             : }
     181             : 
     182             : void xhci_unregister_pci()
     183             : {
     184           4 :         pci_unregister_driver(&xhci_pci_driver);
     185           2 : }

Generated by: LCOV version 1.10