~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/usb/musb-new/omap2430.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#define __UBOOT__
 
28
#ifndef __UBOOT__
 
29
#include <linux/module.h>
 
30
#include <linux/kernel.h>
 
31
#include <linux/sched.h>
 
32
#include <linux/init.h>
 
33
#include <linux/list.h>
 
34
#include <linux/io.h>
 
35
#include <linux/platform_device.h>
 
36
#include <linux/dma-mapping.h>
 
37
#include <linux/pm_runtime.h>
 
38
#include <linux/err.h>
 
39
#include <linux/usb/musb-omap.h>
 
40
#else
 
41
#include <common.h>
 
42
#include <asm/omap_musb.h>
 
43
#include <twl4030.h>
 
44
#include "linux-compat.h"
 
45
#endif
 
46
 
 
47
#include "musb_core.h"
 
48
#include "omap2430.h"
 
49
 
 
50
#ifndef __UBOOT__
 
51
struct omap2430_glue {
 
52
        struct device           *dev;
 
53
        struct platform_device  *musb;
 
54
        enum omap_musb_vbus_id_status status;
 
55
        struct work_struct      omap_musb_mailbox_work;
 
56
};
 
57
#define glue_to_musb(g)         platform_get_drvdata(g->musb)
 
58
 
 
59
struct omap2430_glue            *_glue;
 
60
 
 
61
static struct timer_list musb_idle_timer;
 
62
 
 
63
static void musb_do_idle(unsigned long _musb)
 
64
{
 
65
        struct musb     *musb = (void *)_musb;
 
66
        unsigned long   flags;
 
67
        u8      power;
 
68
        u8      devctl;
 
69
 
 
70
        spin_lock_irqsave(&musb->lock, flags);
 
71
 
 
72
        switch (musb->xceiv->state) {
 
73
        case OTG_STATE_A_WAIT_BCON:
 
74
 
 
75
                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
76
                if (devctl & MUSB_DEVCTL_BDEVICE) {
 
77
                        musb->xceiv->state = OTG_STATE_B_IDLE;
 
78
                        MUSB_DEV_MODE(musb);
 
79
                } else {
 
80
                        musb->xceiv->state = OTG_STATE_A_IDLE;
 
81
                        MUSB_HST_MODE(musb);
 
82
                }
 
83
                break;
 
84
        case OTG_STATE_A_SUSPEND:
 
85
                /* finish RESUME signaling? */
 
86
                if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
 
87
                        power = musb_readb(musb->mregs, MUSB_POWER);
 
88
                        power &= ~MUSB_POWER_RESUME;
 
89
                        dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power);
 
90
                        musb_writeb(musb->mregs, MUSB_POWER, power);
 
91
                        musb->is_active = 1;
 
92
                        musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
 
93
                                                | MUSB_PORT_STAT_RESUME);
 
94
                        musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
 
95
                        usb_hcd_poll_rh_status(musb_to_hcd(musb));
 
96
                        /* NOTE: it might really be A_WAIT_BCON ... */
 
97
                        musb->xceiv->state = OTG_STATE_A_HOST;
 
98
                }
 
99
                break;
 
100
        case OTG_STATE_A_HOST:
 
101
                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
102
                if (devctl &  MUSB_DEVCTL_BDEVICE)
 
103
                        musb->xceiv->state = OTG_STATE_B_IDLE;
 
104
                else
 
105
                        musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
 
106
        default:
 
107
                break;
 
108
        }
 
109
        spin_unlock_irqrestore(&musb->lock, flags);
 
110
}
 
111
 
 
112
 
 
113
static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
 
114
{
 
115
        unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
 
116
        static unsigned long    last_timer;
 
117
 
 
118
        if (timeout == 0)
 
119
                timeout = default_timeout;
 
120
 
 
121
        /* Never idle if active, or when VBUS timeout is not set as host */
 
122
        if (musb->is_active || ((musb->a_wait_bcon == 0)
 
123
                        && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
 
124
                dev_dbg(musb->controller, "%s active, deleting timer\n",
 
125
                        otg_state_string(musb->xceiv->state));
 
126
                del_timer(&musb_idle_timer);
 
127
                last_timer = jiffies;
 
128
                return;
 
129
        }
 
130
 
 
131
        if (time_after(last_timer, timeout)) {
 
132
                if (!timer_pending(&musb_idle_timer))
 
133
                        last_timer = timeout;
 
134
                else {
 
135
                        dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n");
 
136
                        return;
 
137
                }
 
138
        }
 
139
        last_timer = timeout;
 
140
 
 
141
        dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
 
142
                otg_state_string(musb->xceiv->state),
 
143
                (unsigned long)jiffies_to_msecs(timeout - jiffies));
 
144
        mod_timer(&musb_idle_timer, timeout);
 
145
}
 
