uboot/drivers/usb/musb-new/musb_dsps.c
<<
>>
Prefs
   1/*
   2 * Texas Instruments DSPS platforms "glue layer"
   3 *
   4 * Copyright (C) 2012, by Texas Instruments
   5 *
   6 * Based on the am35x "glue layer" code.
   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 * musb_dsps.c will be a common file for all the TI DSPS platforms
  27 * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
  28 * For now only ti81x is using this and in future davinci.c, am35x.c
  29 * da8xx.c would be merged to this file after testing.
  30 */
  31
  32#define __UBOOT__
  33#ifndef __UBOOT__
  34#include <linux/init.h>
  35#include <linux/io.h>
  36#include <linux/err.h>
  37#include <linux/platform_device.h>
  38#include <linux/dma-mapping.h>
  39#include <linux/pm_runtime.h>
  40#include <linux/module.h>
  41
  42#include <linux/of.h>
  43#include <linux/of_device.h>
  44#include <linux/of_address.h>
  45
  46#include <plat/usb.h>
  47#else
  48#include <common.h>
  49#include <asm/omap_musb.h>
  50#include "linux-compat.h"
  51#endif
  52
  53#include "musb_core.h"
  54
  55/**
  56 * avoid using musb_readx()/musb_writex() as glue layer should not be
  57 * dependent on musb core layer symbols.
  58 */
  59static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
  60        { return __raw_readb(addr + offset); }
  61
  62static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
  63        { return __raw_readl(addr + offset); }
  64
  65static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
  66        { __raw_writeb(data, addr + offset); }
  67
  68static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
  69        { __raw_writel(data, addr + offset); }
  70
  71/**
  72 * DSPS musb wrapper register offset.
  73 * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
  74 * musb ips.
  75 */
  76struct dsps_musb_wrapper {
  77        u16     revision;
  78        u16     control;
  79        u16     status;
  80        u16     eoi;
  81        u16     epintr_set;
  82        u16     epintr_clear;
  83        u16     epintr_status;
  84        u16     coreintr_set;
  85        u16     coreintr_clear;
  86        u16     coreintr_status;
  87        u16     phy_utmi;
  88        u16     mode;
  89
  90        /* bit positions for control */
  91        unsigned        reset:5;
  92
  93        /* bit positions for interrupt */
  94        unsigned        usb_shift:5;
  95        u32             usb_mask;
  96        u32             usb_bitmap;
  97        unsigned        drvvbus:5;
  98
  99        unsigned        txep_shift:5;
 100        u32             txep_mask;
 101        u32             txep_bitmap;
 102
 103        unsigned        rxep_shift:5;
 104        u32             rxep_mask;
 105        u32             rxep_bitmap;
 106
 107        /* bit positions for phy_utmi */
 108        unsigned        otg_disable:5;
 109
 110        /* bit positions for mode */
 111        unsigned        iddig:5;
 112        /* miscellaneous stuff */
 113        u32             musb_core_offset;
 114        u8              poll_seconds;
 115};
 116
 117static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
 118        .revision               = 0x00,
 119        .control                = 0x14,
 120        .status                 = 0x18,
 121        .eoi                    = 0x24,
 122        .epintr_set             = 0x38,
 123        .epintr_clear           = 0x40,
 124        .epintr_status          = 0x30,
 125        .coreintr_set           = 0x3c,
 126        .coreintr_clear         = 0x44,
 127        .coreintr_status        = 0x34,
 128        .phy_utmi               = 0xe0,
 129        .mode                   = 0xe8,
 130        .reset                  = 0,
 131        .otg_disable            = 21,
 132        .iddig                  = 8,
 133        .usb_shift              = 0,
 134        .usb_mask               = 0x1ff,
 135        .usb_bitmap             = (0x1ff << 0),
 136        .drvvbus                = 8,
 137        .txep_shift             = 0,
 138        .txep_mask              = 0xffff,
 139        .txep_bitmap            = (0xffff << 0),
 140        .rxep_shift             = 16,
 141        .rxep_mask              = 0xfffe,
 142        .rxep_bitmap            = (0xfffe << 16),
 143        .musb_core_offset       = 0x400,
 144        .poll_seconds           = 2,
 145};
 146
 147/**
 148 * DSPS glue structure.
 149 */
 150struct dsps_glue {
 151        struct device *dev;
 152        struct platform_device *musb;   /* child musb pdev */
 153        const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
 154        struct timer_list timer;        /* otg_workaround timer */
 155};
 156
 157/**
 158 * dsps_musb_enable - enable interrupts
 159 */
 160static void dsps_musb_enable(struct musb *musb)
 161{
 162#ifndef __UBOOT__
 163        struct device *dev = musb->controller;
 164        struct platform_device *pdev = to_platform_device(dev->parent);
 165        struct dsps_glue *glue = platform_get_drvdata(pdev);
 166        const struct dsps_musb_wrapper *wrp = glue->wrp;
 167#else
 168        const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data;
 169#endif
 170        void __iomem *reg_base = musb->ctrl_base;
 171        u32 epmask, coremask;
 172
 173        /* Workaround: setup IRQs through both register sets. */
 174        epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
 175               ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
 176        coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
 177
 178        dsps_writel(reg_base, wrp->epintr_set, epmask);
 179        dsps_writel(reg_base, wrp->coreintr_set, coremask);
 180        /* Force the DRVVBUS IRQ so we can start polling for ID change. */
 181#ifndef __UBOOT__
 182        if (is_otg_enabled(musb))
 183                dsps_writel(reg_base, wrp->coreintr_set,
 184                            (1 << wrp->drvvbus) << wrp->usb_shift);
 185#endif
 186}
 187
 188/**
 189 * dsps_musb_disable - disable HDRC and flush interrupts
 190 */
 191static void dsps_musb_disable(struct musb *musb)
 192{
 193#ifndef __UBOOT__
 194        struct device *dev = musb->controller;
 195        struct platform_device *pdev = to_platform_device(dev->parent);
 196        struct dsps_glue *glue = platform_get_drvdata(pdev);
 197        const struct dsps_musb_wrapper *wrp = glue->wrp;
 198        void __iomem *reg_base = musb->ctrl_base;
 199
 200        dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
 201        dsps_writel(reg_base, wrp->epintr_clear,
 202                         wrp->txep_bitmap | wrp->rxep_bitmap);
 203        dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
 204        dsps_writel(reg_base, wrp->eoi, 0);
 205#endif
 206}
 207
 208#ifndef __UBOOT__
 209static void otg_timer(unsigned long _musb)
 210{
 211        struct musb *musb = (void *)_musb;
 212        void __iomem *mregs = musb->mregs;
 213        struct device *dev = musb->controller;
 214        struct platform_device *pdev = to_platform_device(dev->parent);
 215        struct dsps_glue *glue = platform_get_drvdata(pdev);
 216        const struct dsps_musb_wrapper *wrp = glue->wrp;
 217        u8 devctl;
 218        unsigned long flags;
 219
 220        /*
 221         * We poll because DSPS IP's won't expose several OTG-critical
 222         * status change events (from the transceiver) otherwise.
 223         */
 224        devctl = dsps_readb(mregs, MUSB_DEVCTL);
 225        dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
 226                                otg_state_string(musb->xceiv->state));
 227
 228        spin_lock_irqsave(&musb->lock, flags);
 229        switch (musb->xceiv->state) {
 230        case OTG_STATE_A_WAIT_BCON:
 231                devctl &= ~MUSB_DEVCTL_SESSION;
 232                dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 233
 234                devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
 235                if (devctl & MUSB_DEVCTL_BDEVICE) {
 236                        musb->xceiv->state = OTG_STATE_B_IDLE;
 237                        MUSB_DEV_MODE(musb);
 238                } else {
 239                        musb->xceiv->state = OTG_STATE_A_IDLE;
 240                        MUSB_HST_MODE(musb);
 241                }
 242                break;
 243        case OTG_STATE_A_WAIT_VFALL:
 244                musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 245                dsps_writel(musb->ctrl_base, wrp->coreintr_set,
 246                            MUSB_INTR_VBUSERROR << wrp->usb_shift);
 247                break;
 248        case OTG_STATE_B_IDLE:
 249                if (!is_peripheral_enabled(musb))
 250                        break;
 251
 252                devctl = dsps_readb(mregs, MUSB_DEVCTL);
 253                if (devctl & MUSB_DEVCTL_BDEVICE)
 254                        mod_timer(&glue->timer,
 255                                        jiffies + wrp->poll_seconds * HZ);
 256                else
 257                        musb->xceiv->state = OTG_STATE_A_IDLE;
 258                break;
 259        default:
 260                break;
 261        }
 262        spin_unlock_irqrestore(&musb->lock, flags);
 263}
 264
 265static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
 266{
 267        struct device *dev = musb->controller;
 268        struct platform_device *pdev = to_platform_device(dev->parent);
 269        struct dsps_glue *glue = platform_get_drvdata(pdev);
 270        static unsigned long last_timer;
 271
 272        if (!is_otg_enabled(musb))
 273                return;
 274
 275        if (timeout == 0)
 276                timeout = jiffies + msecs_to_jiffies(3);
 277
 278        /* Never idle if active, or when VBUS timeout is not set as host */
 279        if (musb->is_active || (musb->a_wait_bcon == 0 &&
 280                                musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
 281                dev_dbg(musb->controller, "%s active, deleting timer\n",
 282                                otg_state_string(musb->xceiv->state));
 283                del_timer(&glue->timer);
 284                last_timer = jiffies;
 285                return;
 286        }
 287
 288        if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) {
 289                dev_dbg(musb->controller,
 290                        "Longer idle timer already pending, ignoring...\n");
 291                return;
 292        }
 293        last_timer = timeout;
 294
 295        dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
 296                otg_state_string(musb->xceiv->state),
 297                        jiffies_to_msecs(timeout - jiffies));
 298        mod_timer(&glue->timer, timeout);
 299}
 300#endif
 301
 302static irqreturn_t dsps_interrupt(int irq, void *hci)
 303{
 304        struct musb  *musb = hci;
 305        void __iomem *reg_base = musb->ctrl_base;
 306#ifndef __UBOOT__
 307        struct device *dev = musb->controller;
 308        struct platform_device *pdev = to_platform_device(dev->parent);
 309        struct dsps_glue *glue = platform_get_drvdata(pdev);
 310        const struct dsps_musb_wrapper *wrp = glue->wrp;
 311#else
 312        const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data;
 313#endif
 314        unsigned long flags;
 315        irqreturn_t ret = IRQ_NONE;
 316        u32 epintr, usbintr;
 317
 318        spin_lock_irqsave(&musb->lock, flags);
 319
 320        /* Get endpoint interrupts */
 321        epintr = dsps_readl(reg_base, wrp->epintr_status);
 322        musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
 323        musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
 324
 325        if (epintr)
 326                dsps_writel(reg_base, wrp->epintr_status, epintr);
 327
 328        /* Get usb core interrupts */
 329        usbintr = dsps_readl(reg_base, wrp->coreintr_status);
 330        if (!usbintr && !epintr)
 331                goto eoi;
 332
 333        musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
 334        if (usbintr)
 335                dsps_writel(reg_base, wrp->coreintr_status, usbintr);
 336
 337        dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
 338                        usbintr, epintr);
 339#ifndef __UBOOT__
 340        /*
 341         * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
 342         * DSPS IP's missing ID change IRQ.  We need an ID change IRQ to
 343         * switch appropriately between halves of the OTG state machine.
 344         * Managing DEVCTL.SESSION per Mentor docs requires that we know its
 345         * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
 346         * Also, DRVVBUS pulses for SRP (but not at 5V) ...
 347         */
 348        if ((usbintr & MUSB_INTR_BABBLE) && is_host_enabled(musb))
 349                pr_info("CAUTION: musb: Babble Interrupt Occured\n");
 350
 351        if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
 352                int drvvbus = dsps_readl(reg_base, wrp->status);
 353                void __iomem *mregs = musb->mregs;
 354                u8 devctl = dsps_readb(mregs, MUSB_DEVCTL);
 355                int err;
 356
 357                err = is_host_enabled(musb) && (musb->int_usb &
 358                                                MUSB_INTR_VBUSERROR);
 359                if (err) {
 360                        /*
 361                         * The Mentor core doesn't debounce VBUS as needed
 362                         * to cope with device connect current spikes. This
 363                         * means it's not uncommon for bus-powered devices
 364                         * to get VBUS errors during enumeration.
 365                         *
 366                         * This is a workaround, but newer RTL from Mentor
 367                         * seems to allow a better one: "re"-starting sessions
 368                         * without waiting for VBUS to stop registering in
 369                         * devctl.
 370                         */
 371                        musb->int_usb &= ~MUSB_INTR_VBUSERROR;
 372                        musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
 373                        mod_timer(&glue->timer,
 374                                        jiffies + wrp->poll_seconds * HZ);
 375                        WARNING("VBUS error workaround (delay coming)\n");
 376                } else if (is_host_enabled(musb) && drvvbus) {
 377                        musb->is_active = 1;
 378                        MUSB_HST_MODE(musb);
 379                        musb->xceiv->otg->default_a = 1;
 380                        musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 381                        del_timer(&glue->timer);
 382                } else {
 383                        musb->is_active = 0;
 384                        MUSB_DEV_MODE(musb);
 385                        musb->xceiv->otg->default_a = 0;
 386                        musb->xceiv->state = OTG_STATE_B_IDLE;
 387                }
 388
 389                /* NOTE: this must complete power-on within 100 ms. */
 390                dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
 391                                drvvbus ? "on" : "off",
 392                                otg_state_string(musb->xceiv->state),
 393                                err ? " ERROR" : "",
 394                                devctl);
 395                ret = IRQ_HANDLED;
 396        }
 397#endif
 398
 399        if (musb->int_tx || musb->int_rx || musb->int_usb)
 400                ret |= musb_interrupt(musb);
 401
 402 eoi:
 403        /* EOI needs to be written for the IRQ to be re-asserted. */
 404        if (ret == IRQ_HANDLED || epintr || usbintr)
 405                dsps_writel(reg_base, wrp->eoi, 1);
 406
 407#ifndef __UBOOT__
 408        /* Poll for ID change */
 409        if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
 410                mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
 411#endif
 412
 413        spin_unlock_irqrestore(&musb->lock, flags);
 414
 415        return ret;
 416}
 417
 418static int dsps_musb_init(struct musb *musb)
 419{
 420#ifndef __UBOOT__
 421        struct device *dev = musb->controller;
 422        struct musb_hdrc_platform_data *plat = dev->platform_data;
 423        struct platform_device *pdev = to_platform_device(dev->parent);
 424        struct dsps_glue *glue = platform_get_drvdata(pdev);
 425        const struct dsps_musb_wrapper *wrp = glue->wrp;
 426        struct omap_musb_board_data *data = plat->board_data;
 427#else
 428        struct omap_musb_board_data *data =
 429                        (struct omap_musb_board_data *)musb->controller;
 430        const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data;
 431#endif
 432        void __iomem *reg_base = musb->ctrl_base;
 433        u32 rev, val;
 434        int status;
 435
 436        /* mentor core register starts at offset of 0x400 from musb base */
 437        musb->mregs += wrp->musb_core_offset;
 438
 439#ifndef __UBOOT__
 440        /* NOP driver needs change if supporting dual instance */
 441        usb_nop_xceiv_register();
 442        musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
 443        if (IS_ERR_OR_NULL(musb->xceiv))
 444                return -ENODEV;
 445#endif
 446
 447        /* Returns zero if e.g. not clocked */
 448        rev = dsps_readl(reg_base, wrp->revision);
 449        if (!rev) {
 450                status = -ENODEV;
 451                goto err0;
 452        }
 453
 454#ifndef __UBOOT__
 455        if (is_host_enabled(musb))
 456                setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
 457#endif
 458
 459        /* Reset the musb */
 460        dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
 461
 462        /* Start the on-chip PHY and its PLL. */
 463        if (data->set_phy_power)
 464                data->set_phy_power(1);
 465
 466        musb->isr = dsps_interrupt;
 467
 468        /* reset the otgdisable bit, needed for host mode to work */
 469        val = dsps_readl(reg_base, wrp->phy_utmi);
 470        val &= ~(1 << wrp->otg_disable);
 471        dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
 472
 473        /* clear level interrupt */
 474        dsps_writel(reg_base, wrp->eoi, 0);
 475
 476        return 0;
 477err0:
 478#ifndef __UBOOT__
 479        usb_put_phy(musb->xceiv);
 480        usb_nop_xceiv_unregister();
 481#endif
 482        return status;
 483}
 484
 485static int dsps_musb_exit(struct musb *musb)
 486{
 487#ifndef __UBOOT__
 488        struct device *dev = musb->controller;
 489        struct musb_hdrc_platform_data *plat = dev->platform_data;
 490        struct omap_musb_board_data *data = plat->board_data;
 491        struct platform_device *pdev = to_platform_device(dev->parent);
 492        struct dsps_glue *glue = platform_get_drvdata(pdev);
 493#else
 494        struct omap_musb_board_data *data =
 495                        (struct omap_musb_board_data *)musb->controller;
 496#endif
 497
 498#ifndef __UBOOT__
 499        if (is_host_enabled(musb))
 500                del_timer_sync(&glue->timer);
 501#endif
 502
 503        /* Shutdown the on-chip PHY and its PLL. */
 504        if (data->set_phy_power)
 505                data->set_phy_power(0);
 506
 507#ifndef __UBOOT__
 508        /* NOP driver needs change if supporting dual instance */
 509        usb_put_phy(musb->xceiv);
 510        usb_nop_xceiv_unregister();
 511#endif
 512
 513        return 0;
 514}
 515
 516#ifndef __UBOOT__
 517static struct musb_platform_ops dsps_ops = {
 518#else
 519struct musb_platform_ops musb_dsps_ops = {
 520#endif
 521        .init           = dsps_musb_init,
 522        .exit           = dsps_musb_exit,
 523
 524        .enable         = dsps_musb_enable,
 525        .disable        = dsps_musb_disable,
 526
 527#ifndef __UBOOT__
 528        .try_idle       = dsps_musb_try_idle,
 529#endif
 530};
 531
 532#ifndef __UBOOT__
 533static u64 musb_dmamask = DMA_BIT_MASK(32);
 534#endif
 535
 536#ifndef __UBOOT__
 537static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 538{
 539        struct device *dev = glue->dev;
 540        struct platform_device *pdev = to_platform_device(dev);
 541        struct musb_hdrc_platform_data  *pdata = dev->platform_data;
 542        struct platform_device  *musb;
 543        struct resource *res;
 544        struct resource resources[2];
 545        char res_name[10];
 546        int ret;
 547
 548        /* get memory resource */
 549        sprintf(res_name, "musb%d", id);
 550        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
 551        if (!res) {
 552                dev_err(dev, "%s get mem resource failed\n", res_name);
 553                ret = -ENODEV;
 554                goto err0;
 555        }
 556        res->parent = NULL;
 557        resources[0] = *res;
 558
 559        /* get irq resource */
 560        sprintf(res_name, "musb%d-irq", id);
 561        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
 562        if (!res) {
 563                dev_err(dev, "%s get irq resource failed\n", res_name);
 564                ret = -ENODEV;
 565                goto err0;
 566        }
 567        res->parent = NULL;
 568        resources[1] = *res;
 569        resources[1].name = "mc";
 570
 571        /* allocate the child platform device */
 572        musb = platform_device_alloc("musb-hdrc", -1);
 573        if (!musb) {
 574                dev_err(dev, "failed to allocate musb device\n");
 575                ret = -ENOMEM;
 576                goto err0;
 577        }
 578
 579        musb->dev.parent                = dev;
 580        musb->dev.dma_mask              = &musb_dmamask;
 581        musb->dev.coherent_dma_mask     = musb_dmamask;
 582
 583        glue->musb                      = musb;
 584
 585        pdata->platform_ops             = &dsps_ops;
 586
 587        ret = platform_device_add_resources(musb, resources, 2);
 588        if (ret) {
 589                dev_err(dev, "failed to add resources\n");
 590                goto err1;
 591        }
 592
 593        ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 594        if (ret) {
 595                dev_err(dev, "failed to add platform_data\n");
 596                goto err1;
 597        }
 598
 599        ret = platform_device_add(musb);
 600        if (ret) {
 601                dev_err(dev, "failed to register musb device\n");
 602                goto err1;
 603        }
 604
 605        return 0;
 606
 607err1:
 608        platform_device_put(musb);
 609err0:
 610        return ret;
 611}
 612
 613static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue)
 614{
 615        platform_device_del(glue->musb);
 616        platform_device_put(glue->musb);
 617}
 618
 619static int __devinit dsps_probe(struct platform_device *pdev)
 620{
 621        const struct platform_device_id *id = platform_get_device_id(pdev);
 622        const struct dsps_musb_wrapper *wrp =
 623                                (struct dsps_musb_wrapper *)id->driver_data;
 624        struct dsps_glue *glue;
 625        struct resource *iomem;
 626        int ret;
 627
 628        /* allocate glue */
 629        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 630        if (!glue) {
 631                dev_err(&pdev->dev, "unable to allocate glue memory\n");
 632                ret = -ENOMEM;
 633                goto err0;
 634        }
 635
 636        /* get memory resource */
 637        iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 638        if (!iomem) {
 639                dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
 640                ret = -ENODEV;
 641                goto err1;
 642        }
 643
 644        glue->dev = &pdev->dev;
 645
 646        glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
 647        if (!glue->wrp) {
 648                dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n");
 649                ret = -ENOMEM;
 650                goto err1;
 651        }
 652        platform_set_drvdata(pdev, glue);
 653
 654        /* enable the usbss clocks */
 655        pm_runtime_enable(&pdev->dev);
 656
 657        ret = pm_runtime_get_sync(&pdev->dev);
 658        if (ret < 0) {
 659                dev_err(&pdev->dev, "pm_runtime_get_sync FAILED");
 660                goto err2;
 661        }
 662
 663        /* create the child platform device for first instances of musb */
 664        ret = dsps_create_musb_pdev(glue, 0);
 665        if (ret != 0) {
 666                dev_err(&pdev->dev, "failed to create child pdev\n");
 667                goto err3;
 668        }
 669
 670        return 0;
 671
 672err3:
 673        pm_runtime_put(&pdev->dev);
 674err2:
 675        pm_runtime_disable(&pdev->dev);
 676        kfree(glue->wrp);
 677err1:
 678        kfree(glue);
 679err0:
 680        return ret;
 681}
 682static int __devexit dsps_remove(struct platform_device *pdev)
 683{
 684        struct dsps_glue *glue = platform_get_drvdata(pdev);
 685
 686        /* delete the child platform device */
 687        dsps_delete_musb_pdev(glue);
 688
 689        /* disable usbss clocks */
 690        pm_runtime_put(&pdev->dev);
 691        pm_runtime_disable(&pdev->dev);
 692        kfree(glue->wrp);
 693        kfree(glue);
 694        return 0;
 695}
 696
 697#ifdef CONFIG_PM_SLEEP
 698static int dsps_suspend(struct device *dev)
 699{
 700        struct musb_hdrc_platform_data *plat = dev->platform_data;
 701        struct omap_musb_board_data *data = plat->board_data;
 702
 703        /* Shutdown the on-chip PHY and its PLL. */
 704        if (data->set_phy_power)
 705                data->set_phy_power(0);
 706
 707        return 0;
 708}
 709
 710static int dsps_resume(struct device *dev)
 711{
 712        struct musb_hdrc_platform_data *plat = dev->platform_data;
 713        struct omap_musb_board_data *data = plat->board_data;
 714
 715        /* Start the on-chip PHY and its PLL. */
 716        if (data->set_phy_power)
 717                data->set_phy_power(1);
 718
 719        return 0;
 720}
 721#endif
 722
 723static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
 724#endif
 725
 726#ifndef __UBOOT__
 727static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
 728        {
 729                .name   = "musb-ti81xx",
 730                .driver_data    = (kernel_ulong_t) &ti81xx_driver_data,
 731        },
 732        {  },   /* Terminating Entry */
 733};
 734MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
 735
 736static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
 737        { .compatible = "musb-ti81xx", },
 738        { .compatible = "ti,ti81xx-musb", },
 739        { .compatible = "ti,am335x-musb", },
 740        {  },
 741};
 742MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
 743
 744static struct platform_driver dsps_usbss_driver = {
 745        .probe          = dsps_probe,
 746        .remove         = __devexit_p(dsps_remove),
 747        .driver         = {
 748                .name   = "musb-dsps",
 749                .pm     = &dsps_pm_ops,
 750                .of_match_table = musb_dsps_of_match,
 751        },
 752        .id_table       = musb_dsps_id_table,
 753};
 754
 755MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
 756MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
 757MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
 758MODULE_LICENSE("GPL v2");
 759
 760static int __init dsps_init(void)
 761{
 762        return platform_driver_register(&dsps_usbss_driver);
 763}
 764subsys_initcall(dsps_init);
 765
 766static void __exit dsps_exit(void)
 767{
 768        platform_driver_unregister(&dsps_usbss_driver);
 769}
 770module_exit(dsps_exit);
 771#endif
 772