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