linux/drivers/usb/dwc3/dwc3-omap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * dwc3-omap.c - OMAP Specific Glue layer
   4 *
   5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com
   6 *
   7 * Authors: Felipe Balbi <balbi@ti.com>,
   8 *          Sebastian Andrzej Siewior <bigeasy@linutronix.de>
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/kernel.h>
  13#include <linux/slab.h>
  14#include <linux/irq.h>
  15#include <linux/interrupt.h>
  16#include <linux/platform_device.h>
  17#include <linux/pm_runtime.h>
  18#include <linux/dma-mapping.h>
  19#include <linux/ioport.h>
  20#include <linux/io.h>
  21#include <linux/of.h>
  22#include <linux/of_platform.h>
  23#include <linux/extcon.h>
  24#include <linux/regulator/consumer.h>
  25
  26#include <linux/usb/otg.h>
  27
  28/*
  29 * All these registers belong to OMAP's Wrapper around the
  30 * DesignWare USB3 Core.
  31 */
  32
  33#define USBOTGSS_REVISION                       0x0000
  34#define USBOTGSS_SYSCONFIG                      0x0010
  35#define USBOTGSS_IRQ_EOI                        0x0020
  36#define USBOTGSS_EOI_OFFSET                     0x0008
  37#define USBOTGSS_IRQSTATUS_RAW_0                0x0024
  38#define USBOTGSS_IRQSTATUS_0                    0x0028
  39#define USBOTGSS_IRQENABLE_SET_0                0x002c
  40#define USBOTGSS_IRQENABLE_CLR_0                0x0030
  41#define USBOTGSS_IRQ0_OFFSET                    0x0004
  42#define USBOTGSS_IRQSTATUS_RAW_1                0x0030
  43#define USBOTGSS_IRQSTATUS_1                    0x0034
  44#define USBOTGSS_IRQENABLE_SET_1                0x0038
  45#define USBOTGSS_IRQENABLE_CLR_1                0x003c
  46#define USBOTGSS_IRQSTATUS_RAW_2                0x0040
  47#define USBOTGSS_IRQSTATUS_2                    0x0044
  48#define USBOTGSS_IRQENABLE_SET_2                0x0048
  49#define USBOTGSS_IRQENABLE_CLR_2                0x004c
  50#define USBOTGSS_IRQSTATUS_RAW_3                0x0050
  51#define USBOTGSS_IRQSTATUS_3                    0x0054
  52#define USBOTGSS_IRQENABLE_SET_3                0x0058
  53#define USBOTGSS_IRQENABLE_CLR_3                0x005c
  54#define USBOTGSS_IRQSTATUS_EOI_MISC             0x0030
  55#define USBOTGSS_IRQSTATUS_RAW_MISC             0x0034
  56#define USBOTGSS_IRQSTATUS_MISC                 0x0038
  57#define USBOTGSS_IRQENABLE_SET_MISC             0x003c
  58#define USBOTGSS_IRQENABLE_CLR_MISC             0x0040
  59#define USBOTGSS_IRQMISC_OFFSET                 0x03fc
  60#define USBOTGSS_UTMI_OTG_STATUS                0x0080
  61#define USBOTGSS_UTMI_OTG_CTRL                  0x0084
  62#define USBOTGSS_UTMI_OTG_OFFSET                0x0480
  63#define USBOTGSS_TXFIFO_DEPTH                   0x0508
  64#define USBOTGSS_RXFIFO_DEPTH                   0x050c
  65#define USBOTGSS_MMRAM_OFFSET                   0x0100
  66#define USBOTGSS_FLADJ                          0x0104
  67#define USBOTGSS_DEBUG_CFG                      0x0108
  68#define USBOTGSS_DEBUG_DATA                     0x010c
  69#define USBOTGSS_DEV_EBC_EN                     0x0110
  70#define USBOTGSS_DEBUG_OFFSET                   0x0600
  71
  72/* SYSCONFIG REGISTER */
  73#define USBOTGSS_SYSCONFIG_DMADISABLE           BIT(16)
  74
  75/* IRQ_EOI REGISTER */
  76#define USBOTGSS_IRQ_EOI_LINE_NUMBER            BIT(0)
  77
  78/* IRQS0 BITS */
  79#define USBOTGSS_IRQO_COREIRQ_ST                BIT(0)
  80
  81/* IRQMISC BITS */
  82#define USBOTGSS_IRQMISC_DMADISABLECLR          BIT(17)
  83#define USBOTGSS_IRQMISC_OEVT                   BIT(16)
  84#define USBOTGSS_IRQMISC_DRVVBUS_RISE           BIT(13)
  85#define USBOTGSS_IRQMISC_CHRGVBUS_RISE          BIT(12)
  86#define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE       BIT(11)
  87#define USBOTGSS_IRQMISC_IDPULLUP_RISE          BIT(8)
  88#define USBOTGSS_IRQMISC_DRVVBUS_FALL           BIT(5)
  89#define USBOTGSS_IRQMISC_CHRGVBUS_FALL          BIT(4)
  90#define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL               BIT(3)
  91#define USBOTGSS_IRQMISC_IDPULLUP_FALL          BIT(0)
  92
  93/* UTMI_OTG_STATUS REGISTER */
  94#define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS        BIT(5)
  95#define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS       BIT(4)
  96#define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS    BIT(3)
  97#define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP       BIT(0)
  98
  99/* UTMI_OTG_CTRL REGISTER */
 100#define USBOTGSS_UTMI_OTG_CTRL_SW_MODE          BIT(31)
 101#define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT     BIT(9)
 102#define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE BIT(8)
 103#define USBOTGSS_UTMI_OTG_CTRL_IDDIG            BIT(4)
 104#define USBOTGSS_UTMI_OTG_CTRL_SESSEND          BIT(3)
 105#define USBOTGSS_UTMI_OTG_CTRL_SESSVALID        BIT(2)
 106#define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID        BIT(1)
 107
 108enum dwc3_omap_utmi_mode {
 109        DWC3_OMAP_UTMI_MODE_UNKNOWN = 0,
 110        DWC3_OMAP_UTMI_MODE_HW,
 111        DWC3_OMAP_UTMI_MODE_SW,
 112};
 113
 114struct dwc3_omap {
 115        struct device           *dev;
 116
 117        int                     irq;
 118        void __iomem            *base;
 119
 120        u32                     utmi_otg_ctrl;
 121        u32                     utmi_otg_offset;
 122        u32                     irqmisc_offset;
 123        u32                     irq_eoi_offset;
 124        u32                     debug_offset;
 125        u32                     irq0_offset;
 126
 127        struct extcon_dev       *edev;
 128        struct notifier_block   vbus_nb;
 129        struct notifier_block   id_nb;
 130
 131        struct regulator        *vbus_reg;
 132};
 133
 134enum omap_dwc3_vbus_id_status {
 135        OMAP_DWC3_ID_FLOAT,
 136        OMAP_DWC3_ID_GROUND,
 137        OMAP_DWC3_VBUS_OFF,
 138        OMAP_DWC3_VBUS_VALID,
 139};
 140
 141static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 142{
 143        return readl(base + offset);
 144}
 145
 146static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
 147{
 148        writel(value, base + offset);
 149}
 150
 151static u32 dwc3_omap_read_utmi_ctrl(struct dwc3_omap *omap)
 152{
 153        return dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_CTRL +
 154                                                        omap->utmi_otg_offset);
 155}
 156
 157static void dwc3_omap_write_utmi_ctrl(struct dwc3_omap *omap, u32 value)
 158{
 159        dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_CTRL +
 160                                        omap->utmi_otg_offset, value);
 161
 162}
 163
 164static u32 dwc3_omap_read_irq0_status(struct dwc3_omap *omap)
 165{
 166        return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_RAW_0 -
 167                                                omap->irq0_offset);
 168}
 169
 170static void dwc3_omap_write_irq0_status(struct dwc3_omap *omap, u32 value)
 171{
 172        dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0 -
 173                                                omap->irq0_offset, value);
 174
 175}
 176
 177static u32 dwc3_omap_read_irqmisc_status(struct dwc3_omap *omap)
 178{
 179        return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_RAW_MISC +
 180                                                omap->irqmisc_offset);
 181}
 182
 183static void dwc3_omap_write_irqmisc_status(struct dwc3_omap *omap, u32 value)
 184{
 185        dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_MISC +
 186                                        omap->irqmisc_offset, value);
 187
 188}
 189
 190static void dwc3_omap_write_irqmisc_set(struct dwc3_omap *omap, u32 value)
 191{
 192        dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_MISC +
 193                                                omap->irqmisc_offset, value);
 194
 195}
 196
 197static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value)
 198{
 199        dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0 -
 200                                                omap->irq0_offset, value);
 201}
 202
 203static void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value)
 204{
 205        dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC +
 206                                                omap->irqmisc_offset, value);
 207}
 208
 209static void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value)
 210{
 211        dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 -
 212                                                omap->irq0_offset, value);
 213}
 214
 215static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
 216        enum omap_dwc3_vbus_id_status status)
 217{
 218        int     ret;
 219        u32     val;
 220
 221        switch (status) {
 222        case OMAP_DWC3_ID_GROUND:
 223                if (omap->vbus_reg) {
 224                        ret = regulator_enable(omap->vbus_reg);
 225                        if (ret) {
 226                                dev_err(omap->dev, "regulator enable failed\n");
 227                                return;
 228                        }
 229                }
 230
 231                val = dwc3_omap_read_utmi_ctrl(omap);
 232                val &= ~USBOTGSS_UTMI_OTG_CTRL_IDDIG;
 233                dwc3_omap_write_utmi_ctrl(omap, val);
 234                break;
 235
 236        case OMAP_DWC3_VBUS_VALID:
 237                val = dwc3_omap_read_utmi_ctrl(omap);
 238                val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND;
 239                val |= USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
 240                                | USBOTGSS_UTMI_OTG_CTRL_SESSVALID;
 241                dwc3_omap_write_utmi_ctrl(omap, val);
 242                break;
 243
 244        case OMAP_DWC3_ID_FLOAT:
 245                if (omap->vbus_reg)
 246                        regulator_disable(omap->vbus_reg);
 247                val = dwc3_omap_read_utmi_ctrl(omap);
 248                val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG;
 249                dwc3_omap_write_utmi_ctrl(omap, val);
 250                break;
 251
 252        case OMAP_DWC3_VBUS_OFF:
 253                val = dwc3_omap_read_utmi_ctrl(omap);
 254                val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID
 255                                | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID);
 256                val |= USBOTGSS_UTMI_OTG_CTRL_SESSEND;
 257                dwc3_omap_write_utmi_ctrl(omap, val);
 258                break;
 259
 260        default:
 261                dev_WARN(omap->dev, "invalid state\n");
 262        }
 263}
 264
 265static void dwc3_omap_enable_irqs(struct dwc3_omap *omap);
 266static void dwc3_omap_disable_irqs(struct dwc3_omap *omap);
 267
 268static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 269{
 270        struct dwc3_omap        *omap = _omap;
 271
 272        if (dwc3_omap_read_irqmisc_status(omap) ||
 273            dwc3_omap_read_irq0_status(omap)) {
 274                /* mask irqs */
 275                dwc3_omap_disable_irqs(omap);
 276                return IRQ_WAKE_THREAD;
 277        }
 278
 279        return IRQ_NONE;
 280}
 281
 282static irqreturn_t dwc3_omap_interrupt_thread(int irq, void *_omap)
 283{
 284        struct dwc3_omap        *omap = _omap;
 285        u32                     reg;
 286
 287        /* clear irq status flags */
 288        reg = dwc3_omap_read_irqmisc_status(omap);
 289        dwc3_omap_write_irqmisc_status(omap, reg);
 290
 291        reg = dwc3_omap_read_irq0_status(omap);
 292        dwc3_omap_write_irq0_status(omap, reg);
 293
 294        /* unmask irqs */
 295        dwc3_omap_enable_irqs(omap);
 296
 297        return IRQ_HANDLED;
 298}
 299
 300static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
 301{
 302        u32                     reg;
 303
 304        /* enable all IRQs */
 305        reg = USBOTGSS_IRQO_COREIRQ_ST;
 306        dwc3_omap_write_irq0_set(omap, reg);
 307
 308        reg = (USBOTGSS_IRQMISC_OEVT |
 309                        USBOTGSS_IRQMISC_DRVVBUS_RISE |
 310                        USBOTGSS_IRQMISC_CHRGVBUS_RISE |
 311                        USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
 312                        USBOTGSS_IRQMISC_IDPULLUP_RISE |
 313                        USBOTGSS_IRQMISC_DRVVBUS_FALL |
 314                        USBOTGSS_IRQMISC_CHRGVBUS_FALL |
 315                        USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
 316                        USBOTGSS_IRQMISC_IDPULLUP_FALL);
 317
 318        dwc3_omap_write_irqmisc_set(omap, reg);
 319}
 320
 321static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
 322{
 323        u32                     reg;
 324
 325        /* disable all IRQs */
 326        reg = USBOTGSS_IRQO_COREIRQ_ST;
 327        dwc3_omap_write_irq0_clr(omap, reg);
 328
 329        reg = (USBOTGSS_IRQMISC_OEVT |
 330                        USBOTGSS_IRQMISC_DRVVBUS_RISE |
 331                        USBOTGSS_IRQMISC_CHRGVBUS_RISE |
 332                        USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
 333                        USBOTGSS_IRQMISC_IDPULLUP_RISE |
 334                        USBOTGSS_IRQMISC_DRVVBUS_FALL |
 335                        USBOTGSS_IRQMISC_CHRGVBUS_FALL |
 336                        USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
 337                        USBOTGSS_IRQMISC_IDPULLUP_FALL);
 338
 339        dwc3_omap_write_irqmisc_clr(omap, reg);
 340}
 341
 342static int dwc3_omap_id_notifier(struct notifier_block *nb,
 343        unsigned long event, void *ptr)
 344{
 345        struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, id_nb);
 346
 347        if (event)
 348                dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
 349        else
 350                dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
 351
 352        return NOTIFY_DONE;
 353}
 354
 355static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
 356        unsigned long event, void *ptr)
 357{
 358        struct dwc3_omap *omap = container_of(nb, struct dwc3_omap, vbus_nb);
 359
 360        if (event)
 361                dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
 362        else
 363                dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
 364
 365        return NOTIFY_DONE;
 366}
 367
 368static void dwc3_omap_map_offset(struct dwc3_omap *omap)
 369{
 370        struct device_node      *node = omap->dev->of_node;
 371
 372        /*
 373         * Differentiate between OMAP5 and AM437x.
 374         *
 375         * For OMAP5(ES2.0) and AM437x wrapper revision is same, even
 376         * though there are changes in wrapper register offsets.
 377         *
 378         * Using dt compatible to differentiate AM437x.
 379         */
 380        if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
 381                omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
 382                omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
 383                omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
 384                omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
 385                omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
 386        }
 387}
 388
 389static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
 390{
 391        u32                     reg;
 392        struct device_node      *node = omap->dev->of_node;
 393        u32                     utmi_mode = 0;
 394
 395        reg = dwc3_omap_read_utmi_ctrl(omap);
 396
 397        of_property_read_u32(node, "utmi-mode", &utmi_mode);
 398
 399        switch (utmi_mode) {
 400        case DWC3_OMAP_UTMI_MODE_SW:
 401                reg |= USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
 402                break;
 403        case DWC3_OMAP_UTMI_MODE_HW:
 404                reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
 405                break;
 406        default:
 407                dev_WARN(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
 408        }
 409
 410        dwc3_omap_write_utmi_ctrl(omap, reg);
 411}
 412
 413static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
 414{
 415        int                     ret;
 416        struct device_node      *node = omap->dev->of_node;
 417        struct extcon_dev       *edev;
 418
 419        if (of_property_read_bool(node, "extcon")) {
 420                edev = extcon_get_edev_by_phandle(omap->dev, 0);
 421                if (IS_ERR(edev)) {
 422                        dev_vdbg(omap->dev, "couldn't get extcon device\n");
 423                        return -EPROBE_DEFER;
 424                }
 425
 426                omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
 427                ret = devm_extcon_register_notifier(omap->dev, edev,
 428                                                EXTCON_USB, &omap->vbus_nb);
 429                if (ret < 0)
 430                        dev_vdbg(omap->dev, "failed to register notifier for USB\n");
 431
 432                omap->id_nb.notifier_call = dwc3_omap_id_notifier;
 433                ret = devm_extcon_register_notifier(omap->dev, edev,
 434                                                EXTCON_USB_HOST, &omap->id_nb);
 435                if (ret < 0)
 436                        dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
 437
 438                if (extcon_get_state(edev, EXTCON_USB) == true)
 439                        dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
 440                else
 441                        dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
 442
 443                if (extcon_get_state(edev, EXTCON_USB_HOST) == true)
 444                        dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
 445                else
 446                        dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
 447
 448                omap->edev = edev;
 449        }
 450
 451        return 0;
 452}
 453
 454static int dwc3_omap_probe(struct platform_device *pdev)
 455{
 456        struct device_node      *node = pdev->dev.of_node;
 457
 458        struct dwc3_omap        *omap;
 459        struct device           *dev = &pdev->dev;
 460        struct regulator        *vbus_reg = NULL;
 461
 462        int                     ret;
 463        int                     irq;
 464
 465        void __iomem            *base;
 466
 467        if (!node) {
 468                dev_err(dev, "device node not found\n");
 469                return -EINVAL;
 470        }
 471
 472        omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 473        if (!omap)
 474                return -ENOMEM;
 475
 476        platform_set_drvdata(pdev, omap);
 477
 478        irq = platform_get_irq(pdev, 0);
 479        if (irq < 0) {
 480                dev_err(dev, "missing IRQ resource: %d\n", irq);
 481                return irq;
 482        }
 483
 484        base = devm_platform_ioremap_resource(pdev, 0);
 485        if (IS_ERR(base))
 486                return PTR_ERR(base);
 487
 488        if (of_property_read_bool(node, "vbus-supply")) {
 489                vbus_reg = devm_regulator_get(dev, "vbus");
 490                if (IS_ERR(vbus_reg)) {
 491                        dev_err(dev, "vbus init failed\n");
 492                        return PTR_ERR(vbus_reg);
 493                }
 494        }
 495
 496        omap->dev       = dev;
 497        omap->irq       = irq;
 498        omap->base      = base;
 499        omap->vbus_reg  = vbus_reg;
 500
 501        pm_runtime_enable(dev);
 502        ret = pm_runtime_get_sync(dev);
 503        if (ret < 0) {
 504                dev_err(dev, "get_sync failed with err %d\n", ret);
 505                goto err1;
 506        }
 507
 508        dwc3_omap_map_offset(omap);
 509        dwc3_omap_set_utmi_mode(omap);
 510
 511        ret = dwc3_omap_extcon_register(omap);
 512        if (ret < 0)
 513                goto err1;
 514
 515        ret = of_platform_populate(node, NULL, NULL, dev);
 516        if (ret) {
 517                dev_err(&pdev->dev, "failed to create dwc3 core\n");
 518                goto err1;
 519        }
 520
 521        ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
 522                                        dwc3_omap_interrupt_thread, IRQF_SHARED,
 523                                        "dwc3-omap", omap);
 524        if (ret) {
 525                dev_err(dev, "failed to request IRQ #%d --> %d\n",
 526                        omap->irq, ret);
 527                goto err1;
 528        }
 529        dwc3_omap_enable_irqs(omap);
 530        return 0;
 531
 532err1:
 533        pm_runtime_put_sync(dev);
 534        pm_runtime_disable(dev);
 535
 536        return ret;
 537}
 538
 539static int dwc3_omap_remove(struct platform_device *pdev)
 540{
 541        struct dwc3_omap        *omap = platform_get_drvdata(pdev);
 542
 543        dwc3_omap_disable_irqs(omap);
 544        disable_irq(omap->irq);
 545        of_platform_depopulate(omap->dev);
 546        pm_runtime_put_sync(&pdev->dev);
 547        pm_runtime_disable(&pdev->dev);
 548
 549        return 0;
 550}
 551
 552static const struct of_device_id of_dwc3_match[] = {
 553        {
 554                .compatible =   "ti,dwc3"
 555        },
 556        {
 557                .compatible =   "ti,am437x-dwc3"
 558        },
 559        { },
 560};
 561MODULE_DEVICE_TABLE(of, of_dwc3_match);
 562
 563#ifdef CONFIG_PM_SLEEP
 564static int dwc3_omap_suspend(struct device *dev)
 565{
 566        struct dwc3_omap        *omap = dev_get_drvdata(dev);
 567
 568        omap->utmi_otg_ctrl = dwc3_omap_read_utmi_ctrl(omap);
 569        dwc3_omap_disable_irqs(omap);
 570
 571        return 0;
 572}
 573
 574static int dwc3_omap_resume(struct device *dev)
 575{
 576        struct dwc3_omap        *omap = dev_get_drvdata(dev);
 577
 578        dwc3_omap_write_utmi_ctrl(omap, omap->utmi_otg_ctrl);
 579        dwc3_omap_enable_irqs(omap);
 580
 581        pm_runtime_disable(dev);
 582        pm_runtime_set_active(dev);
 583        pm_runtime_enable(dev);
 584
 585        return 0;
 586}
 587
 588static void dwc3_omap_complete(struct device *dev)
 589{
 590        struct dwc3_omap        *omap = dev_get_drvdata(dev);
 591
 592        if (extcon_get_state(omap->edev, EXTCON_USB))
 593                dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
 594        else
 595                dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
 596
 597        if (extcon_get_state(omap->edev, EXTCON_USB_HOST))
 598                dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
 599        else
 600                dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
 601}
 602
 603static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
 604
 605        SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
 606        .complete = dwc3_omap_complete,
 607};
 608
 609#define DEV_PM_OPS      (&dwc3_omap_dev_pm_ops)
 610#else
 611#define DEV_PM_OPS      NULL
 612#endif /* CONFIG_PM_SLEEP */
 613
 614static struct platform_driver dwc3_omap_driver = {
 615        .probe          = dwc3_omap_probe,
 616        .remove         = dwc3_omap_remove,
 617        .driver         = {
 618                .name   = "omap-dwc3",
 619                .of_match_table = of_dwc3_match,
 620                .pm     = DEV_PM_OPS,
 621        },
 622};
 623
 624module_platform_driver(dwc3_omap_driver);
 625
 626MODULE_ALIAS("platform:omap-dwc3");
 627MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 628MODULE_LICENSE("GPL v2");
 629MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");
 630