linux/drivers/usb/dwc3/host.c
<<
>>
Prefs
   1/**
   2 * host.c - DesignWare USB3 DRD Controller Host Glue
   3 *
   4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
   5 *
   6 * Authors: Felipe Balbi <balbi@ti.com>,
   7 *
   8 * This program is free software: you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2  of
  10 * the License as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#include <linux/platform_device.h>
  19
  20#include "core.h"
  21
  22int dwc3_host_init(struct dwc3 *dwc)
  23{
  24        struct property_entry   props[2];
  25        struct platform_device  *xhci;
  26        int                     ret, irq;
  27        struct resource         *res;
  28        struct platform_device  *dwc3_pdev = to_platform_device(dwc->dev);
  29
  30        irq = platform_get_irq_byname(dwc3_pdev, "host");
  31        if (irq == -EPROBE_DEFER)
  32                return irq;
  33
  34        if (irq <= 0) {
  35                irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
  36                if (irq == -EPROBE_DEFER)
  37                        return irq;
  38
  39                if (irq <= 0) {
  40                        irq = platform_get_irq(dwc3_pdev, 0);
  41                        if (irq <= 0) {
  42                                if (irq != -EPROBE_DEFER) {
  43                                        dev_err(dwc->dev,
  44                                                "missing host IRQ\n");
  45                                }
  46                                if (!irq)
  47                                        irq = -EINVAL;
  48                                return irq;
  49                        } else {
  50                                res = platform_get_resource(dwc3_pdev,
  51                                                            IORESOURCE_IRQ, 0);
  52                        }
  53                } else {
  54                        res = platform_get_resource_byname(dwc3_pdev,
  55                                                           IORESOURCE_IRQ,
  56                                                           "dwc_usb3");
  57                }
  58
  59        } else {
  60                res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ,
  61                                                   "host");
  62        }
  63
  64        dwc->xhci_resources[1].start = irq;
  65        dwc->xhci_resources[1].end = irq;
  66        dwc->xhci_resources[1].flags = res->flags;
  67        dwc->xhci_resources[1].name = res->name;
  68
  69        xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
  70        if (!xhci) {
  71                dev_err(dwc->dev, "couldn't allocate xHCI device\n");
  72                return -ENOMEM;
  73        }
  74
  75        dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
  76
  77        xhci->dev.parent        = dwc->dev;
  78        xhci->dev.dma_mask      = dwc->dev->dma_mask;
  79        xhci->dev.dma_parms     = dwc->dev->dma_parms;
  80
  81        dwc->xhci = xhci;
  82
  83        ret = platform_device_add_resources(xhci, dwc->xhci_resources,
  84                                                DWC3_XHCI_RESOURCES_NUM);
  85        if (ret) {
  86                dev_err(dwc->dev, "couldn't add resources to xHCI device\n");
  87                goto err1;
  88        }
  89
  90        memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
  91
  92        if (dwc->usb3_lpm_capable) {
  93                props[0].name = "usb3-lpm-capable";
  94                ret = platform_device_add_properties(xhci, props);
  95                if (ret) {
  96                        dev_err(dwc->dev, "failed to add properties to xHCI\n");
  97                        goto err1;
  98                }
  99        }
 100
 101        phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy",
 102                          dev_name(&xhci->dev));
 103        phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
 104                          dev_name(&xhci->dev));
 105
 106        ret = platform_device_add(xhci);
 107        if (ret) {
 108                dev_err(dwc->dev, "failed to register xHCI device\n");
 109                goto err2;
 110        }
 111
 112        return 0;
 113err2:
 114        phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
 115                          dev_name(&xhci->dev));
 116        phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
 117                          dev_name(&xhci->dev));
 118err1:
 119        platform_device_put(xhci);
 120        return ret;
 121}
 122
 123void dwc3_host_exit(struct dwc3 *dwc)
 124{
 125        phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
 126                          dev_name(&dwc->xhci->dev));
 127        phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
 128                          dev_name(&dwc->xhci->dev));
 129        platform_device_unregister(dwc->xhci);
 130}
 131