146
 
 
147
static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 
148
{
 
149
        struct usb_otg  *otg = musb->xceiv->otg;
 
150
        u8              devctl;
 
151
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 
152
        int ret = 1;
 
153
        /* HDRC controls CPEN, but beware current surges during device
 
154
         * connect.  They can trigger transient overcurrent conditions
 
155
         * that must be ignored.
 
156
         */
 
157
 
 
158
        devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
159
 
 
160
        if (is_on) {
 
161
                if (musb->xceiv->state == OTG_STATE_A_IDLE) {
 
162
                        /* start the session */
 
163
                        devctl |= MUSB_DEVCTL_SESSION;
 
164
                        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
165
                        /*
 
166
                         * Wait for the musb to set as A device to enable the
 
167
                         * VBUS
 
168
                         */
 
169
                        while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
 
170
 
 
171
                                cpu_relax();
 
172
 
 
173
                                if (time_after(jiffies, timeout)) {
 
174
                                        dev_err(musb->controller,
 
175
                                        "configured as A device timeout");
 
176
                                        ret = -EINVAL;
 
177
                                        break;
 
178
                                }
 
179
                        }
 
180
 
 
181
                        if (ret && otg->set_vbus)
 
182
                                otg_set_vbus(otg, 1);
 
183
                } else {
 
184
                        musb->is_active = 1;
 
185
                        otg->default_a = 1;
 
186
                        musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 
187
                        devctl |= MUSB_DEVCTL_SESSION;
 
188
                        MUSB_HST_MODE(musb);
 
189
                }
 
190
        } else {
 
191
                musb->is_active = 0;
 
192
 
 
193
                /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
 
194
                 * jumping right to B_IDLE...
 
195
                 */
 
196
 
 
197
                otg->default_a = 0;
 
198
                musb->xceiv->state = OTG_STATE_B_IDLE;
 
199
                devctl &= ~MUSB_DEVCTL_SESSION;
 
200
 
 
201
                MUSB_DEV_MODE(musb);
 
202
        }
 
203
        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
204
 
 
205
        dev_dbg(musb->controller, "VBUS %s, devctl %02x "
 
206
                /* otg %3x conf %08x prcm %08x */ "\n",
 
207
                otg_state_string(musb->xceiv->state),
 
208
                musb_readb(musb->mregs, MUSB_DEVCTL));
 
209
}
 
210
 
 
211
static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
 
212
{
 
213
        u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
214
 
 
215
        devctl |= MUSB_DEVCTL_SESSION;
 
216
        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
217
 
 
218
        return 0;
 
219
}
 
220
#endif
 
221
 
 
222
static inline void omap2430_low_level_exit(struct musb *musb)
 
223
{
 
224
        u32 l;
 
225
 
 
226
        /* in any role */
 
227
        l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 
228
        l |= ENABLEFORCE;       /* enable MSTANDBY */
 
229
        musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 
230
}
 
231
 
 
232
static inline void omap2430_low_level_init(struct musb *musb)
 
233
{
 
234
        u32 l;
 
235
 
 
236
        l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 
237
        l &= ~ENABLEFORCE;      /* disable MSTANDBY */
 
238
        musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 
239
}
 
240
 
 
241
#ifndef __UBOOT__
 
242
void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 
243
{
 
244
        struct omap2430_glue    *glue = _glue;
 
245
        struct musb             *musb = glue_to_musb(glue);
 
246
 
 
247
        glue->status = status;
 
248
        if (!musb) {
 
249
                dev_err(glue->dev, "musb core is not yet ready\n");
 
250
                return;
 
251
        }
 
252
 
 
253
        schedule_work(&glue->omap_musb_mailbox_work);
 
254
}
 
255
EXPORT_SYMBOL_GPL(omap_musb_mailbox);
 
