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