linux/drivers/usb/dwc3/core.c
<<
>>
Prefs
   1/**
   2 * core.c - DesignWare USB3 DRD Controller Core file
   3 *
   4 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
   5 *
   6 * Authors: Felipe Balbi <balbi@ti.com>,
   7 *          Sebastian Andrzej Siewior <bigeasy@linutronix.de>
   8 *
   9 * Redistribution and use in source and binary forms, with or without
  10 * modification, are permitted provided that the following conditions
  11 * are met:
  12 * 1. Redistributions of source code must retain the above copyright
  13 *    notice, this list of conditions, and the following disclaimer,
  14 *    without modification.
  15 * 2. Redistributions in binary form must reproduce the above copyright
  16 *    notice, this list of conditions and the following disclaimer in the
  17 *    documentation and/or other materials provided with the distribution.
  18 * 3. The names of the above-listed copyright holders may not be used
  19 *    to endorse or promote products derived from this software without
  20 *    specific prior written permission.
  21 *
  22 * ALTERNATIVELY, this software may be distributed under the terms of the
  23 * GNU General Public License ("GPL") version 2, as published by the Free
  24 * Software Foundation.
  25 *
  26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  27 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  28 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  30 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  32 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  33 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  34 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  36 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37 */
  38
  39#include <linux/module.h>
  40#include <linux/kernel.h>
  41#include <linux/slab.h>
  42#include <linux/spinlock.h>
  43#include <linux/platform_device.h>
  44#include <linux/pm_runtime.h>
  45#include <linux/interrupt.h>
  46#include <linux/ioport.h>
  47#include <linux/io.h>
  48#include <linux/list.h>
  49#include <linux/delay.h>
  50#include <linux/dma-mapping.h>
  51#include <linux/of.h>
  52
  53#include <linux/usb/otg.h>
  54#include <linux/usb/ch9.h>
  55#include <linux/usb/gadget.h>
  56
  57#include "core.h"
  58#include "gadget.h"
  59#include "io.h"
  60
  61#include "debug.h"
  62
  63static char *maximum_speed = "super";
  64module_param(maximum_speed, charp, 0);
  65MODULE_PARM_DESC(maximum_speed, "Maximum supported speed.");
  66
  67/* -------------------------------------------------------------------------- */
  68
  69void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
  70{
  71        u32 reg;
  72
  73        reg = dwc3_readl(dwc->regs, DWC3_GCTL);
  74        reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
  75        reg |= DWC3_GCTL_PRTCAPDIR(mode);
  76        dwc3_writel(dwc->regs, DWC3_GCTL, reg);
  77}
  78
  79/**
  80 * dwc3_core_soft_reset - Issues core soft reset and PHY reset
  81 * @dwc: pointer to our context structure
  82 */
  83static void dwc3_core_soft_reset(struct dwc3 *dwc)
  84{
  85        u32             reg;
  86
  87        /* Before Resetting PHY, put Core in Reset */
  88        reg = dwc3_readl(dwc->regs, DWC3_GCTL);
  89        reg |= DWC3_GCTL_CORESOFTRESET;
  90        dwc3_writel(dwc->regs, DWC3_GCTL, reg);
  91
  92        /* Assert USB3 PHY reset */
  93        reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
  94        reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST;
  95        dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
  96
  97        /* Assert USB2 PHY reset */
  98        reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
  99        reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
 100        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 101
 102        usb_phy_init(dwc->usb2_phy);
 103        usb_phy_init(dwc->usb3_phy);
 104        mdelay(100);
 105
 106        /* Clear USB3 PHY reset */
 107        reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
 108        reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
 109        dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
 110
 111        /* Clear USB2 PHY reset */
 112        reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 113        reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST;
 114        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 115
 116        mdelay(100);
 117
 118        /* After PHYs are stable we can take Core out of reset state */
 119        reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 120        reg &= ~DWC3_GCTL_CORESOFTRESET;
 121        dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 122}
 123
 124/**
 125 * dwc3_free_one_event_buffer - Frees one event buffer
 126 * @dwc: Pointer to our controller context structure
 127 * @evt: Pointer to event buffer to be freed
 128 */
 129static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
 130                struct dwc3_event_buffer *evt)
 131{
 132        dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma);
 133}
 134
 135/**
 136 * dwc3_alloc_one_event_buffer - Allocates one event buffer structure
 137 * @dwc: Pointer to our controller context structure
 138 * @length: size of the event buffer
 139 *
 140 * Returns a pointer to the allocated event buffer structure on success
 141 * otherwise ERR_PTR(errno).
 142 */
 143static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
 144{
 145        struct dwc3_event_buffer        *evt;
 146
 147        evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL);
 148        if (!evt)
 149                return ERR_PTR(-ENOMEM);
 150
 151        evt->dwc        = dwc;
 152        evt->length     = length;
 153        evt->buf        = dma_alloc_coherent(dwc->dev, length,
 154                        &evt->dma, GFP_KERNEL);
 155        if (!evt->buf)
 156                return ERR_PTR(-ENOMEM);
 157
 158        return evt;
 159}
 160
 161/**
 162 * dwc3_free_event_buffers - frees all allocated event buffers
 163 * @dwc: Pointer to our controller context structure
 164 */
 165static void dwc3_free_event_buffers(struct dwc3 *dwc)
 166{
 167        struct dwc3_event_buffer        *evt;
 168        int i;
 169
 170        for (i = 0; i < dwc->num_event_buffers; i++) {
 171                evt = dwc->ev_buffs[i];
 172                if (evt)
 173                        dwc3_free_one_event_buffer(dwc, evt);
 174        }
 175}
 176
 177/**
 178 * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length
 179 * @dwc: pointer to our controller context structure
 180 * @length: size of event buffer
 181 *
 182 * Returns 0 on success otherwise negative errno. In the error case, dwc
 183 * may contain some buffers allocated but not all which were requested.
 184 */
 185static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length)
 186{
 187        int                     num;
 188        int                     i;
 189
 190        num = DWC3_NUM_INT(dwc->hwparams.hwparams1);
 191        dwc->num_event_buffers = num;
 192
 193        dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num,
 194                        GFP_KERNEL);
 195        if (!dwc->ev_buffs) {
 196                dev_err(dwc->dev, "can't allocate event buffers array\n");
 197                return -ENOMEM;
 198        }
 199
 200        for (i = 0; i < num; i++) {
 201                struct dwc3_event_buffer        *evt;
 202
 203                evt = dwc3_alloc_one_event_buffer(dwc, length);
 204                if (IS_ERR(evt)) {
 205                        dev_err(dwc->dev, "can't allocate event buffer\n");
 206                        return PTR_ERR(evt);
 207                }
 208                dwc->ev_buffs[i] = evt;
 209        }
 210
 211        return 0;
 212}
 213
 214/**
 215 * dwc3_event_buffers_setup - setup our allocated event buffers
 216 * @dwc: pointer to our controller context structure
 217 *
 218 * Returns 0 on success otherwise negative errno.
 219 */
 220static int dwc3_event_buffers_setup(struct dwc3 *dwc)
 221{
 222        struct dwc3_event_buffer        *evt;
 223        int                             n;
 224
 225        for (n = 0; n < dwc->num_event_buffers; n++) {
 226                evt = dwc->ev_buffs[n];
 227                dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n",
 228                                evt->buf, (unsigned long long) evt->dma,
 229                                evt->length);
 230
 231                evt->lpos = 0;
 232
 233                dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
 234                                lower_32_bits(evt->dma));
 235                dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n),
 236                                upper_32_bits(evt->dma));
 237                dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n),
 238                                evt->length & 0xffff);
 239                dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
 240        }
 241
 242        return 0;
 243}
 244
 245static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
 246{
 247        struct dwc3_event_buffer        *evt;
 248        int                             n;
 249
 250        for (n = 0; n < dwc->num_event_buffers; n++) {
 251                evt = dwc->ev_buffs[n];
 252
 253                evt->lpos = 0;
 254
 255                dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0);
 256                dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0);
 257                dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0);
 258                dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0);
 259        }
 260}
 261
 262static void dwc3_cache_hwparams(struct dwc3 *dwc)
 263{
 264        struct dwc3_hwparams    *parms = &dwc->hwparams;
 265
 266        parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
 267        parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
 268        parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
 269        parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
 270        parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
 271        parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
 272        parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
 273        parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
 274        parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
 275}
 276
 277/**
 278 * dwc3_core_init - Low-level initialization of DWC3 Core
 279 * @dwc: Pointer to our controller context structure
 280 *
 281 * Returns 0 on success otherwise negative errno.
 282 */
 283static int dwc3_core_init(struct dwc3 *dwc)
 284{
 285        unsigned long           timeout;
 286        u32                     reg;
 287        int                     ret;
 288
 289        reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
 290        /* This should read as U3 followed by revision number */
 291        if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
 292                dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
 293                ret = -ENODEV;
 294                goto err0;
 295        }
 296        dwc->revision = reg;
 297
 298        /* issue device SoftReset too */
 299        timeout = jiffies + msecs_to_jiffies(500);
 300        dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
 301        do {
 302                reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 303                if (!(reg & DWC3_DCTL_CSFTRST))
 304                        break;
 305
 306                if (time_after(jiffies, timeout)) {
 307                        dev_err(dwc->dev, "Reset Timed Out\n");
 308                        ret = -ETIMEDOUT;
 309                        goto err0;
 310                }
 311
 312                cpu_relax();
 313        } while (true);
 314
 315        dwc3_core_soft_reset(dwc);
 316
 317        reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 318        reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
 319        reg &= ~DWC3_GCTL_DISSCRAMBLE;
 320
 321        switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
 322        case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
 323                reg &= ~DWC3_GCTL_DSBLCLKGTNG;
 324                break;
 325        default:
 326                dev_dbg(dwc->dev, "No power optimization available\n");
 327        }
 328
 329        /*
 330         * WORKAROUND: DWC3 revisions <1.90a have a bug
 331         * where the device can fail to connect at SuperSpeed
 332         * and falls back to high-speed mode which causes
 333         * the device to enter a Connect/Disconnect loop
 334         */
 335        if (dwc->revision < DWC3_REVISION_190A)
 336                reg |= DWC3_GCTL_U2RSTECN;
 337
 338        dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 339
 340        ret = dwc3_event_buffers_setup(dwc);
 341        if (ret) {
 342                dev_err(dwc->dev, "failed to setup event buffers\n");
 343                goto err0;
 344        }
 345
 346        return 0;
 347
 348err0:
 349        return ret;
 350}
 351
 352static void dwc3_core_exit(struct dwc3 *dwc)
 353{
 354        dwc3_event_buffers_cleanup(dwc);
 355
 356        usb_phy_shutdown(dwc->usb2_phy);
 357        usb_phy_shutdown(dwc->usb3_phy);
 358}
 359
 360#define DWC3_ALIGN_MASK         (16 - 1)
 361
 362static int dwc3_probe(struct platform_device *pdev)
 363{
 364        struct device_node      *node = pdev->dev.of_node;
 365        struct resource         *res;
 366        struct dwc3             *dwc;
 367        struct device           *dev = &pdev->dev;
 368
 369        int                     ret = -ENOMEM;
 370
 371        void __iomem            *regs;
 372        void                    *mem;
 373
 374        u8                      mode;
 375
 376        mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
 377        if (!mem) {
 378                dev_err(dev, "not enough memory\n");
 379                return -ENOMEM;
 380        }
 381        dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
 382        dwc->mem = mem;
 383
 384        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 385        if (!res) {
 386                dev_err(dev, "missing IRQ\n");
 387                return -ENODEV;
 388        }
 389        dwc->xhci_resources[1].start = res->start;
 390        dwc->xhci_resources[1].end = res->end;
 391        dwc->xhci_resources[1].flags = res->flags;
 392        dwc->xhci_resources[1].name = res->name;
 393
 394        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 395        if (!res) {
 396                dev_err(dev, "missing memory resource\n");
 397                return -ENODEV;
 398        }
 399        dwc->xhci_resources[0].start = res->start;
 400        dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
 401                                        DWC3_XHCI_REGS_END;
 402        dwc->xhci_resources[0].flags = res->flags;
 403        dwc->xhci_resources[0].name = res->name;
 404
 405         /*
 406          * Request memory region but exclude xHCI regs,
 407          * since it will be requested by the xhci-plat driver.
 408          */
 409        res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START,
 410                        resource_size(res) - DWC3_GLOBALS_REGS_START,
 411                        dev_name(dev));
 412        if (!res) {
 413                dev_err(dev, "can't request mem region\n");
 414                return -ENOMEM;
 415        }
 416
 417        regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
 418        if (!regs) {
 419                dev_err(dev, "ioremap failed\n");
 420                return -ENOMEM;
 421        }
 422
 423        if (node) {
 424                dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
 425                dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
 426        } else {
 427                dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 428                dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
 429        }
 430
 431        if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
 432                dev_err(dev, "no usb2 phy configured\n");
 433                return -EPROBE_DEFER;
 434        }
 435
 436        if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
 437                dev_err(dev, "no usb3 phy configured\n");
 438                return -EPROBE_DEFER;
 439        }
 440
 441        usb_phy_set_suspend(dwc->usb2_phy, 0);
 442        usb_phy_set_suspend(dwc->usb3_phy, 0);
 443
 444        spin_lock_init(&dwc->lock);
 445        platform_set_drvdata(pdev, dwc);
 446
 447        dwc->regs       = regs;
 448        dwc->regs_size  = resource_size(res);
 449        dwc->dev        = dev;
 450
 451        if (!strncmp("super", maximum_speed, 5))
 452                dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 453        else if (!strncmp("high", maximum_speed, 4))
 454                dwc->maximum_speed = DWC3_DCFG_HIGHSPEED;
 455        else if (!strncmp("full", maximum_speed, 4))
 456                dwc->maximum_speed = DWC3_DCFG_FULLSPEED1;
 457        else if (!strncmp("low", maximum_speed, 3))
 458                dwc->maximum_speed = DWC3_DCFG_LOWSPEED;
 459        else
 460                dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
 461
 462        dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
 463
 464        pm_runtime_enable(dev);
 465        pm_runtime_get_sync(dev);
 466        pm_runtime_forbid(dev);
 467
 468        dwc3_cache_hwparams(dwc);
 469
 470        ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
 471        if (ret) {
 472                dev_err(dwc->dev, "failed to allocate event buffers\n");
 473                ret = -ENOMEM;
 474                goto err0;
 475        }
 476
 477        ret = dwc3_core_init(dwc);
 478        if (ret) {
 479                dev_err(dev, "failed to initialize core\n");
 480                goto err0;
 481        }
 482
 483        mode = DWC3_MODE(dwc->hwparams.hwparams0);
 484
 485        switch (mode) {
 486        case DWC3_MODE_DEVICE:
 487                dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 488                ret = dwc3_gadget_init(dwc);
 489                if (ret) {
 490                        dev_err(dev, "failed to initialize gadget\n");
 491                        goto err1;
 492                }
 493                break;
 494        case DWC3_MODE_HOST:
 495                dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
 496                ret = dwc3_host_init(dwc);
 497                if (ret) {
 498                        dev_err(dev, "failed to initialize host\n");
 499                        goto err1;
 500                }
 501                break;
 502        case DWC3_MODE_DRD:
 503                dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
 504                ret = dwc3_host_init(dwc);
 505                if (ret) {
 506                        dev_err(dev, "failed to initialize host\n");
 507                        goto err1;
 508                }
 509
 510                ret = dwc3_gadget_init(dwc);
 511                if (ret) {
 512                        dev_err(dev, "failed to initialize gadget\n");
 513                        goto err1;
 514                }
 515                break;
 516        default:
 517                dev_err(dev, "Unsupported mode of operation %d\n", mode);
 518                goto err1;
 519        }
 520        dwc->mode = mode;
 521
 522        ret = dwc3_debugfs_init(dwc);
 523        if (ret) {
 524                dev_err(dev, "failed to initialize debugfs\n");
 525                goto err2;
 526        }
 527
 528        pm_runtime_allow(dev);
 529
 530        return 0;
 531
 532err2:
 533        switch (mode) {
 534        case DWC3_MODE_DEVICE:
 535                dwc3_gadget_exit(dwc);
 536                break;
 537        case DWC3_MODE_HOST:
 538                dwc3_host_exit(dwc);
 539                break;
 540        case DWC3_MODE_DRD:
 541                dwc3_host_exit(dwc);
 542                dwc3_gadget_exit(dwc);
 543                break;
 544        default:
 545                /* do nothing */
 546                break;
 547        }
 548
 549err1:
 550        dwc3_core_exit(dwc);
 551
 552err0:
 553        dwc3_free_event_buffers(dwc);
 554
 555        return ret;
 556}
 557
 558static int dwc3_remove(struct platform_device *pdev)
 559{
 560        struct dwc3     *dwc = platform_get_drvdata(pdev);
 561
 562        usb_phy_set_suspend(dwc->usb2_phy, 1);
 563        usb_phy_set_suspend(dwc->usb3_phy, 1);
 564
 565        pm_runtime_put(&pdev->dev);
 566        pm_runtime_disable(&pdev->dev);
 567
 568        dwc3_debugfs_exit(dwc);
 569
 570        switch (dwc->mode) {
 571        case DWC3_MODE_DEVICE:
 572                dwc3_gadget_exit(dwc);
 573                break;
 574        case DWC3_MODE_HOST:
 575                dwc3_host_exit(dwc);
 576                break;
 577        case DWC3_MODE_DRD:
 578                dwc3_host_exit(dwc);
 579                dwc3_gadget_exit(dwc);
 580                break;
 581        default:
 582                /* do nothing */
 583                break;
 584        }
 585
 586        dwc3_free_event_buffers(dwc);
 587        dwc3_core_exit(dwc);
 588
 589        return 0;
 590}
 591
 592#ifdef CONFIG_OF
 593static const struct of_device_id of_dwc3_match[] = {
 594        {
 595                .compatible = "synopsys,dwc3"
 596        },
 597        { },
 598};
 599MODULE_DEVICE_TABLE(of, of_dwc3_match);
 600#endif
 601
 602static struct platform_driver dwc3_driver = {
 603        .probe          = dwc3_probe,
 604        .remove         = dwc3_remove,
 605        .driver         = {
 606                .name   = "dwc3",
 607                .of_match_table = of_match_ptr(of_dwc3_match),
 608        },
 609};
 610
 611module_platform_driver(dwc3_driver);
 612
 613MODULE_ALIAS("platform:dwc3");
 614MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 615MODULE_LICENSE("Dual BSD/GPL");
 616MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
 617
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.