256
 
 
257
static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 
258
{
 
259
        struct musb *musb = glue_to_musb(glue);
 
260
        struct device *dev = musb->controller;
 
261
        struct musb_hdrc_platform_data *pdata = dev->platform_data;
 
262
        struct omap_musb_board_data *data = pdata->board_data;
 
263
        struct usb_otg *otg = musb->xceiv->otg;
 
264
 
 
265
        switch (glue->status) {
 
266
        case OMAP_MUSB_ID_GROUND:
 
267
                dev_dbg(dev, "ID GND\n");
 
268
 
 
269
                otg->default_a = true;
 
270
                musb->xceiv->state = OTG_STATE_A_IDLE;
 
271
                musb->xceiv->last_event = USB_EVENT_ID;
 
272
                if (!is_otg_enabled(musb) || musb->gadget_driver) {
 
273
                        pm_runtime_get_sync(dev);
 
274
                        usb_phy_init(musb->xceiv);
 
275
                        omap2430_musb_set_vbus(musb, 1);
 
276
                }
 
277
                break;
 
278
 
 
279
        case OMAP_MUSB_VBUS_VALID:
 
280
                dev_dbg(dev, "VBUS Connect\n");
 
281
 
 
282
                otg->default_a = false;
 
283
                musb->xceiv->state = OTG_STATE_B_IDLE;
 
284
                musb->xceiv->last_event = USB_EVENT_VBUS;
 
285
                if (musb->gadget_driver)
 
286
                        pm_runtime_get_sync(dev);
 
287
                usb_phy_init(musb->xceiv);
 
288
                break;
 
289
 
 
290
        case OMAP_MUSB_ID_FLOAT:
 
291
        case OMAP_MUSB_VBUS_OFF:
 
292
                dev_dbg(dev, "VBUS Disconnect\n");
 
293
 
 
294
                musb->xceiv->last_event = USB_EVENT_NONE;
 
295
                if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
 
296
                        if (musb->gadget_driver) {
 
297
                                pm_runtime_mark_last_busy(dev);
 
298
                                pm_runtime_put_autosuspend(dev);
 
299
                        }
 
300
 
 
301
                if (data->interface_type == MUSB_INTERFACE_UTMI) {
 
302
                        if (musb->xceiv->otg->set_vbus)
 
303
                                otg_set_vbus(musb->xceiv->otg, 0);
 
304
                }
 
305
                usb_phy_shutdown(musb->xceiv);
 
306
                break;
 
307
        default:
 
308
                dev_dbg(dev, "ID float\n");
 
309
        }
 
310
}
 
311
 
 
312
 
 
313
static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
 
314
{
 
315
        struct omap2430_glue *glue = container_of(mailbox_work,
 
316
                                struct omap2430_glue, omap_musb_mailbox_work);
 
317
        omap_musb_set_mailbox(glue);
 
318
}
 
319
#endif
 
320
 
 
321
static int omap2430_musb_init(struct musb *musb)
 
322
{
 
323
        u32 l;
 
324
        int status = 0;
 
325
#ifndef __UBOOT__
 
326
        struct device *dev = musb->controller;
 
327
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
328
        struct musb_hdrc_platform_data *plat = dev->platform_data;
 
329
        struct omap_musb_board_data *data = plat->board_data;
 
330
#else
 
331
        struct omap_musb_board_data *data =
 
332
                (struct omap_musb_board_data *)musb->controller;
 
333
#endif
 
334
 
 
335
 
 
336
#ifndef __UBOOT__
 
337
        /* We require some kind of external transceiver, hooked
 
338
         * up through ULPI.  TWL4030-family PMICs include one,
 
339
         * which needs a driver, drivers aren't always needed.
 
340
         */
 
341
        musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 
342
        if (IS_ERR_OR_NULL(musb->xceiv)) {
 
343
                pr_err("HS USB OTG: no transceiver configured\n");
 
344
                return -ENODEV;
 
345
        }
 
346
 
 
347
        status = pm_runtime_get_sync(dev);
 
348
        if (status < 0) {
 
349
                dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
 
350
                goto err1;
 
351
        }
 
352
#endif
 
353
 
 
354
        l = musb_readl(musb->mregs, OTG_INTERFSEL);
 
355
 
 
356
        if (data->interface_type == MUSB_INTERFACE_UTMI) {
 
357
                /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
 
358
                l &= ~ULPI_12PIN;       /* Disable ULPI */
 
359
                l |= UTMI_8BIT;         /* Enable UTMI  */
 
360
        } else {
 
361
                l |= ULPI_12PIN;
 
362
        }
 
363
 
 
364
        musb_writel(musb->mregs, OTG_INTERFSEL, l);
 
365
 
 
366
        pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
 
367
                        "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
 
368
                        musb_readl(musb->mregs, OTG_REVISION),
 
369
                        musb_readl(musb->mregs, OTG_SYSCONFIG),
 
370
                        musb_readl(musb->mregs, OTG_SYSSTATUS),
 
371
                        musb_readl(musb->mregs, OTG_INTERFSEL),
 
372
                        musb_readl(musb->mregs, OTG_SIMENABLE));
 
373
 
 
374
#ifndef __UBOOT__
 
375
        setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
