root/drivers/usb/host/ehci-grlib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ehci_hcd_grlib_probe
  2. ehci_hcd_grlib_remove

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Driver for Aeroflex Gaisler GRLIB GRUSBHC EHCI host controller
   4  *
   5  * GRUSBHC is typically found on LEON/GRLIB SoCs
   6  *
   7  * (c) Jan Andersson <jan@gaisler.com>
   8  *
   9  * Based on ehci-ppc-of.c which is:
  10  * (c) Valentine Barshak <vbarshak@ru.mvista.com>
  11  * and in turn based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
  12  * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
  13  */
  14 
  15 #include <linux/err.h>
  16 #include <linux/signal.h>
  17 
  18 #include <linux/of_irq.h>
  19 #include <linux/of_address.h>
  20 #include <linux/of_platform.h>
  21 
  22 #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
  23 
  24 static const struct hc_driver ehci_grlib_hc_driver = {
  25         .description            = hcd_name,
  26         .product_desc           = "GRLIB GRUSBHC EHCI",
  27         .hcd_priv_size          = sizeof(struct ehci_hcd),
  28 
  29         /*
  30          * generic hardware linkage
  31          */
  32         .irq                    = ehci_irq,
  33         .flags                  = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
  34 
  35         /*
  36          * basic lifecycle operations
  37          */
  38         .reset                  = ehci_setup,
  39         .start                  = ehci_run,
  40         .stop                   = ehci_stop,
  41         .shutdown               = ehci_shutdown,
  42 
  43         /*
  44          * managing i/o requests and associated device resources
  45          */
  46         .urb_enqueue            = ehci_urb_enqueue,
  47         .urb_dequeue            = ehci_urb_dequeue,
  48         .endpoint_disable       = ehci_endpoint_disable,
  49         .endpoint_reset         = ehci_endpoint_reset,
  50 
  51         /*
  52          * scheduling support
  53          */
  54         .get_frame_number       = ehci_get_frame,
  55 
  56         /*
  57          * root hub support
  58          */
  59         .hub_status_data        = ehci_hub_status_data,
  60         .hub_control            = ehci_hub_control,
  61 #ifdef  CONFIG_PM
  62         .bus_suspend            = ehci_bus_suspend,
  63         .bus_resume             = ehci_bus_resume,
  64 #endif
  65         .relinquish_port        = ehci_relinquish_port,
  66         .port_handed_over       = ehci_port_handed_over,
  67 
  68         .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
  69 };
  70 
  71 
  72 static int ehci_hcd_grlib_probe(struct platform_device *op)
  73 {
  74         struct device_node *dn = op->dev.of_node;
  75         struct usb_hcd *hcd;
  76         struct ehci_hcd *ehci = NULL;
  77         struct resource res;
  78         u32 hc_capbase;
  79         int irq;
  80         int rv;
  81 
  82         if (usb_disabled())
  83                 return -ENODEV;
  84 
  85         dev_dbg(&op->dev, "initializing GRUSBHC EHCI USB Controller\n");
  86 
  87         rv = of_address_to_resource(dn, 0, &res);
  88         if (rv)
  89                 return rv;
  90 
  91         /* usb_create_hcd requires dma_mask != NULL */
  92         op->dev.dma_mask = &op->dev.coherent_dma_mask;
  93         hcd = usb_create_hcd(&ehci_grlib_hc_driver, &op->dev,
  94                         "GRUSBHC EHCI USB");
  95         if (!hcd)
  96                 return -ENOMEM;
  97 
  98         hcd->rsrc_start = res.start;
  99         hcd->rsrc_len = resource_size(&res);
 100 
 101         irq = irq_of_parse_and_map(dn, 0);
 102         if (irq == NO_IRQ) {
 103                 dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
 104                         __FILE__);
 105                 rv = -EBUSY;
 106                 goto err_irq;
 107         }
 108 
 109         hcd->regs = devm_ioremap_resource(&op->dev, &res);
 110         if (IS_ERR(hcd->regs)) {
 111                 rv = PTR_ERR(hcd->regs);
 112                 goto err_ioremap;
 113         }
 114 
 115         ehci = hcd_to_ehci(hcd);
 116 
 117         ehci->caps = hcd->regs;
 118 
 119         /* determine endianness of this implementation */
 120         hc_capbase = ehci_readl(ehci, &ehci->caps->hc_capbase);
 121         if (HC_VERSION(ehci, hc_capbase) != GRUSBHC_HCIVERSION) {
 122                 ehci->big_endian_mmio = 1;
 123                 ehci->big_endian_desc = 1;
 124                 ehci->big_endian_capbase = 1;
 125         }
 126 
 127         rv = usb_add_hcd(hcd, irq, 0);
 128         if (rv)
 129                 goto err_ioremap;
 130 
 131         device_wakeup_enable(hcd->self.controller);
 132         return 0;
 133 
 134 err_ioremap:
 135         irq_dispose_mapping(irq);
 136 err_irq:
 137         usb_put_hcd(hcd);
 138 
 139         return rv;
 140 }
 141 
 142 
 143 static int ehci_hcd_grlib_remove(struct platform_device *op)
 144 {
 145         struct usb_hcd *hcd = platform_get_drvdata(op);
 146 
 147         dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n");
 148 
 149         usb_remove_hcd(hcd);
 150 
 151         irq_dispose_mapping(hcd->irq);
 152 
 153         usb_put_hcd(hcd);
 154 
 155         return 0;
 156 }
 157 
 158 
 159 static const struct of_device_id ehci_hcd_grlib_of_match[] = {
 160         {
 161                 .name = "GAISLER_EHCI",
 162          },
 163         {
 164                 .name = "01_026",
 165          },
 166         {},
 167 };
 168 MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
 169 
 170 
 171 static struct platform_driver ehci_grlib_driver = {
 172         .probe          = ehci_hcd_grlib_probe,
 173         .remove         = ehci_hcd_grlib_remove,
 174         .shutdown       = usb_hcd_platform_shutdown,
 175         .driver = {
 176                 .name = "grlib-ehci",
 177                 .of_match_table = ehci_hcd_grlib_of_match,
 178         },
 179 };

/* [<][>][^][v][top][bottom][index][help] */