linux/drivers/usb/host/xhci-plat.c
<<
>>
Prefs
   1/*
   2 * xhci-plat.c - xHCI host controller driver platform Bus Glue.
   3 *
   4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
   5 * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
   6 *
   7 * A lot of code borrowed from the Linux xHCI driver.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License
  11 * version 2 as published by the Free Software Foundation.
  12 */
  13
  14#include <linux/clk.h>
  15#include <linux/dma-mapping.h>
  16#include <linux/module.h>
  17#include <linux/of.h>
  18#include <linux/platform_device.h>
  19#include <linux/usb/phy.h>
  20#include <linux/slab.h>
  21#include <linux/usb/xhci_pdriver.h>
  22#include <linux/acpi.h>
  23
  24#include "xhci.h"
  25#include "xhci-mvebu.h"
  26#include "xhci-rcar.h"
  27
  28static struct hc_driver __read_mostly xhci_plat_hc_driver;
  29
  30static int xhci_plat_setup(struct usb_hcd *hcd);
  31static int xhci_plat_start(struct usb_hcd *hcd);
  32
  33static const struct xhci_driver_overrides xhci_plat_overrides __initconst = {
  34        .extra_priv_size = sizeof(struct xhci_hcd),
  35        .reset = xhci_plat_setup,
  36        .start = xhci_plat_start,
  37};
  38
  39static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
  40{
  41        /*
  42         * As of now platform drivers don't provide MSI support so we ensure
  43         * here that the generic code does not try to make a pci_dev from our
  44         * dev struct in order to setup MSI
  45         */
  46        xhci->quirks |= XHCI_PLAT;
  47}
  48
  49/* called during probe() after chip reset completes */
  50static int xhci_plat_setup(struct usb_hcd *hcd)
  51{
  52        struct device_node *of_node = hcd->self.controller->of_node;
  53        int ret;
  54
  55        if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") ||
  56            of_device_is_compatible(of_node, "renesas,xhci-r8a7791")) {
  57                ret = xhci_rcar_init_quirk(hcd);
  58                if (ret)
  59                        return ret;
  60        }
  61
  62        return xhci_gen_setup(hcd, xhci_plat_quirks);
  63}
  64
  65static int xhci_plat_start(struct usb_hcd *hcd)
  66{
  67        struct device_node *of_node = hcd->self.controller->of_node;
  68
  69        if (of_device_is_compatible(of_node, "renesas,xhci-r8a7790") ||
  70            of_device_is_compatible(of_node, "renesas,xhci-r8a7791"))
  71                xhci_rcar_start(hcd);
  72
  73        return xhci_run(hcd);
  74}
  75
  76static int xhci_plat_probe(struct platform_device *pdev)
  77{
  78        struct device_node      *node = pdev->dev.of_node;
  79        struct usb_xhci_pdata   *pdata = dev_get_platdata(&pdev->dev);
  80        const struct hc_driver  *driver;
  81        struct xhci_hcd         *xhci;
  82        struct resource         *res;
  83        struct usb_hcd          *hcd;
  84        struct clk              *clk;
  85        int                     ret;
  86        int                     irq;
  87
  88        if (usb_disabled())
  89                return -ENODEV;
  90
  91        driver = &xhci_plat_hc_driver;
  92
  93        irq = platform_get_irq(pdev, 0);
  94        if (irq < 0)
  95                return -ENODEV;
  96
  97        /* Try to set 64-bit DMA first */
  98        if (WARN_ON(!pdev->dev.dma_mask))
  99                /* Platform did not initialize dma_mask */
 100                ret = dma_coerce_mask_and_coherent(&pdev->dev,
 101                                                   DMA_BIT_MASK(64));
 102        else
 103                ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 104
 105        /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
 106        if (ret) {
 107                ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
 108                if (ret)
 109                        return ret;
 110        }
 111
 112        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 113        if (!hcd)
 114                return -ENOMEM;
 115
 116        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 117        hcd->regs = devm_ioremap_resource(&pdev->dev, res);
 118        if (IS_ERR(hcd->regs)) {
 119                ret = PTR_ERR(hcd->regs);
 120                goto put_hcd;
 121        }
 122
 123        hcd->rsrc_start = res->start;
 124        hcd->rsrc_len = resource_size(res);
 125
 126        /*
 127         * Not all platforms have a clk so it is not an error if the
 128         * clock does not exists.
 129         */
 130        clk = devm_clk_get(&pdev->dev, NULL);
 131        if (!IS_ERR(clk)) {
 132                ret = clk_prepare_enable(clk);
 133                if (ret)
 134                        goto put_hcd;
 135        }
 136
 137        if (of_device_is_compatible(pdev->dev.of_node,
 138                                    "marvell,armada-375-xhci") ||
 139            of_device_is_compatible(pdev->dev.of_node,
 140                                    "marvell,armada-380-xhci")) {
 141                ret = xhci_mvebu_mbus_init_quirk(pdev);
 142                if (ret)
 143                        goto disable_clk;
 144        }
 145
 146        device_wakeup_enable(hcd->self.controller);
 147
 148        xhci = hcd_to_xhci(hcd);
 149        xhci->clk = clk;
 150        xhci->main_hcd = hcd;
 151        xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev,
 152                        dev_name(&pdev->dev), hcd);
 153        if (!xhci->shared_hcd) {
 154                ret = -ENOMEM;
 155                goto disable_clk;
 156        }
 157
 158        if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
 159                        (pdata && pdata->usb3_lpm_capable))
 160                xhci->quirks |= XHCI_LPM_SUPPORT;
 161
 162        if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
 163                xhci->shared_hcd->can_do_streams = 1;
 164
 165        hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
 166        if (IS_ERR(hcd->usb_phy)) {
 167                ret = PTR_ERR(hcd->usb_phy);
 168                if (ret == -EPROBE_DEFER)
 169                        goto put_usb3_hcd;
 170                hcd->usb_phy = NULL;
 171        } else {
 172                ret = usb_phy_init(hcd->usb_phy);
 173                if (ret)
 174                        goto put_usb3_hcd;
 175        }
 176
 177        ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 178        if (ret)
 179                goto disable_usb_phy;
 180
 181        ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
 182        if (ret)
 183                goto dealloc_usb2_hcd;
 184
 185        return 0;
 186
 187
 188dealloc_usb2_hcd:
 189        usb_remove_hcd(hcd);
 190
 191disable_usb_phy:
 192        usb_phy_shutdown(hcd->usb_phy);
 193
 194put_usb3_hcd:
 195        usb_put_hcd(xhci->shared_hcd);
 196
 197disable_clk:
 198        if (!IS_ERR(clk))
 199                clk_disable_unprepare(clk);
 200
 201put_hcd:
 202        usb_put_hcd(hcd);
 203
 204        return ret;
 205}
 206
 207static int xhci_plat_remove(struct platform_device *dev)
 208{
 209        struct usb_hcd  *hcd = platform_get_drvdata(dev);
 210        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 211        struct clk *clk = xhci->clk;
 212
 213        usb_remove_hcd(xhci->shared_hcd);
 214        usb_phy_shutdown(hcd->usb_phy);
 215
 216        usb_remove_hcd(hcd);
 217        usb_put_hcd(xhci->shared_hcd);
 218
 219        if (!IS_ERR(clk))
 220                clk_disable_unprepare(clk);
 221        usb_put_hcd(hcd);
 222
 223        return 0;
 224}
 225
 226#ifdef CONFIG_PM_SLEEP
 227static int xhci_plat_suspend(struct device *dev)
 228{
 229        struct usb_hcd  *hcd = dev_get_drvdata(dev);
 230        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 231
 232        /*
 233         * xhci_suspend() needs `do_wakeup` to know whether host is allowed
 234         * to do wakeup during suspend. Since xhci_plat_suspend is currently
 235         * only designed for system suspend, device_may_wakeup() is enough
 236         * to dertermine whether host is allowed to do wakeup. Need to
 237         * reconsider this when xhci_plat_suspend enlarges its scope, e.g.,
 238         * also applies to runtime suspend.
 239         */
 240        return xhci_suspend(xhci, device_may_wakeup(dev));
 241}
 242
 243static int xhci_plat_resume(struct device *dev)
 244{
 245        struct usb_hcd  *hcd = dev_get_drvdata(dev);
 246        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 247
 248        return xhci_resume(xhci, 0);
 249}
 250
 251static const struct dev_pm_ops xhci_plat_pm_ops = {
 252        SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume)
 253};
 254#define DEV_PM_OPS      (&xhci_plat_pm_ops)
 255#else
 256#define DEV_PM_OPS      NULL
 257#endif /* CONFIG_PM */
 258
 259#ifdef CONFIG_OF
 260static const struct of_device_id usb_xhci_of_match[] = {
 261        { .compatible = "generic-xhci" },
 262        { .compatible = "xhci-platform" },
 263        { .compatible = "marvell,armada-375-xhci"},
 264        { .compatible = "marvell,armada-380-xhci"},
 265        { .compatible = "renesas,xhci-r8a7790"},
 266        { .compatible = "renesas,xhci-r8a7791"},
 267        { },
 268};
 269MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
 270#endif
 271
 272static const struct acpi_device_id usb_xhci_acpi_match[] = {
 273        /* XHCI-compliant USB Controller */
 274        { "PNP0D10", },
 275        { }
 276};
 277MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
 278
 279static struct platform_driver usb_xhci_driver = {
 280        .probe  = xhci_plat_probe,
 281        .remove = xhci_plat_remove,
 282        .driver = {
 283                .name = "xhci-hcd",
 284                .pm = DEV_PM_OPS,
 285                .of_match_table = of_match_ptr(usb_xhci_of_match),
 286                .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
 287        },
 288};
 289MODULE_ALIAS("platform:xhci-hcd");
 290
 291static int __init xhci_plat_init(void)
 292{
 293        xhci_init_driver(&xhci_plat_hc_driver, &xhci_plat_overrides);
 294        return platform_driver_register(&usb_xhci_driver);
 295}
 296module_init(xhci_plat_init);
 297
 298static void __exit xhci_plat_exit(void)
 299{
 300        platform_driver_unregister(&usb_xhci_driver);
 301}
 302module_exit(xhci_plat_exit);
 303
 304MODULE_DESCRIPTION("xHCI Platform Host Controller Driver");
 305MODULE_LICENSE("GPL");
 306