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

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

DEFINITIONS

This source file includes following definitions.
  1. usb_hcd_tdi_set_mode
  2. ehci_msp_setup
  3. usb_hcd_msp_map_regs
  4. usb_hcd_msp_probe
  5. usb_hcd_msp_remove
  6. ehci_hcd_msp_drv_probe
  7. ehci_hcd_msp_drv_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * PMC MSP EHCI (Host Controller Driver) for USB.
   4  *
   5  * (C) Copyright 2006-2010 PMC-Sierra Inc
   6  */
   7 
   8 /* includes */
   9 #include <linux/platform_device.h>
  10 #include <linux/gpio.h>
  11 #include <linux/usb.h>
  12 #include <msp_usb.h>
  13 
  14 /* stream disable*/
  15 #define USB_CTRL_MODE_STREAM_DISABLE    0x10
  16 
  17 /* threshold */
  18 #define USB_CTRL_FIFO_THRESH            0x00300000
  19 
  20 /* register offset for usb_mode */
  21 #define USB_EHCI_REG_USB_MODE           0x68
  22 
  23 /* register offset for usb fifo */
  24 #define USB_EHCI_REG_USB_FIFO           0x24
  25 
  26 /* register offset for usb status */
  27 #define USB_EHCI_REG_USB_STATUS         0x44
  28 
  29 /* serial/parallel transceiver */
  30 #define USB_EHCI_REG_BIT_STAT_STS       (1<<29)
  31 
  32 /* TWI USB0 host device pin */
  33 #define MSP_PIN_USB0_HOST_DEV           49
  34 
  35 /* TWI USB1 host device pin */
  36 #define MSP_PIN_USB1_HOST_DEV           50
  37 
  38 
  39 static void usb_hcd_tdi_set_mode(struct ehci_hcd *ehci)
  40 {
  41         u8 *base;
  42         u8 *statreg;
  43         u8 *fiforeg;
  44         u32 val;
  45         struct ehci_regs *reg_base = ehci->regs;
  46 
  47         /* get register base */
  48         base = (u8 *)reg_base + USB_EHCI_REG_USB_MODE;
  49         statreg = (u8 *)reg_base + USB_EHCI_REG_USB_STATUS;
  50         fiforeg = (u8 *)reg_base + USB_EHCI_REG_USB_FIFO;
  51 
  52         /* Disable controller mode stream */
  53         val = ehci_readl(ehci, (u32 *)base);
  54         ehci_writel(ehci, (val | USB_CTRL_MODE_STREAM_DISABLE),
  55                         (u32 *)base);
  56 
  57         /* clear STS to select parallel transceiver interface */
  58         val = ehci_readl(ehci, (u32 *)statreg);
  59         val = val & ~USB_EHCI_REG_BIT_STAT_STS;
  60         ehci_writel(ehci, val, (u32 *)statreg);
  61 
  62         /* write to set the proper fifo threshold */
  63         ehci_writel(ehci, USB_CTRL_FIFO_THRESH, (u32 *)fiforeg);
  64 
  65         /* set TWI GPIO USB_HOST_DEV pin high */
  66         gpio_direction_output(MSP_PIN_USB0_HOST_DEV, 1);
  67 }
  68 
  69 /* called during probe() after chip reset completes */
  70 static int ehci_msp_setup(struct usb_hcd *hcd)
  71 {
  72         struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
  73         int                     retval;
  74 
  75         ehci->big_endian_mmio = 1;
  76         ehci->big_endian_desc = 1;
  77 
  78         ehci->caps = hcd->regs;
  79         hcd->has_tt = 1;
  80 
  81         retval = ehci_setup(hcd);
  82         if (retval)
  83                 return retval;
  84 
  85         usb_hcd_tdi_set_mode(ehci);
  86 
  87         return retval;
  88 }
  89 
  90 
  91 /* configure so an HC device and id are always provided
  92  * always called with process context; sleeping is OK
  93  */
  94 
  95 static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
  96 {
  97         struct resource *res;
  98         struct platform_device *pdev = &dev->dev;
  99         u32 res_len;
 100         int retval;
 101 
 102         /* MAB register space */
 103         res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 104         if (res == NULL)
 105                 return -ENOMEM;
 106         res_len = resource_size(res);
 107         if (!request_mem_region(res->start, res_len, "mab regs"))
 108                 return -EBUSY;
 109 
 110         dev->mab_regs = ioremap_nocache(res->start, res_len);
 111         if (dev->mab_regs == NULL) {
 112                 retval = -ENOMEM;
 113                 goto err1;
 114         }
 115 
 116         /* MSP USB register space */
 117         res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
 118         if (res == NULL) {
 119                 retval = -ENOMEM;
 120                 goto err2;
 121         }
 122         res_len = resource_size(res);
 123         if (!request_mem_region(res->start, res_len, "usbid regs")) {
 124                 retval = -EBUSY;
 125                 goto err2;
 126         }
 127         dev->usbid_regs = ioremap_nocache(res->start, res_len);
 128         if (dev->usbid_regs == NULL) {
 129                 retval = -ENOMEM;
 130                 goto err3;
 131         }
 132 
 133         return 0;
 134 err3:
 135         res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
 136         res_len = resource_size(res);
 137         release_mem_region(res->start, res_len);
 138 err2:
 139         iounmap(dev->mab_regs);
 140 err1:
 141         res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 142         res_len = resource_size(res);
 143         release_mem_region(res->start, res_len);
 144         dev_err(&pdev->dev, "Failed to map non-EHCI regs.\n");
 145         return retval;
 146 }
 147 
 148 /**
 149  * usb_hcd_msp_probe - initialize PMC MSP-based HCDs
 150  * Context: !in_interrupt()
 151  *
 152  * Allocates basic resources for this USB host controller, and
 153  * then invokes the start() method for the HCD associated with it
 154  * through the hotplug entry's driver_data.
 155  *
 156  */
 157 int usb_hcd_msp_probe(const struct hc_driver *driver,
 158                           struct platform_device *dev)
 159 {
 160         int retval;
 161         struct usb_hcd *hcd;
 162         struct resource *res;
 163         struct ehci_hcd         *ehci ;
 164 
 165         hcd = usb_create_hcd(driver, &dev->dev, "pmcmsp");
 166         if (!hcd)
 167                 return -ENOMEM;
 168 
 169         res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 170         if (res == NULL) {
 171                 pr_debug("No IOMEM resource info for %s.\n", dev->name);
 172                 retval = -ENOMEM;
 173                 goto err1;
 174         }
 175         hcd->rsrc_start = res->start;
 176         hcd->rsrc_len = resource_size(res);
 177         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, dev->name)) {
 178                 retval = -EBUSY;
 179                 goto err1;
 180         }
 181         hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
 182         if (!hcd->regs) {
 183                 pr_debug("ioremap failed");
 184                 retval = -ENOMEM;
 185                 goto err2;
 186         }
 187 
 188         res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
 189         if (res == NULL) {
 190                 dev_err(&dev->dev, "No IRQ resource info for %s.\n", dev->name);
 191                 retval = -ENOMEM;
 192                 goto err3;
 193         }
 194 
 195         /* Map non-EHCI register spaces */
 196         retval = usb_hcd_msp_map_regs(to_mspusb_device(dev));
 197         if (retval != 0)
 198                 goto err3;
 199 
 200         ehci = hcd_to_ehci(hcd);
 201         ehci->big_endian_mmio = 1;
 202         ehci->big_endian_desc = 1;
 203 
 204 
 205         retval = usb_add_hcd(hcd, res->start, IRQF_SHARED);
 206         if (retval == 0) {
 207                 device_wakeup_enable(hcd->self.controller);
 208                 return 0;
 209         }
 210 
 211         usb_remove_hcd(hcd);
 212 err3:
 213         iounmap(hcd->regs);
 214 err2:
 215         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 216 err1:
 217         usb_put_hcd(hcd);
 218 
 219         return retval;
 220 }
 221 
 222 
 223 
 224 /**
 225  * usb_hcd_msp_remove - shutdown processing for PMC MSP-based HCDs
 226  * @dev: USB Host Controller being removed
 227  * Context: !in_interrupt()
 228  *
 229  * Reverses the effect of usb_hcd_msp_probe(), first invoking
 230  * the HCD's stop() method.  It is always called from a thread
 231  * context, normally "rmmod", "apmd", or something similar.
 232  *
 233  * may be called without controller electrically present
 234  * may be called with controller, bus, and devices active
 235  */
 236 void usb_hcd_msp_remove(struct usb_hcd *hcd, struct platform_device *dev)
 237 {
 238         usb_remove_hcd(hcd);
 239         iounmap(hcd->regs);
 240         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 241         usb_put_hcd(hcd);
 242 }
 243 
 244 static const struct hc_driver ehci_msp_hc_driver = {
 245         .description =          hcd_name,
 246         .product_desc =         "PMC MSP EHCI",
 247         .hcd_priv_size =        sizeof(struct ehci_hcd),
 248 
 249         /*
 250          * generic hardware linkage
 251          */
 252         .irq =                  ehci_irq,
 253         .flags =                HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
 254 
 255         /*
 256          * basic lifecycle operations
 257          */
 258         .reset                  = ehci_msp_setup,
 259         .shutdown               = ehci_shutdown,
 260         .start                  = ehci_run,
 261         .stop                   = ehci_stop,
 262 
 263         /*
 264          * managing i/o requests and associated device resources
 265          */
 266         .urb_enqueue            = ehci_urb_enqueue,
 267         .urb_dequeue            = ehci_urb_dequeue,
 268         .endpoint_disable       = ehci_endpoint_disable,
 269         .endpoint_reset         = ehci_endpoint_reset,
 270 
 271         /*
 272          * scheduling support
 273          */
 274         .get_frame_number       = ehci_get_frame,
 275 
 276         /*
 277          * root hub support
 278          */
 279         .hub_status_data        = ehci_hub_status_data,
 280         .hub_control            = ehci_hub_control,
 281         .bus_suspend            = ehci_bus_suspend,
 282         .bus_resume             = ehci_bus_resume,
 283         .relinquish_port        = ehci_relinquish_port,
 284         .port_handed_over       = ehci_port_handed_over,
 285 
 286         .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 287 };
 288 
 289 static int ehci_hcd_msp_drv_probe(struct platform_device *pdev)
 290 {
 291         int ret;
 292 
 293         pr_debug("In ehci_hcd_msp_drv_probe");
 294 
 295         if (usb_disabled())
 296                 return -ENODEV;
 297 
 298         gpio_request(MSP_PIN_USB0_HOST_DEV, "USB0_HOST_DEV_GPIO");
 299 
 300         ret = usb_hcd_msp_probe(&ehci_msp_hc_driver, pdev);
 301 
 302         return ret;
 303 }
 304 
 305 static int ehci_hcd_msp_drv_remove(struct platform_device *pdev)
 306 {
 307         struct usb_hcd *hcd = platform_get_drvdata(pdev);
 308 
 309         usb_hcd_msp_remove(hcd, pdev);
 310 
 311         /* free TWI GPIO USB_HOST_DEV pin */
 312         gpio_free(MSP_PIN_USB0_HOST_DEV);
 313 
 314         return 0;
 315 }
 316 
 317 MODULE_ALIAS("pmcmsp-ehci");
 318 
 319 static struct platform_driver ehci_hcd_msp_driver = {
 320         .probe          = ehci_hcd_msp_drv_probe,
 321         .remove         = ehci_hcd_msp_drv_remove,
 322         .driver         = {
 323                 .name   = "pmcmsp-ehci",
 324         },
 325 };

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