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
  22static int dwc3_host_get_irq(struct dwc3 *dwc)
  23{
  24        struct platform_device  *dwc3_pdev = to_platform_device(dwc->dev);
  25        int irq;
  26
  27        irq = platform_get_irq_byname(dwc3_pdev, "host");
  28        if (irq > 0)
  29                goto out;
  30
  31        if (irq == -EPROBE_DEFER)
  32                goto out;
  33
  34        irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
  35        if (irq > 0)
  36                goto out;
  37
  38        if (irq == -EPROBE_DEFER)
  39                goto out;
  40
  41        irq = platform_get_irq(dwc3_pdev, 0);
  42        if (irq > 0)
  43                goto out;
  44
  45        if (irq != -EPROBE_DEFER)
  46                dev_err(dwc->dev, "missing host IRQ\n");
  47
  48        if (!irq)
  49                irq = -EINVAL;
  50
  51out:
  52        return irq;
  53}
  54
  55int dwc3_host_init(struct dwc3 *dwc)
  56{
  57        struct property_entry   props[2];
  58        struct platform_device  *xhci;
  59        int                     ret, irq;
  60        struct resource         *res;
  61        struct platform_device  *dwc3_pdev = to_platform_device(dwc->dev);
  62
  63        irq = dwc3_host_get_irq(dwc);
  64        if (irq < 0)
  65                return irq;
  66
  67        res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ, "host");
  68        if (!res)
  69                res = platform_get_resource_byname(dwc3_pdev, IORESOURCE_IRQ,
  70                                "dwc_usb3");
  71        if (!res)
  72                res = platform_get_resource(dwc3_pdev, IORESOURCE_IRQ, 0);
  73        if (!res)
  74                return -ENOMEM;
  75
  76        dwc->xhci_resources[1].start = irq;
  77        dwc->xhci_resources[1].end = irq;
  78        dwc->xhci_resources[1].flags = res->flags;
  79        dwc->xhci_resources[1].name = res->name;
  80
  81        xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
  82        if (!xhci) {
  83                dev_err(dwc->dev, "couldn't allocate xHCI device\n");
  84                return -ENOMEM;
  85        }
  86
  87        xhci->dev.parent        = dwc->dev;
  88
  89        dwc->xhci = xhci;
  90
  91        ret = platform_device_add_resources(xhci, dwc->xhci_resources,
  92                                                DWC3_XHCI_RESOURCES_NUM);
  93        if (ret) {
  94                dev_err(dwc->dev, "couldn't add resources to xHCI device\n");
  95                goto err1;
  96        }
  97
  98        memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
  99
 100        if (dwc->usb3_lpm_capable) {
 101                props[0].name = "usb3-lpm-capable";
 102                ret = platform_device_add_properties(xhci, props);
 103                if (ret) {
 104                        dev_err(dwc->dev, "failed to add properties to xHCI\n");
 105                        goto err1;
 106                }
 107        }
 108
 109        phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy",
 110                          dev_name(dwc->dev));
 111        phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
 112                          dev_name(dwc->dev));
 113
 114        ret = platform_device_add(xhci);
 115        if (ret) {
 116                dev_err(dwc->dev, "failed to register xHCI device\n");
 117                goto err2;
 118        }
 119
 120        return 0;
 121err2:
 122        phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
 123                          dev_name(dwc->dev));
 124        phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
 125                          dev_name(dwc->dev));
 126err1:
 127        platform_device_put(xhci);
 128        return ret;
 129}
 130
 131void dwc3_host_exit(struct dwc3 *dwc)
 132{
 133        phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
 134                          dev_name(dwc->dev));
 135        phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
 136                          dev_name(dwc->dev));
 137        platform_device_unregister(dwc->xhci);
 138}
 139