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