376
 
 
377
        if (glue->status != OMAP_MUSB_UNKNOWN)
 
378
                omap_musb_set_mailbox(glue);
 
379
 
 
380
        pm_runtime_put_noidle(musb->controller);
 
381
#endif
 
382
        return 0;
 
383
 
 
384
err1:
 
385
        return status;
 
386
}
 
387
 
 
388
static void omap2430_musb_enable(struct musb *musb)
 
389
{
 
390
#ifndef __UBOOT__
 
391
        u8              devctl;
 
392
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 
393
        struct device *dev = musb->controller;
 
394
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
395
        struct musb_hdrc_platform_data *pdata = dev->platform_data;
 
396
        struct omap_musb_board_data *data = pdata->board_data;
 
397
 
 
398
        switch (glue->status) {
 
399
 
 
400
        case OMAP_MUSB_ID_GROUND:
 
401
                usb_phy_init(musb->xceiv);
 
402
                if (data->interface_type != MUSB_INTERFACE_UTMI)
 
403
                        break;
 
404
                devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 
405
                /* start the session */
 
406
                devctl |= MUSB_DEVCTL_SESSION;
 
407
                musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
408
                while (musb_readb(musb->mregs, MUSB_DEVCTL) &
 
409
                                MUSB_DEVCTL_BDEVICE) {
 
410
                        cpu_relax();
 
411
 
 
412
                        if (time_after(jiffies, timeout)) {
 
413
                                dev_err(dev, "configured as A device timeout");
 
414
                                break;
 
415
                        }
 
416
                }
 
417
                break;
 
418
 
 
419
        case OMAP_MUSB_VBUS_VALID:
 
420
                usb_phy_init(musb->xceiv);
 
421
                break;
 
422
 
 
423
        default:
 
424
                break;
 
425
        }
 
426
#else
 
427
#ifdef CONFIG_TWL4030_USB
 
428
        if (twl4030_usb_ulpi_init()) {
 
429
                serial_printf("ERROR: %s Could not initialize PHY\n",
 
430
                                __PRETTY_FUNCTION__);
 
431
        }
 
432
#endif
 
433
#endif
 
434
}
 
435
 
 
436
static void omap2430_musb_disable(struct musb *musb)
 
437
{
 
438
#ifndef __UBOOT__
 
439
        struct device *dev = musb->controller;
 
440
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
441
 
 
442
        if (glue->status != OMAP_MUSB_UNKNOWN)
 
443
                usb_phy_shutdown(musb->xceiv);
 
444
#endif
 
445
}
 
446
 
 
447
static int omap2430_musb_exit(struct musb *musb)
 
448
{
 
449
        del_timer_sync(&musb_idle_timer);
 
450
 
 
451
        omap2430_low_level_exit(musb);
 
452
 
 
453
        return 0;
 
454
}
 
455
 
 
456
#ifndef __UBOOT__
 
