linux/drivers/usb/musb/omap2430.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005-2007 by Texas Instruments
   3 * Some code has been taken from tusb6010.c
   4 * Copyrights for that are attributable to:
   5 * Copyright (C) 2006 Nokia Corporation
   6 * Tony Lindgren <tony@atomide.com>
   7 *
   8 * This file is part of the Inventra Controller Driver for Linux.
   9 *
  10 * The Inventra Controller Driver for Linux is free software; you
  11 * can redistribute it and/or modify it under the terms of the GNU
  12 * General Public License version 2 as published by the Free Software
  13 * Foundation.
  14 *
  15 * The Inventra Controller Driver for Linux is distributed in
  16 * the hope that it will be useful, but WITHOUT ANY WARRANTY;
  17 * without even the implied warranty of MERCHANTABILITY or
  18 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  19 * License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with The Inventra Controller Driver for Linux ; if not,
  23 * write to the Free Software Foundation, Inc., 59 Temple Place,
  24 * Suite 330, Boston, MA  02111-1307  USA
  25 *
  26 */
  27#include <linux/module.h>
  28#include <linux/kernel.h>
  29#include <linux/sched.h>
  30#include <linux/init.h>
  31#include <linux/list.h>
  32#include <linux/io.h>
  33#include <linux/of.h>
  34#include <linux/platform_device.h>
  35#include <linux/dma-mapping.h>
  36#include <linux/pm_runtime.h>
  37#include <linux/err.h>
  38#include <linux/delay.h>
  39#include <linux/usb/musb-omap.h>
  40#include <linux/usb/omap_control_usb.h>
  41
  42#include "musb_core.h"
  43#include "omap2430.h"
  44
  45struct omap2430_glue {
  46        struct device           *dev;
  47        struct platform_device  *musb;
  48        enum omap_musb_vbus_id_status status;
  49        struct work_struct      omap_musb_mailbox_work;
  50        struct device           *control_otghs;
  51};
  52#define glue_to_musb(g)         platform_get_drvdata(g->musb)
  53
  54static struct omap2430_glue     *_glue;
  55
  56static struct timer_list musb_idle_timer;
  57
  58static void musb_do_idle(unsigned long _musb)
  59{
  60        struct musb     *musb = (void *)_musb;
  61        unsigned long   flags;
  62        u8      power;
  63        u8      devctl;
  64
  65        spin_lock_irqsave(&musb->lock, flags);
  66
  67        switch (musb->xceiv->state) {
  68        case OTG_STATE_A_WAIT_BCON:
  69
  70                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
  71                if (devctl & MUSB_DEVCTL_BDEVICE) {
  72                        musb->xceiv->state = OTG_STATE_B_IDLE;
  73                        MUSB_DEV_MODE(musb);
  74                } else {
  75                        musb->xceiv->state = OTG_STATE_A_IDLE;
  76                        MUSB_HST_MODE(musb);
  77                }
  78                break;
  79        case OTG_STATE_A_SUSPEND:
  80                /* finish RESUME signaling? */
  81                if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
  82                        power = musb_readb(musb->mregs, MUSB_POWER);
  83                        power &= ~MUSB_POWER_RESUME;
  84                        dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power);
  85                        musb_writeb(musb->mregs, MUSB_POWER, power);
  86                        musb->is_active = 1;
  87                        musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
  88                                                | MUSB_PORT_STAT_RESUME);
  89                        musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
  90                        usb_hcd_poll_rh_status(musb->hcd);
  91                        /* NOTE: it might really be A_WAIT_BCON ... */
  92                        musb->xceiv->state = OTG_STATE_A_HOST;
  93                }
  94                break;
  95        case OTG_STATE_A_HOST:
  96                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
  97                if (devctl &  MUSB_DEVCTL_BDEVICE)
  98                        musb->xceiv->state = OTG_STATE_B_IDLE;
  99                else
 100                        musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
 101        default:
 102                break;
 103        }
 104        spin_unlock_irqrestore(&musb->lock, flags);
 105}
 106
 107
 108static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
 109{
 110        unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
 111        static unsigned long    last_timer;
 112
 113        if (timeout == 0)
 114                timeout = default_timeout;
 115
 116        /* Never idle if active, or when VBUS timeout is not set as host */
 117        if (musb->is_active || ((musb->a_wait_bcon == 0)
 118                        && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
 119                dev_dbg(musb->controller, "%s active, deleting timer\n",
 120                        usb_otg_state_string(musb->xceiv->state));
 121                del_timer(&musb_idle_timer);
 122                last_timer = jiffies;
 123                return;
 124        }
 125
 126        if (time_after(last_timer, timeout)) {
 127                if (!timer_pending(&musb_idle_timer))
 128                        last_timer = timeout;
 129                else {
 130                        dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n");
 131                        return;
 132                }
 133        }
 134        last_timer = timeout;
 135
 136        dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
 137                usb_otg_state_string(musb->xceiv->state),
 138                (unsigned long)jiffies_to_msecs(timeout - jiffies));
 139        mod_timer(&musb_idle_timer, timeout);
 140}
 141
 142static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 143{
 144        struct usb_otg  *otg = musb->xceiv->otg;
 145        u8              devctl;
 146        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 147        /* HDRC controls CPEN, but beware current surges during device
 148         * connect.  They can trigger transient overcurrent conditions
 149         * that must be ignored.
 150         */
 151
 152        devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 153
 154        if (is_on) {
 155                if (musb->xceiv->state == OTG_STATE_A_IDLE) {
 156                        int loops = 100;
 157                        /* start the session */
 158                        devctl |= MUSB_DEVCTL_SESSION;
 159                        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 160                        /*
 161                         * Wait for the musb to set as A device to enable the
 162                         * VBUS
 163                         */
 164                        while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
 165
 166                                mdelay(5);
 167                                cpu_relax();
 168
 169                                if (time_after(jiffies, timeout)
 170                                    || loops-- <= 0) {
 171                                        dev_err(musb->controller,
 172                                        "configured as A device timeout");
 173                                        break;
 174                                }
 175                        }
 176
 177                        otg_set_vbus(otg, 1);
 178                } else {
 179                        musb->is_active = 1;
 180                        otg->default_a = 1;
 181                        musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 182                        devctl |= MUSB_DEVCTL_SESSION;
 183                        MUSB_HST_MODE(musb);
 184                }
 185        } else {
 186                musb->is_active = 0;
 187
 188                /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
 189                 * jumping right to B_IDLE...
 190                 */
 191
 192                otg->default_a = 0;
 193                musb->xceiv->state = OTG_STATE_B_IDLE;
 194                devctl &= ~MUSB_DEVCTL_SESSION;
 195
 196                MUSB_DEV_MODE(musb);
 197        }
 198        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 199
 200        dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 201                /* otg %3x conf %08x prcm %08x */ "\n",
 202                usb_otg_state_string(musb->xceiv->state),
 203                musb_readb(musb->mregs, MUSB_DEVCTL));
 204}
 205
 206static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
 207{
 208        u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 209
 210        devctl |= MUSB_DEVCTL_SESSION;
 211        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 212
 213        return 0;
 214}
 215
 216static inline void omap2430_low_level_exit(struct musb *musb)
 217{
 218        u32 l;
 219
 220        /* in any role */
 221        l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 222        l |= ENABLEFORCE;       /* enable MSTANDBY */
 223        musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 224}
 225
 226static inline void omap2430_low_level_init(struct musb *musb)
 227{
 228        u32 l;
 229
 230        l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 231        l &= ~ENABLEFORCE;      /* disable MSTANDBY */
 232        musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 233}
 234
 235void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 236{
 237        struct omap2430_glue    *glue = _glue;
 238
 239        if (!glue) {
 240                pr_err("%s: musb core is not yet initialized\n", __func__);
 241                return;
 242        }
 243        glue->status = status;
 244
 245        if (!glue_to_musb(glue)) {
 246                pr_err("%s: musb core is not yet ready\n", __func__);
 247                return;
 248        }
 249
 250        schedule_work(&glue->omap_musb_mailbox_work);
 251}
 252EXPORT_SYMBOL_GPL(omap_musb_mailbox);
 253
 254static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 255{
 256        struct musb *musb = glue_to_musb(glue);
 257        struct device *dev = musb->controller;
 258        struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 259        struct omap_musb_board_data *data = pdata->board_data;
 260        struct usb_otg *otg = musb->xceiv->otg;
 261
 262        switch (glue->status) {
 263        case OMAP_MUSB_ID_GROUND:
 264                dev_dbg(dev, "ID GND\n");
 265
 266                otg->default_a = true;
 267                musb->xceiv->state = OTG_STATE_A_IDLE;
 268                musb->xceiv->last_event = USB_EVENT_ID;
 269                if (musb->gadget_driver) {
 270                        pm_runtime_get_sync(dev);
 271                        omap_control_usb_set_mode(glue->control_otghs,
 272                                USB_MODE_HOST);
 273                        omap2430_musb_set_vbus(musb, 1);
 274                }
 275                break;
 276
 277        case OMAP_MUSB_VBUS_VALID:
 278                dev_dbg(dev, "VBUS Connect\n");
 279
 280                otg->default_a = false;
 281                musb->xceiv->state = OTG_STATE_B_IDLE;
 282                musb->xceiv->last_event = USB_EVENT_VBUS;
 283                if (musb->gadget_driver)
 284                        pm_runtime_get_sync(dev);
 285                omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
 286                break;
 287
 288        case OMAP_MUSB_ID_FLOAT:
 289        case OMAP_MUSB_VBUS_OFF:
 290                dev_dbg(dev, "VBUS Disconnect\n");
 291
 292                musb->xceiv->last_event = USB_EVENT_NONE;
 293                if (musb->gadget_driver) {
 294                        omap2430_musb_set_vbus(musb, 0);
 295                        pm_runtime_mark_last_busy(dev);
 296                        pm_runtime_put_autosuspend(dev);
 297                }
 298
 299                if (data->interface_type == MUSB_INTERFACE_UTMI)
 300                        otg_set_vbus(musb->xceiv->otg, 0);
 301
 302                omap_control_usb_set_mode(glue->control_otghs,
 303                        USB_MODE_DISCONNECT);
 304                break;
 305        default:
 306                dev_dbg(dev, "ID float\n");
 307        }
 308}
 309
 310
 311static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
 312{
 313        struct omap2430_glue *glue = container_of(mailbox_work,
 314                                struct omap2430_glue, omap_musb_mailbox_work);
 315        omap_musb_set_mailbox(glue);
 316}
 317
 318static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
 319{
 320        unsigned long   flags;
 321        irqreturn_t     retval = IRQ_NONE;
 322        struct musb     *musb = __hci;
 323
 324        spin_lock_irqsave(&musb->lock, flags);
 325
 326        musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
 327        musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
 328        musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
 329
 330        if (musb->int_usb || musb->int_tx || musb->int_rx)
 331                retval = musb_interrupt(musb);
 332
 333        spin_unlock_irqrestore(&musb->lock, flags);
 334
 335        return retval;
 336}
 337
 338static int omap2430_musb_init(struct musb *musb)
 339{
 340        u32 l;
 341        int status = 0;
 342        struct device *dev = musb->controller;
 343        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 344        struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 345        struct omap_musb_board_data *data = plat->board_data;
 346
 347        /* We require some kind of external transceiver, hooked
 348         * up through ULPI.  TWL4030-family PMICs include one,
 349         * which needs a driver, drivers aren't always needed.
 350         */
 351        if (dev->parent->of_node)
 352                musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
 353                    "usb-phy", 0);
 354        else
 355                musb->xceiv = devm_usb_get_phy_dev(dev, 0);
 356
 357        if (IS_ERR(musb->xceiv)) {
 358                status = PTR_ERR(musb->xceiv);
 359
 360                if (status == -ENXIO)
 361                        return status;
 362
 363                pr_err("HS USB OTG: no transceiver configured\n");
 364                return -EPROBE_DEFER;
 365        }
 366
 367        musb->isr = omap2430_musb_interrupt;
 368
 369        status = pm_runtime_get_sync(dev);
 370        if (status < 0) {
 371                dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
 372                goto err1;
 373        }
 374
 375        l = musb_readl(musb->mregs, OTG_INTERFSEL);
 376
 377        if (data->interface_type == MUSB_INTERFACE_UTMI) {
 378                /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
 379                l &= ~ULPI_12PIN;       /* Disable ULPI */
 380                l |= UTMI_8BIT;         /* Enable UTMI  */
 381        } else {
 382                l |= ULPI_12PIN;
 383        }
 384
 385        musb_writel(musb->mregs, OTG_INTERFSEL, l);
 386
 387        pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
 388                        "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
 389                        musb_readl(musb->mregs, OTG_REVISION),
 390                        musb_readl(musb->mregs, OTG_SYSCONFIG),
 391                        musb_readl(musb->mregs, OTG_SYSSTATUS),
 392                        musb_readl(musb->mregs, OTG_INTERFSEL),
 393                        musb_readl(musb->mregs, OTG_SIMENABLE));
 394
 395        setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 396
 397        if (glue->status != OMAP_MUSB_UNKNOWN)
 398                omap_musb_set_mailbox(glue);
 399
 400        usb_phy_init(musb->xceiv);
 401
 402        pm_runtime_put_noidle(musb->controller);
 403        return 0;
 404
 405err1:
 406        return status;
 407}
 408
 409static void omap2430_musb_enable(struct musb *musb)
 410{
 411        u8              devctl;
 412        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 413        struct device *dev = musb->controller;
 414        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 415        struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 416        struct omap_musb_board_data *data = pdata->board_data;
 417
 418        switch (glue->status) {
 419
 420        case OMAP_MUSB_ID_GROUND:
 421                omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
 422                if (data->interface_type != MUSB_INTERFACE_UTMI)
 423                        break;
 424                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 425                /* start the session */
 426                devctl |= MUSB_DEVCTL_SESSION;
 427                musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 428                while (musb_readb(musb->mregs, MUSB_DEVCTL) &
 429                                MUSB_DEVCTL_BDEVICE) {
 430                        cpu_relax();
 431
 432                        if (time_after(jiffies, timeout)) {
 433                                dev_err(dev, "configured as A device timeout");
 434                                break;
 435                        }
 436                }
 437                break;
 438
 439        case OMAP_MUSB_VBUS_VALID:
 440                omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
 441                break;
 442
 443        default:
 444                break;
 445        }
 446}
 447
 448static void omap2430_musb_disable(struct musb *musb)
 449{
 450        struct device *dev = musb->controller;
 451        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 452
 453        if (glue->status != OMAP_MUSB_UNKNOWN)
 454                omap_control_usb_set_mode(glue->control_otghs,
 455                        USB_MODE_DISCONNECT);
 456}
 457
 458static int omap2430_musb_exit(struct musb *musb)
 459{
 460        del_timer_sync(&musb_idle_timer);
 461
 462        omap2430_low_level_exit(musb);
 463
 464        return 0;
 465}
 466
 467static const struct musb_platform_ops omap2430_ops = {
 468        .init           = omap2430_musb_init,
 469        .exit           = omap2430_musb_exit,
 470
 471        .set_mode       = omap2430_musb_set_mode,
 472        .try_idle       = omap2430_musb_try_idle,
 473
 474        .set_vbus       = omap2430_musb_set_vbus,
 475
 476        .enable         = omap2430_musb_enable,
 477        .disable        = omap2430_musb_disable,
 478};
 479
 480static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 481
 482static int omap2430_probe(struct platform_device *pdev)
 483{
 484        struct resource                 musb_resources[3];
 485        struct musb_hdrc_platform_data  *pdata = dev_get_platdata(&pdev->dev);
 486        struct omap_musb_board_data     *data;
 487        struct platform_device          *musb;
 488        struct omap2430_glue            *glue;
 489        struct device_node              *np = pdev->dev.of_node;
 490        struct musb_hdrc_config         *config;
 491        int                             ret = -ENOMEM;
 492
 493        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 494        if (!glue) {
 495                dev_err(&pdev->dev, "failed to allocate glue context\n");
 496                goto err0;
 497        }
 498
 499        musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 500        if (!musb) {
 501                dev_err(&pdev->dev, "failed to allocate musb device\n");
 502                goto err0;
 503        }
 504
 505        musb->dev.parent                = &pdev->dev;
 506        musb->dev.dma_mask              = &omap2430_dmamask;
 507        musb->dev.coherent_dma_mask     = omap2430_dmamask;
 508
 509        glue->dev                       = &pdev->dev;
 510        glue->musb                      = musb;
 511        glue->status                    = OMAP_MUSB_UNKNOWN;
 512
 513        if (np) {
 514                pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 515                if (!pdata) {
 516                        dev_err(&pdev->dev,
 517                                "failed to allocate musb platform data\n");
 518                        goto err2;
 519                }
 520
 521                data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 522                if (!data) {
 523                        dev_err(&pdev->dev,
 524                                "failed to allocate musb board data\n");
 525                        goto err2;
 526                }
 527
 528                config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 529                if (!config) {
 530                        dev_err(&pdev->dev,
 531                                "failed to allocate musb hdrc config\n");
 532                        goto err2;
 533                }
 534
 535                of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
 536                of_property_read_u32(np, "interface-type",
 537                                                (u32 *)&data->interface_type);
 538                of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
 539                of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
 540                of_property_read_u32(np, "power", (u32 *)&pdata->power);
 541                config->multipoint = of_property_read_bool(np, "multipoint");
 542                pdata->has_mailbox = of_property_read_bool(np,
 543                    "ti,has-mailbox");
 544
 545                pdata->board_data       = data;
 546                pdata->config           = config;
 547        }
 548
 549        if (pdata->has_mailbox) {
 550                glue->control_otghs = omap_get_control_dev();
 551                if (IS_ERR(glue->control_otghs)) {
 552                        dev_vdbg(&pdev->dev, "Failed to get control device\n");
 553                        ret = PTR_ERR(glue->control_otghs);
 554                        goto err2;
 555                }
 556        } else {
 557                glue->control_otghs = ERR_PTR(-ENODEV);
 558        }
 559        pdata->platform_ops             = &omap2430_ops;
 560
 561        platform_set_drvdata(pdev, glue);
 562
 563        /*
 564         * REVISIT if we ever have two instances of the wrapper, we will be
 565         * in big trouble
 566         */
 567        _glue   = glue;
 568
 569        INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
 570
 571        memset(musb_resources, 0x00, sizeof(*musb_resources) *
 572                        ARRAY_SIZE(musb_resources));
 573
 574        musb_resources[0].name = pdev->resource[0].name;
 575        musb_resources[0].start = pdev->resource[0].start;
 576        musb_resources[0].end = pdev->resource[0].end;
 577        musb_resources[0].flags = pdev->resource[0].flags;
 578
 579        musb_resources[1].name = pdev->resource[1].name;
 580        musb_resources[1].start = pdev->resource[1].start;
 581        musb_resources[1].end = pdev->resource[1].end;
 582        musb_resources[1].flags = pdev->resource[1].flags;
 583
 584        musb_resources[2].name = pdev->resource[2].name;
 585        musb_resources[2].start = pdev->resource[2].start;
 586        musb_resources[2].end = pdev->resource[2].end;
 587        musb_resources[2].flags = pdev->resource[2].flags;
 588
 589        ret = platform_device_add_resources(musb, musb_resources,
 590                        ARRAY_SIZE(musb_resources));
 591        if (ret) {
 592                dev_err(&pdev->dev, "failed to add resources\n");
 593                goto err2;
 594        }
 595
 596        ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 597        if (ret) {
 598                dev_err(&pdev->dev, "failed to add platform_data\n");
 599                goto err2;
 600        }
 601
 602        pm_runtime_enable(&pdev->dev);
 603
 604        ret = platform_device_add(musb);
 605        if (ret) {
 606                dev_err(&pdev->dev, "failed to register musb device\n");
 607                goto err2;
 608        }
 609
 610        return 0;
 611
 612err2:
 613        platform_device_put(musb);
 614
 615err0:
 616        return ret;
 617}
 618
 619static int omap2430_remove(struct platform_device *pdev)
 620{
 621        struct omap2430_glue            *glue = platform_get_drvdata(pdev);
 622
 623        cancel_work_sync(&glue->omap_musb_mailbox_work);
 624        platform_device_unregister(glue->musb);
 625
 626        return 0;
 627}
 628
 629#ifdef CONFIG_PM
 630
 631static int omap2430_runtime_suspend(struct device *dev)
 632{
 633        struct omap2430_glue            *glue = dev_get_drvdata(dev);
 634        struct musb                     *musb = glue_to_musb(glue);
 635
 636        if (musb) {
 637                musb->context.otg_interfsel = musb_readl(musb->mregs,
 638                                OTG_INTERFSEL);
 639
 640                omap2430_low_level_exit(musb);
 641                usb_phy_set_suspend(musb->xceiv, 1);
 642        }
 643
 644        return 0;
 645}
 646
 647static int omap2430_runtime_resume(struct device *dev)
 648{
 649        struct omap2430_glue            *glue = dev_get_drvdata(dev);
 650        struct musb                     *musb = glue_to_musb(glue);
 651
 652        if (musb) {
 653                omap2430_low_level_init(musb);
 654                musb_writel(musb->mregs, OTG_INTERFSEL,
 655                                musb->context.otg_interfsel);
 656
 657                usb_phy_set_suspend(musb->xceiv, 0);
 658        }
 659
 660        return 0;
 661}
 662
 663static struct dev_pm_ops omap2430_pm_ops = {
 664        .runtime_suspend = omap2430_runtime_suspend,
 665        .runtime_resume = omap2430_runtime_resume,
 666};
 667
 668#define DEV_PM_OPS      (&omap2430_pm_ops)
 669#else
 670#define DEV_PM_OPS      NULL
 671#endif
 672
 673#ifdef CONFIG_OF
 674static const struct of_device_id omap2430_id_table[] = {
 675        {
 676                .compatible = "ti,omap4-musb"
 677        },
 678        {
 679                .compatible = "ti,omap3-musb"
 680        },
 681        {},
 682};
 683MODULE_DEVICE_TABLE(of, omap2430_id_table);
 684#endif
 685
 686static struct platform_driver omap2430_driver = {
 687        .probe          = omap2430_probe,
 688        .remove         = omap2430_remove,
 689        .driver         = {
 690                .name   = "musb-omap2430",
 691                .pm     = DEV_PM_OPS,
 692                .of_match_table = of_match_ptr(omap2430_id_table),
 693        },
 694};
 695
 696MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
 697MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 698MODULE_LICENSE("GPL v2");
 699
 700static int __init omap2430_init(void)
 701{
 702        return platform_driver_register(&omap2430_driver);
 703}
 704subsys_initcall(omap2430_init);
 705
 706static void __exit omap2430_exit(void)
 707{
 708        platform_driver_unregister(&omap2430_driver);
 709}
 710module_exit(omap2430_exit);
 711