457
static const struct musb_platform_ops omap2430_ops = {
 
458
#else
 
459
const struct musb_platform_ops omap2430_ops = {
 
460
#endif
 
461
        .init           = omap2430_musb_init,
 
462
        .exit           = omap2430_musb_exit,
 
463
 
 
464
#ifndef __UBOOT__
 
465
        .set_mode       = omap2430_musb_set_mode,
 
466
        .try_idle       = omap2430_musb_try_idle,
 
467
 
 
468
        .set_vbus       = omap2430_musb_set_vbus,
 
469
#endif
 
470
 
 
471
        .enable         = omap2430_musb_enable,
 
472
        .disable        = omap2430_musb_disable,
 
473
};
 
474
 
 
475
#ifndef __UBOOT__
 
476
static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 
477
 
 
478
static int __devinit omap2430_probe(struct platform_device *pdev)
 
479
{
 
480
        struct musb_hdrc_platform_data  *pdata = pdev->dev.platform_data;
 
481
        struct platform_device          *musb;
 
482
        struct omap2430_glue            *glue;
 
483
        int                             ret = -ENOMEM;
 
484
 
 
485
        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 
486
        if (!glue) {
 
487
                dev_err(&pdev->dev, "failed to allocate glue context\n");
 
488
                goto err0;
 
489
        }
 
490
 
 
491
        musb = platform_device_alloc("musb-hdrc", -1);
 
492
        if (!musb) {
 
493
                dev_err(&pdev->dev, "failed to allocate musb device\n");
 
494
                goto err0;
 
495
        }
 
496
 
 
497
        musb->dev.parent                = &pdev->dev;
 
498
        musb->dev.dma_mask              = &omap2430_dmamask;
 
499
        musb->dev.coherent_dma_mask     = omap2430_dmamask;
 
500
 
 
501
        glue->dev                       = &pdev->dev;
 
502
        glue->musb                      = musb;
 
503
        glue->status                    = OMAP_MUSB_UNKNOWN;
 
504
 
 
505
        pdata->platform_ops             = &omap2430_ops;
 
506
 
 
507
        platform_set_drvdata(pdev, glue);
 
508
 
 
509
        /*
 
510
         * REVISIT if we ever have two instances of the wrapper, we will be
 
511
         * in big trouble
 
512
         */
 
513
        _glue   = glue;
 
514
 
 
515
        INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
 
516
 
 
517
        ret = platform_device_add_resources(musb, pdev->resource,
 
518
                        pdev->num_resources);
 
519
        if (ret) {
 
520
                dev_err(&pdev->dev, "failed to add resources\n");
 
521
                goto err1;
 
522
        }
 
523
 
 
524
        ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 
525
        if (ret) {
 
526
                dev_err(&pdev->dev, "failed to add platform_data\n");
 
527
                goto err1;
 
528
        }
 
529
 
 
530
        pm_runtime_enable(&pdev->dev);
 
531
 
 
532
        ret = platform_device_add(musb);
 
533
        if (ret) {
 
534
                dev_err(&pdev->dev, "failed to register musb device\n");
 
535
                goto err1;
 
536
        }
 
537
 
 
538
        return 0;
 
539
 
 
540
err1:
 
541
        platform_device_put(musb);
 
542
 
 
543
err0:
 
544
        return ret;
 
545
}
 
546
 
 
547
static int __devexit omap2430_remove(struct platform_device *pdev)
 
548
{
 
549
        struct omap2430_glue            *glue = platform_get_drvdata(pdev);
 
550
 
 
551
        cancel_work_sync(&glue->omap_musb_mailbox_work);
 
552
        platform_device_del(glue->musb);
 
553
        platform_device_put(glue->musb);
 
554
 
 
555
        return 0;
 
556
}
 
557
 
 
558
#ifdef CONFIG_PM
 
559
 
 
560
static int omap2430_runtime_suspend(struct device *dev)
 
561
{
 
562
        struct omap2430_glue            *glue = dev_get_drvdata(dev);
 
563
        struct musb                     *musb = glue_to_musb(glue);
 
564
 
 
565
        if (musb) {
 
566
                musb->context.otg_interfsel = musb_readl(musb->mregs,
 
567
                                OTG_INTERFSEL);
 
568
 
 
569
                omap2430_low_level_exit(musb);
 
570
                usb_phy_set_suspend(musb->xceiv, 1);
 
571
        }
 
572
 
 
573
        return 0;
 
574
}
 
575
 
 
576
static int omap2430_runtime_resume(struct device *dev)
 
577
{
 
578
        struct omap2430_glue            *glue = dev_get_drvdata(dev);
 
579
        struct musb                     *musb = glue_to_musb(glue);
 
580
 
 
581
        if (musb) {
 
582
                omap2430_low_level_init(musb);
 
583
                musb_writel(musb->mregs, OTG_INTERFSEL,
 
584
                                musb->context.otg_interfsel);
 
585
 
 
586
                usb_phy_set_suspend(musb->xceiv, 0);
 
587
        }
 
588
 
 
589
        return 0;
 
590
}
 
591
 
 
592
static struct dev_pm_ops omap2430_pm_ops = {
 
593
        .runtime_suspend = omap2430_runtime_suspend,
 
594
        .runtime_resume = omap2430_runtime_resume,
 
595
};
 
596
 
 
597
#define DEV_PM_OPS      (&omap2430_pm_ops)
 
598
#else
 
599
#define DEV_PM_OPS      NULL
 
600
#endif
 
601
 
 
602
static struct platform_driver omap2430_driver = {
 
603
        .probe          = omap2430_probe,
 
604
        .remove         = __devexit_p(omap2430_remove),
 
605
        .driver         = {
 
606
                .name   = "musb-omap2430",
 
607
                .pm     = DEV_PM_OPS,
 
608
        },
 
609
};
 
610
 
 
611
MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
 
612
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 
613
MODULE_LICENSE("GPL v2");
 
614
 
 
615
static int __init omap2430_init(void)
 
616
{
 
617
        return platform_driver_register(&omap2430_driver);
 
618
}
 
619
subsys_initcall(omap2430_init);
 
620
 
 
621
static void __exit omap2430_exit(void)
 
622
{
 
623
        platform_driver_unregister(&omap2430_driver);
 
624
}
 
625
module_exit(omap2430_exit);
 
626
#endif