15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
29ecb8875SAjay Kumar Gupta /*
39ecb8875SAjay Kumar Gupta * Texas Instruments DSPS platforms "glue layer"
49ecb8875SAjay Kumar Gupta *
59ecb8875SAjay Kumar Gupta * Copyright (C) 2012, by Texas Instruments
69ecb8875SAjay Kumar Gupta *
79ecb8875SAjay Kumar Gupta * Based on the am35x "glue layer" code.
89ecb8875SAjay Kumar Gupta *
99ecb8875SAjay Kumar Gupta * This file is part of the Inventra Controller Driver for Linux.
109ecb8875SAjay Kumar Gupta *
119ecb8875SAjay Kumar Gupta * musb_dsps.c will be a common file for all the TI DSPS platforms
129ecb8875SAjay Kumar Gupta * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
139ecb8875SAjay Kumar Gupta * For now only ti81x is using this and in future davinci.c, am35x.c
149ecb8875SAjay Kumar Gupta * da8xx.c would be merged to this file after testing.
159ecb8875SAjay Kumar Gupta */
169ecb8875SAjay Kumar Gupta
179ecb8875SAjay Kumar Gupta #include <linux/io.h>
18ce1d37cbSLad Prabhakar #include <linux/irq.h>
19ded017eeSKishon Vijay Abraham I #include <linux/err.h>
209ecb8875SAjay Kumar Gupta #include <linux/platform_device.h>
219ecb8875SAjay Kumar Gupta #include <linux/dma-mapping.h>
229ecb8875SAjay Kumar Gupta #include <linux/pm_runtime.h>
239ecb8875SAjay Kumar Gupta #include <linux/module.h>
24d7078df6SFelipe Balbi #include <linux/usb/usb_phy_generic.h>
25e8c4a7acSFelipe Balbi #include <linux/platform_data/usb-omap.h>
260f53e481SFelipe Balbi #include <linux/sizes.h>
279ecb8875SAjay Kumar Gupta
289ecb8875SAjay Kumar Gupta #include <linux/of.h>
299ecb8875SAjay Kumar Gupta #include <linux/of_address.h>
30c031a7d4SSebastian Andrzej Siewior #include <linux/usb/of.h>
319ecb8875SAjay Kumar Gupta
3240f099e3SMarkus Pargmann #include <linux/debugfs.h>
3340f099e3SMarkus Pargmann
349ecb8875SAjay Kumar Gupta #include "musb_core.h"
359ecb8875SAjay Kumar Gupta
3665145677SAjay Kumar Gupta static const struct of_device_id musb_dsps_of_match[];
3765145677SAjay Kumar Gupta
3809e03a89SLee Jones /*
399ecb8875SAjay Kumar Gupta * DSPS musb wrapper register offset.
409ecb8875SAjay Kumar Gupta * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
419ecb8875SAjay Kumar Gupta * musb ips.
429ecb8875SAjay Kumar Gupta */
439ecb8875SAjay Kumar Gupta struct dsps_musb_wrapper {
449ecb8875SAjay Kumar Gupta u16 revision;
459ecb8875SAjay Kumar Gupta u16 control;
469ecb8875SAjay Kumar Gupta u16 status;
479ecb8875SAjay Kumar Gupta u16 epintr_set;
489ecb8875SAjay Kumar Gupta u16 epintr_clear;
499ecb8875SAjay Kumar Gupta u16 epintr_status;
509ecb8875SAjay Kumar Gupta u16 coreintr_set;
519ecb8875SAjay Kumar Gupta u16 coreintr_clear;
529ecb8875SAjay Kumar Gupta u16 coreintr_status;
539ecb8875SAjay Kumar Gupta u16 phy_utmi;
549ecb8875SAjay Kumar Gupta u16 mode;
55b991f9b7SDaniel Mack u16 tx_mode;
56b991f9b7SDaniel Mack u16 rx_mode;
579ecb8875SAjay Kumar Gupta
589ecb8875SAjay Kumar Gupta /* bit positions for control */
599ecb8875SAjay Kumar Gupta unsigned reset:5;
609ecb8875SAjay Kumar Gupta
619ecb8875SAjay Kumar Gupta /* bit positions for interrupt */
629ecb8875SAjay Kumar Gupta unsigned usb_shift:5;
639ecb8875SAjay Kumar Gupta u32 usb_mask;
649ecb8875SAjay Kumar Gupta u32 usb_bitmap;
659ecb8875SAjay Kumar Gupta unsigned drvvbus:5;
669ecb8875SAjay Kumar Gupta
679ecb8875SAjay Kumar Gupta unsigned txep_shift:5;
689ecb8875SAjay Kumar Gupta u32 txep_mask;
699ecb8875SAjay Kumar Gupta u32 txep_bitmap;
709ecb8875SAjay Kumar Gupta
719ecb8875SAjay Kumar Gupta unsigned rxep_shift:5;
729ecb8875SAjay Kumar Gupta u32 rxep_mask;
739ecb8875SAjay Kumar Gupta u32 rxep_bitmap;
749ecb8875SAjay Kumar Gupta
759ecb8875SAjay Kumar Gupta /* bit positions for phy_utmi */
769ecb8875SAjay Kumar Gupta unsigned otg_disable:5;
779ecb8875SAjay Kumar Gupta
789ecb8875SAjay Kumar Gupta /* bit positions for mode */
799ecb8875SAjay Kumar Gupta unsigned iddig:5;
80943c1397SFelipe Balbi unsigned iddig_mux:5;
819ecb8875SAjay Kumar Gupta /* miscellaneous stuff */
829e204d88SFelipe Balbi unsigned poll_timeout;
839ecb8875SAjay Kumar Gupta };
849ecb8875SAjay Kumar Gupta
85869c5978SDaniel Mack /*
86869c5978SDaniel Mack * register shadow for suspend
87869c5978SDaniel Mack */
88869c5978SDaniel Mack struct dsps_context {
89869c5978SDaniel Mack u32 control;
90869c5978SDaniel Mack u32 epintr;
91869c5978SDaniel Mack u32 coreintr;
92869c5978SDaniel Mack u32 phy_utmi;
93869c5978SDaniel Mack u32 mode;
94869c5978SDaniel Mack u32 tx_mode;
95869c5978SDaniel Mack u32 rx_mode;
96869c5978SDaniel Mack };
97869c5978SDaniel Mack
9809e03a89SLee Jones /*
999ecb8875SAjay Kumar Gupta * DSPS glue structure.
1009ecb8875SAjay Kumar Gupta */
1019ecb8875SAjay Kumar Gupta struct dsps_glue {
1029ecb8875SAjay Kumar Gupta struct device *dev;
10397238b35SSebastian Andrzej Siewior struct platform_device *musb; /* child musb pdev */
1049ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
105369469a9STony Lindgren int vbus_irq; /* optional vbus irq */
10697238b35SSebastian Andrzej Siewior unsigned long last_timer; /* last timer data for each instance */
107371254ceSGeorge Cherian bool sw_babble_enabled;
10825534828SAlexandre Bailon void __iomem *usbss_base;
109869c5978SDaniel Mack
110869c5978SDaniel Mack struct dsps_context context;
11140f099e3SMarkus Pargmann struct debugfs_regset32 regset;
11240f099e3SMarkus Pargmann struct dentry *dbgfs_root;
11340f099e3SMarkus Pargmann };
11440f099e3SMarkus Pargmann
11540f099e3SMarkus Pargmann static const struct debugfs_reg32 dsps_musb_regs[] = {
11640f099e3SMarkus Pargmann { "revision", 0x00 },
11740f099e3SMarkus Pargmann { "control", 0x14 },
11840f099e3SMarkus Pargmann { "status", 0x18 },
11940f099e3SMarkus Pargmann { "eoi", 0x24 },
12040f099e3SMarkus Pargmann { "intr0_stat", 0x30 },
12140f099e3SMarkus Pargmann { "intr1_stat", 0x34 },
12240f099e3SMarkus Pargmann { "intr0_set", 0x38 },
12340f099e3SMarkus Pargmann { "intr1_set", 0x3c },
12440f099e3SMarkus Pargmann { "txmode", 0x70 },
12540f099e3SMarkus Pargmann { "rxmode", 0x74 },
12640f099e3SMarkus Pargmann { "autoreq", 0xd0 },
12740f099e3SMarkus Pargmann { "srpfixtime", 0xd4 },
12840f099e3SMarkus Pargmann { "tdown", 0xd8 },
12940f099e3SMarkus Pargmann { "phy_utmi", 0xe0 },
13040f099e3SMarkus Pargmann { "mode", 0xe8 },
1319ecb8875SAjay Kumar Gupta };
1329ecb8875SAjay Kumar Gupta
dsps_mod_timer(struct dsps_glue * glue,int wait_ms)133369469a9STony Lindgren static void dsps_mod_timer(struct dsps_glue *glue, int wait_ms)
134369469a9STony Lindgren {
135b82162bcSBin Liu struct musb *musb = platform_get_drvdata(glue->musb);
136369469a9STony Lindgren int wait;
137369469a9STony Lindgren
138369469a9STony Lindgren if (wait_ms < 0)
139369469a9STony Lindgren wait = msecs_to_jiffies(glue->wrp->poll_timeout);
140369469a9STony Lindgren else
141369469a9STony Lindgren wait = msecs_to_jiffies(wait_ms);
142369469a9STony Lindgren
143b82162bcSBin Liu mod_timer(&musb->dev_timer, jiffies + wait);
144369469a9STony Lindgren }
145369469a9STony Lindgren
146369469a9STony Lindgren /*
147369469a9STony Lindgren * If no vbus irq from the PMIC is configured, we need to poll VBUS status.
148369469a9STony Lindgren */
dsps_mod_timer_optional(struct dsps_glue * glue)149369469a9STony Lindgren static void dsps_mod_timer_optional(struct dsps_glue *glue)
150369469a9STony Lindgren {
151369469a9STony Lindgren if (glue->vbus_irq)
152369469a9STony Lindgren return;
153369469a9STony Lindgren
154369469a9STony Lindgren dsps_mod_timer(glue, -1);
155369469a9STony Lindgren }
156369469a9STony Lindgren
15725534828SAlexandre Bailon /* USBSS / USB AM335x */
15825534828SAlexandre Bailon #define USBSS_IRQ_STATUS 0x28
15925534828SAlexandre Bailon #define USBSS_IRQ_ENABLER 0x2c
16025534828SAlexandre Bailon #define USBSS_IRQ_CLEARR 0x30
16125534828SAlexandre Bailon
16225534828SAlexandre Bailon #define USBSS_IRQ_PD_COMP (1 << 2)
16325534828SAlexandre Bailon
16409e03a89SLee Jones /*
1659ecb8875SAjay Kumar Gupta * dsps_musb_enable - enable interrupts
1669ecb8875SAjay Kumar Gupta */
dsps_musb_enable(struct musb * musb)1679ecb8875SAjay Kumar Gupta static void dsps_musb_enable(struct musb *musb)
1689ecb8875SAjay Kumar Gupta {
1699ecb8875SAjay Kumar Gupta struct device *dev = musb->controller;
170e823d948SKefeng Wang struct dsps_glue *glue = dev_get_drvdata(dev->parent);
1719ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp;
1729ecb8875SAjay Kumar Gupta void __iomem *reg_base = musb->ctrl_base;
1739ecb8875SAjay Kumar Gupta u32 epmask, coremask;
1749ecb8875SAjay Kumar Gupta
1759ecb8875SAjay Kumar Gupta /* Workaround: setup IRQs through both register sets. */
1769ecb8875SAjay Kumar Gupta epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
1779ecb8875SAjay Kumar Gupta ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
1789ecb8875SAjay Kumar Gupta coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
1799ecb8875SAjay Kumar Gupta
180086b2882SBin Liu musb_writel(reg_base, wrp->epintr_set, epmask);
181086b2882SBin Liu musb_writel(reg_base, wrp->coreintr_set, coremask);
18254578ee8SBin Liu /*
18354578ee8SBin Liu * start polling for runtime PM active and idle,
18454578ee8SBin Liu * and for ID change in dual-role idle mode.
18554578ee8SBin Liu */
18654578ee8SBin Liu if (musb->xceiv->otg->state == OTG_STATE_B_IDLE)
187369469a9STony Lindgren dsps_mod_timer(glue, -1);
1889ecb8875SAjay Kumar Gupta }
1899ecb8875SAjay Kumar Gupta
19009e03a89SLee Jones /*
1919ecb8875SAjay Kumar Gupta * dsps_musb_disable - disable HDRC and flush interrupts
1929ecb8875SAjay Kumar Gupta */
dsps_musb_disable(struct musb * musb)1939ecb8875SAjay Kumar Gupta static void dsps_musb_disable(struct musb *musb)
1949ecb8875SAjay Kumar Gupta {
1959ecb8875SAjay Kumar Gupta struct device *dev = musb->controller;
196e823d948SKefeng Wang struct dsps_glue *glue = dev_get_drvdata(dev->parent);
1979ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp;
1989ecb8875SAjay Kumar Gupta void __iomem *reg_base = musb->ctrl_base;
1999ecb8875SAjay Kumar Gupta
200086b2882SBin Liu musb_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
201086b2882SBin Liu musb_writel(reg_base, wrp->epintr_clear,
2029ecb8875SAjay Kumar Gupta wrp->txep_bitmap | wrp->rxep_bitmap);
203b82162bcSBin Liu del_timer_sync(&musb->dev_timer);
2049ecb8875SAjay Kumar Gupta }
2059ecb8875SAjay Kumar Gupta
206ea2f35c0STony Lindgren /* Caller must take musb->lock */
dsps_check_status(struct musb * musb,void * unused)207ea2f35c0STony Lindgren static int dsps_check_status(struct musb *musb, void *unused)
2089ecb8875SAjay Kumar Gupta {
2099ecb8875SAjay Kumar Gupta void __iomem *mregs = musb->mregs;
2109ecb8875SAjay Kumar Gupta struct device *dev = musb->controller;
211db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent);
2129ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp;
2139ecb8875SAjay Kumar Gupta u8 devctl;
2140f901c98SSebastian Andrzej Siewior int skip_session = 0;
2159ecb8875SAjay Kumar Gupta
216369469a9STony Lindgren if (glue->vbus_irq)
217b82162bcSBin Liu del_timer(&musb->dev_timer);
218369469a9STony Lindgren
2199ecb8875SAjay Kumar Gupta /*
2209ecb8875SAjay Kumar Gupta * We poll because DSPS IP's won't expose several OTG-critical
2219ecb8875SAjay Kumar Gupta * status change events (from the transceiver) otherwise.
2229ecb8875SAjay Kumar Gupta */
223086b2882SBin Liu devctl = musb_readb(mregs, MUSB_DEVCTL);
2249ecb8875SAjay Kumar Gupta dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
225e47d9254SAntoine Tenart usb_otg_state_string(musb->xceiv->otg->state));
2269ecb8875SAjay Kumar Gupta
227e47d9254SAntoine Tenart switch (musb->xceiv->otg->state) {
2282f3fd2c5STony Lindgren case OTG_STATE_A_WAIT_VRISE:
2296010abf2SBin Liu if (musb->port_mode == MUSB_HOST) {
2306010abf2SBin Liu musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
231369469a9STony Lindgren dsps_mod_timer_optional(glue);
2322f3fd2c5STony Lindgren break;
2336010abf2SBin Liu }
234df561f66SGustavo A. R. Silva fallthrough;
2356010abf2SBin Liu
2369ecb8875SAjay Kumar Gupta case OTG_STATE_A_WAIT_BCON:
237b3addcf0SBin Liu /* keep VBUS on for host-only mode */
2387ad76955SBin Liu if (musb->port_mode == MUSB_HOST) {
239b3addcf0SBin Liu dsps_mod_timer_optional(glue);
240b3addcf0SBin Liu break;
241b3addcf0SBin Liu }
242086b2882SBin Liu musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
2430f901c98SSebastian Andrzej Siewior skip_session = 1;
244df561f66SGustavo A. R. Silva fallthrough;
2459ecb8875SAjay Kumar Gupta
2460f901c98SSebastian Andrzej Siewior case OTG_STATE_A_IDLE:
2470f901c98SSebastian Andrzej Siewior case OTG_STATE_B_IDLE:
248369469a9STony Lindgren if (!glue->vbus_irq) {
2499ecb8875SAjay Kumar Gupta if (devctl & MUSB_DEVCTL_BDEVICE) {
250e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_B_IDLE;
2519ecb8875SAjay Kumar Gupta MUSB_DEV_MODE(musb);
2529ecb8875SAjay Kumar Gupta } else {
253e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_IDLE;
2549ecb8875SAjay Kumar Gupta MUSB_HST_MODE(musb);
2559ecb8875SAjay Kumar Gupta }
25654578ee8SBin Liu
25754578ee8SBin Liu if (musb->port_mode == MUSB_PERIPHERAL)
25854578ee8SBin Liu skip_session = 1;
25954578ee8SBin Liu
2600f901c98SSebastian Andrzej Siewior if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
261369469a9STony Lindgren musb_writeb(mregs, MUSB_DEVCTL,
262369469a9STony Lindgren MUSB_DEVCTL_SESSION);
263369469a9STony Lindgren }
264369469a9STony Lindgren dsps_mod_timer_optional(glue);
2659ecb8875SAjay Kumar Gupta break;
2669ecb8875SAjay Kumar Gupta case OTG_STATE_A_WAIT_VFALL:
267e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
268086b2882SBin Liu musb_writel(musb->ctrl_base, wrp->coreintr_set,
2699ecb8875SAjay Kumar Gupta MUSB_INTR_VBUSERROR << wrp->usb_shift);
2709ecb8875SAjay Kumar Gupta break;
2719ecb8875SAjay Kumar Gupta default:
2729ecb8875SAjay Kumar Gupta break;
2739ecb8875SAjay Kumar Gupta }
27465b3f50eSTony Lindgren
275ea2f35c0STony Lindgren return 0;
276ea2f35c0STony Lindgren }
277ea2f35c0STony Lindgren
otg_timer(struct timer_list * t)27805678497SKees Cook static void otg_timer(struct timer_list *t)
279ea2f35c0STony Lindgren {
280b82162bcSBin Liu struct musb *musb = from_timer(musb, t, dev_timer);
281ea2f35c0STony Lindgren struct device *dev = musb->controller;
282ea2f35c0STony Lindgren unsigned long flags;
283ea2f35c0STony Lindgren int err;
284ea2f35c0STony Lindgren
285ea2f35c0STony Lindgren err = pm_runtime_get(dev);
286ea2f35c0STony Lindgren if ((err != -EINPROGRESS) && err < 0) {
287ea2f35c0STony Lindgren dev_err(dev, "Poll could not pm_runtime_get: %i\n", err);
288ea2f35c0STony Lindgren pm_runtime_put_noidle(dev);
289ea2f35c0STony Lindgren
290ea2f35c0STony Lindgren return;
291ea2f35c0STony Lindgren }
292ea2f35c0STony Lindgren
293ea2f35c0STony Lindgren spin_lock_irqsave(&musb->lock, flags);
294ea2f35c0STony Lindgren err = musb_queue_resume_work(musb, dsps_check_status, NULL);
295ea2f35c0STony Lindgren if (err < 0)
296ea2f35c0STony Lindgren dev_err(dev, "%s resume work: %i\n", __func__, err);
297ea2f35c0STony Lindgren spin_unlock_irqrestore(&musb->lock, flags);
29865b3f50eSTony Lindgren pm_runtime_mark_last_busy(dev);
29965b3f50eSTony Lindgren pm_runtime_put_autosuspend(dev);
3009ecb8875SAjay Kumar Gupta }
3019ecb8875SAjay Kumar Gupta
dsps_musb_clear_ep_rxintr(struct musb * musb,int epnum)3024ab53a69SWei Yongjun static void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum)
303c48400baSBin Liu {
304c48400baSBin Liu u32 epintr;
305c48400baSBin Liu struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
306c48400baSBin Liu const struct dsps_musb_wrapper *wrp = glue->wrp;
307c48400baSBin Liu
308c48400baSBin Liu /* musb->lock might already been held */
309c48400baSBin Liu epintr = (1 << epnum) << wrp->rxep_shift;
310c48400baSBin Liu musb_writel(musb->ctrl_base, wrp->epintr_status, epintr);
311c48400baSBin Liu }
312c48400baSBin Liu
dsps_interrupt(int irq,void * hci)3139ecb8875SAjay Kumar Gupta static irqreturn_t dsps_interrupt(int irq, void *hci)
3149ecb8875SAjay Kumar Gupta {
3159ecb8875SAjay Kumar Gupta struct musb *musb = hci;
3169ecb8875SAjay Kumar Gupta void __iomem *reg_base = musb->ctrl_base;
3179ecb8875SAjay Kumar Gupta struct device *dev = musb->controller;
318db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent);
3199ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp;
3209ecb8875SAjay Kumar Gupta unsigned long flags;
3219ecb8875SAjay Kumar Gupta irqreturn_t ret = IRQ_NONE;
3229ecb8875SAjay Kumar Gupta u32 epintr, usbintr;
3239ecb8875SAjay Kumar Gupta
3249ecb8875SAjay Kumar Gupta spin_lock_irqsave(&musb->lock, flags);
3259ecb8875SAjay Kumar Gupta
3269ecb8875SAjay Kumar Gupta /* Get endpoint interrupts */
327086b2882SBin Liu epintr = musb_readl(reg_base, wrp->epintr_status);
3289ecb8875SAjay Kumar Gupta musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
3299ecb8875SAjay Kumar Gupta musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
3309ecb8875SAjay Kumar Gupta
3319ecb8875SAjay Kumar Gupta if (epintr)
332086b2882SBin Liu musb_writel(reg_base, wrp->epintr_status, epintr);
3339ecb8875SAjay Kumar Gupta
3349ecb8875SAjay Kumar Gupta /* Get usb core interrupts */
335086b2882SBin Liu usbintr = musb_readl(reg_base, wrp->coreintr_status);
3369ecb8875SAjay Kumar Gupta if (!usbintr && !epintr)
3379be73baeSSebastian Andrzej Siewior goto out;
3389ecb8875SAjay Kumar Gupta
3399ecb8875SAjay Kumar Gupta musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
3409ecb8875SAjay Kumar Gupta if (usbintr)
341086b2882SBin Liu musb_writel(reg_base, wrp->coreintr_status, usbintr);
3429ecb8875SAjay Kumar Gupta
3439ecb8875SAjay Kumar Gupta dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
3449ecb8875SAjay Kumar Gupta usbintr, epintr);
3451d57de30SDaniel Mack
3469ecb8875SAjay Kumar Gupta if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
347086b2882SBin Liu int drvvbus = musb_readl(reg_base, wrp->status);
3489ecb8875SAjay Kumar Gupta void __iomem *mregs = musb->mregs;
349086b2882SBin Liu u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
3509ecb8875SAjay Kumar Gupta int err;
3519ecb8875SAjay Kumar Gupta
352032ec49fSFelipe Balbi err = musb->int_usb & MUSB_INTR_VBUSERROR;
3539ecb8875SAjay Kumar Gupta if (err) {
3549ecb8875SAjay Kumar Gupta /*
3559ecb8875SAjay Kumar Gupta * The Mentor core doesn't debounce VBUS as needed
3569ecb8875SAjay Kumar Gupta * to cope with device connect current spikes. This
3579ecb8875SAjay Kumar Gupta * means it's not uncommon for bus-powered devices
3589ecb8875SAjay Kumar Gupta * to get VBUS errors during enumeration.
3599ecb8875SAjay Kumar Gupta *
3609ecb8875SAjay Kumar Gupta * This is a workaround, but newer RTL from Mentor
3619ecb8875SAjay Kumar Gupta * seems to allow a better one: "re"-starting sessions
3629ecb8875SAjay Kumar Gupta * without waiting for VBUS to stop registering in
3639ecb8875SAjay Kumar Gupta * devctl.
3649ecb8875SAjay Kumar Gupta */
3659ecb8875SAjay Kumar Gupta musb->int_usb &= ~MUSB_INTR_VBUSERROR;
366e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
367369469a9STony Lindgren dsps_mod_timer_optional(glue);
3689ecb8875SAjay Kumar Gupta WARNING("VBUS error workaround (delay coming)\n");
369032ec49fSFelipe Balbi } else if (drvvbus) {
3709ecb8875SAjay Kumar Gupta MUSB_HST_MODE(musb);
371e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
372369469a9STony Lindgren dsps_mod_timer_optional(glue);
3739ecb8875SAjay Kumar Gupta } else {
3749ecb8875SAjay Kumar Gupta musb->is_active = 0;
3759ecb8875SAjay Kumar Gupta MUSB_DEV_MODE(musb);
376e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_B_IDLE;
3779ecb8875SAjay Kumar Gupta }
3789ecb8875SAjay Kumar Gupta
3799ecb8875SAjay Kumar Gupta /* NOTE: this must complete power-on within 100 ms. */
3809ecb8875SAjay Kumar Gupta dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
3819ecb8875SAjay Kumar Gupta drvvbus ? "on" : "off",
382e47d9254SAntoine Tenart usb_otg_state_string(musb->xceiv->otg->state),
3839ecb8875SAjay Kumar Gupta err ? " ERROR" : "",
3849ecb8875SAjay Kumar Gupta devctl);
3859ecb8875SAjay Kumar Gupta ret = IRQ_HANDLED;
3869ecb8875SAjay Kumar Gupta }
3879ecb8875SAjay Kumar Gupta
3889ecb8875SAjay Kumar Gupta if (musb->int_tx || musb->int_rx || musb->int_usb)
3899ecb8875SAjay Kumar Gupta ret |= musb_interrupt(musb);
3909ecb8875SAjay Kumar Gupta
3912f3fd2c5STony Lindgren /* Poll for ID change and connect */
3922f3fd2c5STony Lindgren switch (musb->xceiv->otg->state) {
3932f3fd2c5STony Lindgren case OTG_STATE_B_IDLE:
3942f3fd2c5STony Lindgren case OTG_STATE_A_WAIT_BCON:
395369469a9STony Lindgren dsps_mod_timer_optional(glue);
3962f3fd2c5STony Lindgren break;
3972f3fd2c5STony Lindgren default:
3982f3fd2c5STony Lindgren break;
3992f3fd2c5STony Lindgren }
4002f3fd2c5STony Lindgren
4019be73baeSSebastian Andrzej Siewior out:
4029ecb8875SAjay Kumar Gupta spin_unlock_irqrestore(&musb->lock, flags);
4039ecb8875SAjay Kumar Gupta
4049ecb8875SAjay Kumar Gupta return ret;
4059ecb8875SAjay Kumar Gupta }
4069ecb8875SAjay Kumar Gupta
dsps_musb_dbg_init(struct musb * musb,struct dsps_glue * glue)40740f099e3SMarkus Pargmann static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue)
40840f099e3SMarkus Pargmann {
40940f099e3SMarkus Pargmann struct dentry *root;
41040f099e3SMarkus Pargmann char buf[128];
41140f099e3SMarkus Pargmann
41240f099e3SMarkus Pargmann sprintf(buf, "%s.dsps", dev_name(musb->controller));
413b3c69ec8SChunfeng Yun root = debugfs_create_dir(buf, usb_debug_root);
41440f099e3SMarkus Pargmann glue->dbgfs_root = root;
41540f099e3SMarkus Pargmann
41640f099e3SMarkus Pargmann glue->regset.regs = dsps_musb_regs;
41740f099e3SMarkus Pargmann glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs);
41840f099e3SMarkus Pargmann glue->regset.base = musb->ctrl_base;
41940f099e3SMarkus Pargmann
4208a1ef171SGreg Kroah-Hartman debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset);
42140f099e3SMarkus Pargmann return 0;
42240f099e3SMarkus Pargmann }
42340f099e3SMarkus Pargmann
dsps_musb_init(struct musb * musb)4249ecb8875SAjay Kumar Gupta static int dsps_musb_init(struct musb *musb)
4259ecb8875SAjay Kumar Gupta {
4269ecb8875SAjay Kumar Gupta struct device *dev = musb->controller;
427db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent);
42897238b35SSebastian Andrzej Siewior struct platform_device *parent = to_platform_device(dev->parent);
4299ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp;
43097238b35SSebastian Andrzej Siewior void __iomem *reg_base;
431ffa13d2dSGeert Uytterhoeven struct resource *r;
4329ecb8875SAjay Kumar Gupta u32 rev, val;
43340f099e3SMarkus Pargmann int ret;
4349ecb8875SAjay Kumar Gupta
435ffa13d2dSGeert Uytterhoeven r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
436ffa13d2dSGeert Uytterhoeven reg_base = devm_ioremap_resource(dev, r);
43751ef74f6SJulia Lawall if (IS_ERR(reg_base))
43851ef74f6SJulia Lawall return PTR_ERR(reg_base);
43997238b35SSebastian Andrzej Siewior musb->ctrl_base = reg_base;
4409ecb8875SAjay Kumar Gupta
441d7554226SAfzal Mohammed /* NOP driver needs change if supporting dual instance */
442983f3cabSFelipe Balbi musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "phys", 0);
44397238b35SSebastian Andrzej Siewior if (IS_ERR(musb->xceiv))
44497238b35SSebastian Andrzej Siewior return PTR_ERR(musb->xceiv);
4459ecb8875SAjay Kumar Gupta
446bb90600dSTony Lindgren musb->phy = devm_phy_get(dev->parent, "usb2-phy");
447bb90600dSTony Lindgren
4489ecb8875SAjay Kumar Gupta /* Returns zero if e.g. not clocked */
449086b2882SBin Liu rev = musb_readl(reg_base, wrp->revision);
45097238b35SSebastian Andrzej Siewior if (!rev)
45197238b35SSebastian Andrzej Siewior return -ENODEV;
4529ecb8875SAjay Kumar Gupta
453bb90600dSTony Lindgren if (IS_ERR(musb->phy)) {
454bb90600dSTony Lindgren musb->phy = NULL;
455bb90600dSTony Lindgren } else {
456bb90600dSTony Lindgren ret = phy_init(musb->phy);
457bb90600dSTony Lindgren if (ret < 0)
458bb90600dSTony Lindgren return ret;
459bb90600dSTony Lindgren ret = phy_power_on(musb->phy);
460bb90600dSTony Lindgren if (ret) {
461bb90600dSTony Lindgren phy_exit(musb->phy);
462bb90600dSTony Lindgren return ret;
463bb90600dSTony Lindgren }
464bb90600dSTony Lindgren }
465bb90600dSTony Lindgren
466b82162bcSBin Liu timer_setup(&musb->dev_timer, otg_timer, 0);
4679ecb8875SAjay Kumar Gupta
4689ecb8875SAjay Kumar Gupta /* Reset the musb */
469086b2882SBin Liu musb_writel(reg_base, wrp->control, (1 << wrp->reset));
4709ecb8875SAjay Kumar Gupta
4719ecb8875SAjay Kumar Gupta musb->isr = dsps_interrupt;
4729ecb8875SAjay Kumar Gupta
4739ecb8875SAjay Kumar Gupta /* reset the otgdisable bit, needed for host mode to work */
474086b2882SBin Liu val = musb_readl(reg_base, wrp->phy_utmi);
4759ecb8875SAjay Kumar Gupta val &= ~(1 << wrp->otg_disable);
476086b2882SBin Liu musb_writel(musb->ctrl_base, wrp->phy_utmi, val);
4779ecb8875SAjay Kumar Gupta
478371254ceSGeorge Cherian /*
479371254ceSGeorge Cherian * Check whether the dsps version has babble control enabled.
480371254ceSGeorge Cherian * In latest silicon revision the babble control logic is enabled.
481371254ceSGeorge Cherian * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
482371254ceSGeorge Cherian * logic enabled.
483371254ceSGeorge Cherian */
484086b2882SBin Liu val = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
485f860f0b1SFelipe Balbi if (val & MUSB_BABBLE_RCV_DISABLE) {
486371254ceSGeorge Cherian glue->sw_babble_enabled = true;
487371254ceSGeorge Cherian val |= MUSB_BABBLE_SW_SESSION_CTRL;
488086b2882SBin Liu musb_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
489371254ceSGeorge Cherian }
490371254ceSGeorge Cherian
491369469a9STony Lindgren dsps_mod_timer(glue, -1);
4922f3fd2c5STony Lindgren
493e94a7369SSaurabh Karajgaonkar return dsps_musb_dbg_init(musb, glue);
4949ecb8875SAjay Kumar Gupta }
4959ecb8875SAjay Kumar Gupta
dsps_musb_exit(struct musb * musb)4969ecb8875SAjay Kumar Gupta static int dsps_musb_exit(struct musb *musb)
4979ecb8875SAjay Kumar Gupta {
4989ecb8875SAjay Kumar Gupta struct device *dev = musb->controller;
499db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent);
5009ecb8875SAjay Kumar Gupta
501b82162bcSBin Liu del_timer_sync(&musb->dev_timer);
502bb90600dSTony Lindgren phy_power_off(musb->phy);
503bb90600dSTony Lindgren phy_exit(musb->phy);
5040fca91b8SDaniel Mack debugfs_remove_recursive(glue->dbgfs_root);
5050fca91b8SDaniel Mack
5069ecb8875SAjay Kumar Gupta return 0;
5079ecb8875SAjay Kumar Gupta }
5089ecb8875SAjay Kumar Gupta
dsps_musb_set_mode(struct musb * musb,u8 mode)509943c1397SFelipe Balbi static int dsps_musb_set_mode(struct musb *musb, u8 mode)
510943c1397SFelipe Balbi {
511943c1397SFelipe Balbi struct device *dev = musb->controller;
512943c1397SFelipe Balbi struct dsps_glue *glue = dev_get_drvdata(dev->parent);
513943c1397SFelipe Balbi const struct dsps_musb_wrapper *wrp = glue->wrp;
514943c1397SFelipe Balbi void __iomem *ctrl_base = musb->ctrl_base;
515943c1397SFelipe Balbi u32 reg;
516943c1397SFelipe Balbi
517086b2882SBin Liu reg = musb_readl(ctrl_base, wrp->mode);
518943c1397SFelipe Balbi
519943c1397SFelipe Balbi switch (mode) {
520943c1397SFelipe Balbi case MUSB_HOST:
521943c1397SFelipe Balbi reg &= ~(1 << wrp->iddig);
522943c1397SFelipe Balbi
523943c1397SFelipe Balbi /*
524943c1397SFelipe Balbi * if we're setting mode to host-only or device-only, we're
525943c1397SFelipe Balbi * going to ignore whatever the PHY sends us and just force
526943c1397SFelipe Balbi * ID pin status by SW
527943c1397SFelipe Balbi */
528943c1397SFelipe Balbi reg |= (1 << wrp->iddig_mux);
529943c1397SFelipe Balbi
530086b2882SBin Liu musb_writel(ctrl_base, wrp->mode, reg);
531086b2882SBin Liu musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
532943c1397SFelipe Balbi break;
533943c1397SFelipe Balbi case MUSB_PERIPHERAL:
534943c1397SFelipe Balbi reg |= (1 << wrp->iddig);
535943c1397SFelipe Balbi
536943c1397SFelipe Balbi /*
537943c1397SFelipe Balbi * if we're setting mode to host-only or device-only, we're
538943c1397SFelipe Balbi * going to ignore whatever the PHY sends us and just force
539943c1397SFelipe Balbi * ID pin status by SW
540943c1397SFelipe Balbi */
541943c1397SFelipe Balbi reg |= (1 << wrp->iddig_mux);
542943c1397SFelipe Balbi
543086b2882SBin Liu musb_writel(ctrl_base, wrp->mode, reg);
544943c1397SFelipe Balbi break;
545943c1397SFelipe Balbi case MUSB_OTG:
546086b2882SBin Liu musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
547943c1397SFelipe Balbi break;
548943c1397SFelipe Balbi default:
549943c1397SFelipe Balbi dev_err(glue->dev, "unsupported mode %d\n", mode);
550943c1397SFelipe Balbi return -EINVAL;
551943c1397SFelipe Balbi }
552943c1397SFelipe Balbi
553943c1397SFelipe Balbi return 0;
554943c1397SFelipe Balbi }
555943c1397SFelipe Balbi
dsps_sw_babble_control(struct musb * musb)5563709ffcaSFelipe Balbi static bool dsps_sw_babble_control(struct musb *musb)
557371254ceSGeorge Cherian {
558371254ceSGeorge Cherian u8 babble_ctl;
559371254ceSGeorge Cherian bool session_restart = false;
560371254ceSGeorge Cherian
561086b2882SBin Liu babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
562371254ceSGeorge Cherian dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
563371254ceSGeorge Cherian babble_ctl);
564371254ceSGeorge Cherian /*
565371254ceSGeorge Cherian * check line monitor flag to check whether babble is
566371254ceSGeorge Cherian * due to noise
567371254ceSGeorge Cherian */
568371254ceSGeorge Cherian dev_dbg(musb->controller, "STUCK_J is %s\n",
569371254ceSGeorge Cherian babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
570371254ceSGeorge Cherian
571371254ceSGeorge Cherian if (babble_ctl & MUSB_BABBLE_STUCK_J) {
572371254ceSGeorge Cherian int timeout = 10;
573371254ceSGeorge Cherian
574371254ceSGeorge Cherian /*
575371254ceSGeorge Cherian * babble is due to noise, then set transmit idle (d7 bit)
576371254ceSGeorge Cherian * to resume normal operation
577371254ceSGeorge Cherian */
578086b2882SBin Liu babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
579371254ceSGeorge Cherian babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
580086b2882SBin Liu musb_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
581371254ceSGeorge Cherian
582371254ceSGeorge Cherian /* wait till line monitor flag cleared */
583371254ceSGeorge Cherian dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
584371254ceSGeorge Cherian do {
585086b2882SBin Liu babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
586371254ceSGeorge Cherian udelay(1);
587371254ceSGeorge Cherian } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
588371254ceSGeorge Cherian
589371254ceSGeorge Cherian /* check whether stuck_at_j bit cleared */
590371254ceSGeorge Cherian if (babble_ctl & MUSB_BABBLE_STUCK_J) {
591371254ceSGeorge Cherian /*
592371254ceSGeorge Cherian * real babble condition has occurred
593371254ceSGeorge Cherian * restart the controller to start the
594371254ceSGeorge Cherian * session again
595371254ceSGeorge Cherian */
596371254ceSGeorge Cherian dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
597371254ceSGeorge Cherian babble_ctl);
598371254ceSGeorge Cherian session_restart = true;
599371254ceSGeorge Cherian }
600371254ceSGeorge Cherian } else {
601371254ceSGeorge Cherian session_restart = true;
602371254ceSGeorge Cherian }
603371254ceSGeorge Cherian
604371254ceSGeorge Cherian return session_restart;
605371254ceSGeorge Cherian }
606371254ceSGeorge Cherian
dsps_musb_recover(struct musb * musb)607b28a6432SFelipe Balbi static int dsps_musb_recover(struct musb *musb)
6081d57de30SDaniel Mack {
6091d57de30SDaniel Mack struct device *dev = musb->controller;
6101d57de30SDaniel Mack struct dsps_glue *glue = dev_get_drvdata(dev->parent);
611011d0dd5SFelipe Balbi int session_restart = 0;
6121d57de30SDaniel Mack
613371254ceSGeorge Cherian if (glue->sw_babble_enabled)
6143709ffcaSFelipe Balbi session_restart = dsps_sw_babble_control(musb);
615011d0dd5SFelipe Balbi else
616371254ceSGeorge Cherian session_restart = 1;
61756700178SGeorge Cherian
618d0cddae7SFelipe Balbi return session_restart ? 0 : -EPIPE;
6191d57de30SDaniel Mack }
6201d57de30SDaniel Mack
6213e457371STony Lindgren /* Similar to am35x, dm81xx support only 32-bit read operation */
dsps_read_fifo32(struct musb_hw_ep * hw_ep,u16 len,u8 * dst)6223e457371STony Lindgren static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
6233e457371STony Lindgren {
6243e457371STony Lindgren void __iomem *fifo = hw_ep->fifo;
6253e457371STony Lindgren
6263e457371STony Lindgren if (len >= 4) {
627d30323f8STony Lindgren ioread32_rep(fifo, dst, len >> 2);
6283e457371STony Lindgren dst += len & ~0x03;
6293e457371STony Lindgren len &= 0x03;
6303e457371STony Lindgren }
6313e457371STony Lindgren
6323e457371STony Lindgren /* Read any remaining 1 to 3 bytes */
6333e457371STony Lindgren if (len > 0) {
6343e457371STony Lindgren u32 val = musb_readl(fifo, 0);
6353e457371STony Lindgren memcpy(dst, &val, len);
6363e457371STony Lindgren }
6373e457371STony Lindgren }
6383e457371STony Lindgren
63925534828SAlexandre Bailon #ifdef CONFIG_USB_TI_CPPI41_DMA
dsps_dma_controller_callback(struct dma_controller * c)64025534828SAlexandre Bailon static void dsps_dma_controller_callback(struct dma_controller *c)
64125534828SAlexandre Bailon {
64225534828SAlexandre Bailon struct musb *musb = c->musb;
64325534828SAlexandre Bailon struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
64425534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base;
64525534828SAlexandre Bailon u32 status;
64625534828SAlexandre Bailon
64725534828SAlexandre Bailon status = musb_readl(usbss_base, USBSS_IRQ_STATUS);
64825534828SAlexandre Bailon if (status & USBSS_IRQ_PD_COMP)
64925534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP);
65025534828SAlexandre Bailon }
65125534828SAlexandre Bailon
65225534828SAlexandre Bailon static struct dma_controller *
dsps_dma_controller_create(struct musb * musb,void __iomem * base)65325534828SAlexandre Bailon dsps_dma_controller_create(struct musb *musb, void __iomem *base)
65425534828SAlexandre Bailon {
65525534828SAlexandre Bailon struct dma_controller *controller;
65625534828SAlexandre Bailon struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
65725534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base;
65825534828SAlexandre Bailon
65925534828SAlexandre Bailon controller = cppi41_dma_controller_create(musb, base);
66025534828SAlexandre Bailon if (IS_ERR_OR_NULL(controller))
66125534828SAlexandre Bailon return controller;
66225534828SAlexandre Bailon
66325534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
66425534828SAlexandre Bailon controller->dma_callback = dsps_dma_controller_callback;
66525534828SAlexandre Bailon
66625534828SAlexandre Bailon return controller;
66725534828SAlexandre Bailon }
66825534828SAlexandre Bailon
66925534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
dsps_dma_controller_suspend(struct dsps_glue * glue)67025534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue)
67125534828SAlexandre Bailon {
67225534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base;
67325534828SAlexandre Bailon
67425534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
67525534828SAlexandre Bailon }
67625534828SAlexandre Bailon
dsps_dma_controller_resume(struct dsps_glue * glue)67725534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue)
67825534828SAlexandre Bailon {
67925534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base;
68025534828SAlexandre Bailon
68125534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
68225534828SAlexandre Bailon }
68325534828SAlexandre Bailon #endif
68425534828SAlexandre Bailon #else /* CONFIG_USB_TI_CPPI41_DMA */
68525534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
dsps_dma_controller_suspend(struct dsps_glue * glue)68625534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue) {}
dsps_dma_controller_resume(struct dsps_glue * glue)68725534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue) {}
68825534828SAlexandre Bailon #endif
68925534828SAlexandre Bailon #endif /* CONFIG_USB_TI_CPPI41_DMA */
69025534828SAlexandre Bailon
6919ecb8875SAjay Kumar Gupta static struct musb_platform_ops dsps_ops = {
692f8e9f34fSTony Lindgren .quirks = MUSB_DMA_CPPI41 | MUSB_INDEXED_EP,
6939ecb8875SAjay Kumar Gupta .init = dsps_musb_init,
6949ecb8875SAjay Kumar Gupta .exit = dsps_musb_exit,
6959ecb8875SAjay Kumar Gupta
6967f6283edSTony Lindgren #ifdef CONFIG_USB_TI_CPPI41_DMA
69725534828SAlexandre Bailon .dma_init = dsps_dma_controller_create,
698783f3b4eSBin Liu .dma_exit = cppi41_dma_controller_destroy,
6997f6283edSTony Lindgren #endif
7009ecb8875SAjay Kumar Gupta .enable = dsps_musb_enable,
7019ecb8875SAjay Kumar Gupta .disable = dsps_musb_disable,
7029ecb8875SAjay Kumar Gupta
703943c1397SFelipe Balbi .set_mode = dsps_musb_set_mode,
704b28a6432SFelipe Balbi .recover = dsps_musb_recover,
705c48400baSBin Liu .clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
7069ecb8875SAjay Kumar Gupta };
7079ecb8875SAjay Kumar Gupta
7089ecb8875SAjay Kumar Gupta static u64 musb_dmamask = DMA_BIT_MASK(32);
7099ecb8875SAjay Kumar Gupta
get_int_prop(struct device_node * dn,const char * s)71097238b35SSebastian Andrzej Siewior static int get_int_prop(struct device_node *dn, const char *s)
7119ecb8875SAjay Kumar Gupta {
71297238b35SSebastian Andrzej Siewior int ret;
71397238b35SSebastian Andrzej Siewior u32 val;
71497238b35SSebastian Andrzej Siewior
71597238b35SSebastian Andrzej Siewior ret = of_property_read_u32(dn, s, &val);
71697238b35SSebastian Andrzej Siewior if (ret)
71797238b35SSebastian Andrzej Siewior return 0;
71897238b35SSebastian Andrzej Siewior return val;
71997238b35SSebastian Andrzej Siewior }
72097238b35SSebastian Andrzej Siewior
dsps_create_musb_pdev(struct dsps_glue * glue,struct platform_device * parent)72197238b35SSebastian Andrzej Siewior static int dsps_create_musb_pdev(struct dsps_glue *glue,
72297238b35SSebastian Andrzej Siewior struct platform_device *parent)
72397238b35SSebastian Andrzej Siewior {
72497238b35SSebastian Andrzej Siewior struct musb_hdrc_platform_data pdata;
72597238b35SSebastian Andrzej Siewior struct resource resources[2];
726c031a7d4SSebastian Andrzej Siewior struct resource *res;
72797238b35SSebastian Andrzej Siewior struct device *dev = &parent->dev;
72865145677SAjay Kumar Gupta struct musb_hdrc_config *config;
7299ecb8875SAjay Kumar Gupta struct platform_device *musb;
73097238b35SSebastian Andrzej Siewior struct device_node *dn = parent->dev.of_node;
731606bf4d5STony Lindgren int ret, val;
7329ecb8875SAjay Kumar Gupta
73397238b35SSebastian Andrzej Siewior memset(resources, 0, sizeof(resources));
734c031a7d4SSebastian Andrzej Siewior res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc");
735c031a7d4SSebastian Andrzej Siewior if (!res) {
73697238b35SSebastian Andrzej Siewior dev_err(dev, "failed to get memory.\n");
737c031a7d4SSebastian Andrzej Siewior return -EINVAL;
7389ecb8875SAjay Kumar Gupta }
739c031a7d4SSebastian Andrzej Siewior resources[0] = *res;
74097238b35SSebastian Andrzej Siewior
741ce1d37cbSLad Prabhakar ret = platform_get_irq_byname(parent, "mc");
742ce1d37cbSLad Prabhakar if (ret < 0)
743ce1d37cbSLad Prabhakar return ret;
744ce1d37cbSLad Prabhakar
745ce1d37cbSLad Prabhakar resources[1].start = ret;
746ce1d37cbSLad Prabhakar resources[1].end = ret;
747ce1d37cbSLad Prabhakar resources[1].flags = IORESOURCE_IRQ | irq_get_trigger_type(ret);
748ce1d37cbSLad Prabhakar resources[1].name = "mc";
7499ecb8875SAjay Kumar Gupta
75065b3d52dSB, Ravi /* allocate the child platform device */
75145abfa68SBin Liu musb = platform_device_alloc("musb-hdrc",
75245abfa68SBin Liu (resources[0].start & 0xFFF) == 0x400 ? 0 : 1);
75365b3d52dSB, Ravi if (!musb) {
75465b3d52dSB, Ravi dev_err(dev, "failed to allocate musb device\n");
75597238b35SSebastian Andrzej Siewior return -ENOMEM;
75665b3d52dSB, Ravi }
7579ecb8875SAjay Kumar Gupta
7589ecb8875SAjay Kumar Gupta musb->dev.parent = dev;
7599ecb8875SAjay Kumar Gupta musb->dev.dma_mask = &musb_dmamask;
7609ecb8875SAjay Kumar Gupta musb->dev.coherent_dma_mask = musb_dmamask;
76149484abdSJohan Hovold device_set_of_node_from_dev(&musb->dev, &parent->dev);
7629ecb8875SAjay Kumar Gupta
76397238b35SSebastian Andrzej Siewior glue->musb = musb;
7649ecb8875SAjay Kumar Gupta
76597238b35SSebastian Andrzej Siewior ret = platform_device_add_resources(musb, resources,
76697238b35SSebastian Andrzej Siewior ARRAY_SIZE(resources));
7679ecb8875SAjay Kumar Gupta if (ret) {
7689ecb8875SAjay Kumar Gupta dev_err(dev, "failed to add resources\n");
76997238b35SSebastian Andrzej Siewior goto err;
7709ecb8875SAjay Kumar Gupta }
7719ecb8875SAjay Kumar Gupta
77297238b35SSebastian Andrzej Siewior config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL);
77365145677SAjay Kumar Gupta if (!config) {
774b25e5f1cSWei Yongjun ret = -ENOMEM;
77597238b35SSebastian Andrzej Siewior goto err;
77665145677SAjay Kumar Gupta }
77797238b35SSebastian Andrzej Siewior pdata.config = config;
77897238b35SSebastian Andrzej Siewior pdata.platform_ops = &dsps_ops;
77965145677SAjay Kumar Gupta
780c031a7d4SSebastian Andrzej Siewior config->num_eps = get_int_prop(dn, "mentor,num-eps");
781c031a7d4SSebastian Andrzej Siewior config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
782869c5978SDaniel Mack config->host_port_deassert_reset_at_resume = 1;
78355479956SBin Liu pdata.mode = musb_get_mode(dev);
784c031a7d4SSebastian Andrzej Siewior /* DT keeps this entry in mA, musb expects it as per USB spec */
785c031a7d4SSebastian Andrzej Siewior pdata.power = get_int_prop(dn, "mentor,power") / 2;
786606bf4d5STony Lindgren
787606bf4d5STony Lindgren ret = of_property_read_u32(dn, "mentor,multipoint", &val);
788606bf4d5STony Lindgren if (!ret && val)
789606bf4d5STony Lindgren config->multipoint = true;
79065145677SAjay Kumar Gupta
79163863b98SHeikki Krogerus config->maximum_speed = usb_get_maximum_speed(&parent->dev);
79241932b9bSBin Liu switch (config->maximum_speed) {
79341932b9bSBin Liu case USB_SPEED_LOW:
79441932b9bSBin Liu case USB_SPEED_FULL:
79541932b9bSBin Liu break;
79641932b9bSBin Liu case USB_SPEED_SUPER:
79741932b9bSBin Liu dev_warn(dev, "ignore incorrect maximum_speed "
79841932b9bSBin Liu "(super-speed) setting in dts");
799df561f66SGustavo A. R. Silva fallthrough;
80041932b9bSBin Liu default:
80141932b9bSBin Liu config->maximum_speed = USB_SPEED_HIGH;
80241932b9bSBin Liu }
80341932b9bSBin Liu
80497238b35SSebastian Andrzej Siewior ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
8059ecb8875SAjay Kumar Gupta if (ret) {
8069ecb8875SAjay Kumar Gupta dev_err(dev, "failed to add platform_data\n");
80797238b35SSebastian Andrzej Siewior goto err;
8089ecb8875SAjay Kumar Gupta }
8099ecb8875SAjay Kumar Gupta
8109ecb8875SAjay Kumar Gupta ret = platform_device_add(musb);
8119ecb8875SAjay Kumar Gupta if (ret) {
8129ecb8875SAjay Kumar Gupta dev_err(dev, "failed to register musb device\n");
81397238b35SSebastian Andrzej Siewior goto err;
8149ecb8875SAjay Kumar Gupta }
8159ecb8875SAjay Kumar Gupta return 0;
8169ecb8875SAjay Kumar Gupta
81797238b35SSebastian Andrzej Siewior err:
8189ecb8875SAjay Kumar Gupta platform_device_put(musb);
8199ecb8875SAjay Kumar Gupta return ret;
8209ecb8875SAjay Kumar Gupta }
8219ecb8875SAjay Kumar Gupta
dsps_vbus_threaded_irq(int irq,void * priv)822369469a9STony Lindgren static irqreturn_t dsps_vbus_threaded_irq(int irq, void *priv)
823369469a9STony Lindgren {
824369469a9STony Lindgren struct dsps_glue *glue = priv;
825369469a9STony Lindgren struct musb *musb = platform_get_drvdata(glue->musb);
826369469a9STony Lindgren
827369469a9STony Lindgren if (!musb)
828369469a9STony Lindgren return IRQ_NONE;
829369469a9STony Lindgren
830369469a9STony Lindgren dev_dbg(glue->dev, "VBUS interrupt\n");
831369469a9STony Lindgren dsps_mod_timer(glue, 0);
832369469a9STony Lindgren
833369469a9STony Lindgren return IRQ_HANDLED;
834369469a9STony Lindgren }
835369469a9STony Lindgren
dsps_setup_optional_vbus_irq(struct platform_device * pdev,struct dsps_glue * glue)836369469a9STony Lindgren static int dsps_setup_optional_vbus_irq(struct platform_device *pdev,
837369469a9STony Lindgren struct dsps_glue *glue)
838369469a9STony Lindgren {
839369469a9STony Lindgren int error;
840369469a9STony Lindgren
841369469a9STony Lindgren glue->vbus_irq = platform_get_irq_byname(pdev, "vbus");
842369469a9STony Lindgren if (glue->vbus_irq == -EPROBE_DEFER)
843369469a9STony Lindgren return -EPROBE_DEFER;
844369469a9STony Lindgren
845369469a9STony Lindgren if (glue->vbus_irq <= 0) {
846369469a9STony Lindgren glue->vbus_irq = 0;
847369469a9STony Lindgren return 0;
848369469a9STony Lindgren }
849369469a9STony Lindgren
850369469a9STony Lindgren error = devm_request_threaded_irq(glue->dev, glue->vbus_irq,
851369469a9STony Lindgren NULL, dsps_vbus_threaded_irq,
852*2f07592cSGrant B Adams IRQF_SHARED,
853369469a9STony Lindgren "vbus", glue);
854369469a9STony Lindgren if (error) {
855369469a9STony Lindgren glue->vbus_irq = 0;
856369469a9STony Lindgren return error;
857369469a9STony Lindgren }
858369469a9STony Lindgren dev_dbg(glue->dev, "VBUS irq %i configured\n", glue->vbus_irq);
859369469a9STony Lindgren
860369469a9STony Lindgren return 0;
861369469a9STony Lindgren }
862369469a9STony Lindgren
dsps_probe(struct platform_device * pdev)86341ac7b3aSBill Pemberton static int dsps_probe(struct platform_device *pdev)
8649ecb8875SAjay Kumar Gupta {
86565145677SAjay Kumar Gupta const struct of_device_id *match;
86665145677SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp;
8679ecb8875SAjay Kumar Gupta struct dsps_glue *glue;
86897238b35SSebastian Andrzej Siewior int ret;
8699ecb8875SAjay Kumar Gupta
8704fc4b274SSebastian Andrzej Siewior if (!strcmp(pdev->name, "musb-hdrc"))
8714fc4b274SSebastian Andrzej Siewior return -ENODEV;
8724fc4b274SSebastian Andrzej Siewior
873cc506036SFelipe Balbi match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
87465145677SAjay Kumar Gupta if (!match) {
87565145677SAjay Kumar Gupta dev_err(&pdev->dev, "fail to get matching of_match struct\n");
87697238b35SSebastian Andrzej Siewior return -EINVAL;
87765145677SAjay Kumar Gupta }
87865145677SAjay Kumar Gupta wrp = match->data;
8799ecb8875SAjay Kumar Gupta
8803e457371STony Lindgren if (of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816"))
8813e457371STony Lindgren dsps_ops.read_fifo = dsps_read_fifo32;
8823e457371STony Lindgren
8839ecb8875SAjay Kumar Gupta /* allocate glue */
884de9db572SMarkus Pargmann glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
8850816ea2fSPeter Chen if (!glue)
88697238b35SSebastian Andrzej Siewior return -ENOMEM;
8879ecb8875SAjay Kumar Gupta
8889ecb8875SAjay Kumar Gupta glue->dev = &pdev->dev;
88997238b35SSebastian Andrzej Siewior glue->wrp = wrp;
89025534828SAlexandre Bailon glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0);
89125534828SAlexandre Bailon if (!glue->usbss_base)
89225534828SAlexandre Bailon return -ENXIO;
8939ecb8875SAjay Kumar Gupta
8949ecb8875SAjay Kumar Gupta platform_set_drvdata(pdev, glue);
8959ecb8875SAjay Kumar Gupta pm_runtime_enable(&pdev->dev);
89697238b35SSebastian Andrzej Siewior ret = dsps_create_musb_pdev(glue, pdev);
89797238b35SSebastian Andrzej Siewior if (ret)
89824752917STony Lindgren goto err;
89965b3f50eSTony Lindgren
9007c75bde3SNadezda Lutovinova if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
9017c75bde3SNadezda Lutovinova ret = dsps_setup_optional_vbus_irq(pdev, glue);
9027c75bde3SNadezda Lutovinova if (ret)
903c2115b2bSMiquel Raynal goto unregister_pdev;
9047c75bde3SNadezda Lutovinova }
9057c75bde3SNadezda Lutovinova
9069ecb8875SAjay Kumar Gupta return 0;
9079ecb8875SAjay Kumar Gupta
908c2115b2bSMiquel Raynal unregister_pdev:
909c2115b2bSMiquel Raynal platform_device_unregister(glue->musb);
91024752917STony Lindgren err:
9110e38c4edSAjay Kumar Gupta pm_runtime_disable(&pdev->dev);
9126b7ad496SBin Liu iounmap(glue->usbss_base);
9139ecb8875SAjay Kumar Gupta return ret;
9149ecb8875SAjay Kumar Gupta }
91597238b35SSebastian Andrzej Siewior
dsps_remove(struct platform_device * pdev)916e6547b5eSUwe Kleine-König static void dsps_remove(struct platform_device *pdev)
9179ecb8875SAjay Kumar Gupta {
9189ecb8875SAjay Kumar Gupta struct dsps_glue *glue = platform_get_drvdata(pdev);
9199ecb8875SAjay Kumar Gupta
92097238b35SSebastian Andrzej Siewior platform_device_unregister(glue->musb);
9219ecb8875SAjay Kumar Gupta
9229ecb8875SAjay Kumar Gupta pm_runtime_disable(&pdev->dev);
9236b7ad496SBin Liu iounmap(glue->usbss_base);
9249ecb8875SAjay Kumar Gupta }
9259ecb8875SAjay Kumar Gupta
926fa7b4ca5SSebastian Andrzej Siewior static const struct dsps_musb_wrapper am33xx_driver_data = {
9279ecb8875SAjay Kumar Gupta .revision = 0x00,
9289ecb8875SAjay Kumar Gupta .control = 0x14,
9299ecb8875SAjay Kumar Gupta .status = 0x18,
9309ecb8875SAjay Kumar Gupta .epintr_set = 0x38,
9319ecb8875SAjay Kumar Gupta .epintr_clear = 0x40,
9329ecb8875SAjay Kumar Gupta .epintr_status = 0x30,
9339ecb8875SAjay Kumar Gupta .coreintr_set = 0x3c,
9349ecb8875SAjay Kumar Gupta .coreintr_clear = 0x44,
9359ecb8875SAjay Kumar Gupta .coreintr_status = 0x34,
9369ecb8875SAjay Kumar Gupta .phy_utmi = 0xe0,
9379ecb8875SAjay Kumar Gupta .mode = 0xe8,
938b991f9b7SDaniel Mack .tx_mode = 0x70,
939b991f9b7SDaniel Mack .rx_mode = 0x74,
9409ecb8875SAjay Kumar Gupta .reset = 0,
9419ecb8875SAjay Kumar Gupta .otg_disable = 21,
9429ecb8875SAjay Kumar Gupta .iddig = 8,
943943c1397SFelipe Balbi .iddig_mux = 7,
9449ecb8875SAjay Kumar Gupta .usb_shift = 0,
9459ecb8875SAjay Kumar Gupta .usb_mask = 0x1ff,
9469ecb8875SAjay Kumar Gupta .usb_bitmap = (0x1ff << 0),
9479ecb8875SAjay Kumar Gupta .drvvbus = 8,
9489ecb8875SAjay Kumar Gupta .txep_shift = 0,
9499ecb8875SAjay Kumar Gupta .txep_mask = 0xffff,
9509ecb8875SAjay Kumar Gupta .txep_bitmap = (0xffff << 0),
9519ecb8875SAjay Kumar Gupta .rxep_shift = 16,
9529ecb8875SAjay Kumar Gupta .rxep_mask = 0xfffe,
9539ecb8875SAjay Kumar Gupta .rxep_bitmap = (0xfffe << 16),
9549e204d88SFelipe Balbi .poll_timeout = 2000, /* ms */
9559ecb8875SAjay Kumar Gupta };
9569ecb8875SAjay Kumar Gupta
9572f82686eSBill Pemberton static const struct of_device_id musb_dsps_of_match[] = {
95865145677SAjay Kumar Gupta { .compatible = "ti,musb-am33xx",
9593e457371STony Lindgren .data = &am33xx_driver_data, },
9603e457371STony Lindgren { .compatible = "ti,musb-dm816",
9613e457371STony Lindgren .data = &am33xx_driver_data, },
9629ecb8875SAjay Kumar Gupta { },
9639ecb8875SAjay Kumar Gupta };
9649ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
9659ecb8875SAjay Kumar Gupta
9665b783983SWolfram Sang #ifdef CONFIG_PM_SLEEP
dsps_suspend(struct device * dev)967869c5978SDaniel Mack static int dsps_suspend(struct device *dev)
968869c5978SDaniel Mack {
969869c5978SDaniel Mack struct dsps_glue *glue = dev_get_drvdata(dev);
970869c5978SDaniel Mack const struct dsps_musb_wrapper *wrp = glue->wrp;
971869c5978SDaniel Mack struct musb *musb = platform_get_drvdata(glue->musb);
972f042e9cbSSebastian Andrzej Siewior void __iomem *mbase;
973706d61b2SJohan Hovold int ret;
974f042e9cbSSebastian Andrzej Siewior
975f042e9cbSSebastian Andrzej Siewior if (!musb)
976f042e9cbSSebastian Andrzej Siewior /* This can happen if the musb device is in -EPROBE_DEFER */
977f042e9cbSSebastian Andrzej Siewior return 0;
978f042e9cbSSebastian Andrzej Siewior
979706d61b2SJohan Hovold ret = pm_runtime_get_sync(dev);
980706d61b2SJohan Hovold if (ret < 0) {
981706d61b2SJohan Hovold pm_runtime_put_noidle(dev);
982706d61b2SJohan Hovold return ret;
983706d61b2SJohan Hovold }
984706d61b2SJohan Hovold
985b82162bcSBin Liu del_timer_sync(&musb->dev_timer);
986706d61b2SJohan Hovold
987f042e9cbSSebastian Andrzej Siewior mbase = musb->ctrl_base;
988086b2882SBin Liu glue->context.control = musb_readl(mbase, wrp->control);
989086b2882SBin Liu glue->context.epintr = musb_readl(mbase, wrp->epintr_set);
990086b2882SBin Liu glue->context.coreintr = musb_readl(mbase, wrp->coreintr_set);
991086b2882SBin Liu glue->context.phy_utmi = musb_readl(mbase, wrp->phy_utmi);
992086b2882SBin Liu glue->context.mode = musb_readl(mbase, wrp->mode);
993086b2882SBin Liu glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode);
994086b2882SBin Liu glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode);
995869c5978SDaniel Mack
99625534828SAlexandre Bailon dsps_dma_controller_suspend(glue);
99725534828SAlexandre Bailon
998869c5978SDaniel Mack return 0;
999869c5978SDaniel Mack }
1000869c5978SDaniel Mack
dsps_resume(struct device * dev)1001869c5978SDaniel Mack static int dsps_resume(struct device *dev)
1002869c5978SDaniel Mack {
1003869c5978SDaniel Mack struct dsps_glue *glue = dev_get_drvdata(dev);
1004869c5978SDaniel Mack const struct dsps_musb_wrapper *wrp = glue->wrp;
1005869c5978SDaniel Mack struct musb *musb = platform_get_drvdata(glue->musb);
1006f042e9cbSSebastian Andrzej Siewior void __iomem *mbase;
1007869c5978SDaniel Mack
1008f042e9cbSSebastian Andrzej Siewior if (!musb)
1009f042e9cbSSebastian Andrzej Siewior return 0;
1010f042e9cbSSebastian Andrzej Siewior
101125534828SAlexandre Bailon dsps_dma_controller_resume(glue);
101225534828SAlexandre Bailon
1013f042e9cbSSebastian Andrzej Siewior mbase = musb->ctrl_base;
1014086b2882SBin Liu musb_writel(mbase, wrp->control, glue->context.control);
1015086b2882SBin Liu musb_writel(mbase, wrp->epintr_set, glue->context.epintr);
1016086b2882SBin Liu musb_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
1017086b2882SBin Liu musb_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
1018086b2882SBin Liu musb_writel(mbase, wrp->mode, glue->context.mode);
1019086b2882SBin Liu musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
1020086b2882SBin Liu musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
1021e47d9254SAntoine Tenart if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
10227ad76955SBin Liu musb->port_mode == MUSB_OTG)
1023369469a9STony Lindgren dsps_mod_timer(glue, -1);
1024869c5978SDaniel Mack
1025706d61b2SJohan Hovold pm_runtime_put(dev);
1026706d61b2SJohan Hovold
1027869c5978SDaniel Mack return 0;
1028869c5978SDaniel Mack }
1029869c5978SDaniel Mack #endif
1030869c5978SDaniel Mack
1031869c5978SDaniel Mack static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
1032869c5978SDaniel Mack
10339ecb8875SAjay Kumar Gupta static struct platform_driver dsps_usbss_driver = {
10349ecb8875SAjay Kumar Gupta .probe = dsps_probe,
1035e6547b5eSUwe Kleine-König .remove_new = dsps_remove,
10369ecb8875SAjay Kumar Gupta .driver = {
10379ecb8875SAjay Kumar Gupta .name = "musb-dsps",
1038869c5978SDaniel Mack .pm = &dsps_pm_ops,
1039b432cb83SSachin Kamat .of_match_table = musb_dsps_of_match,
10409ecb8875SAjay Kumar Gupta },
10419ecb8875SAjay Kumar Gupta };
10429ecb8875SAjay Kumar Gupta
10439ecb8875SAjay Kumar Gupta MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
10449ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
10459ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
10469ecb8875SAjay Kumar Gupta MODULE_LICENSE("GPL v2");
10479ecb8875SAjay Kumar Gupta
104897238b35SSebastian Andrzej Siewior module_platform_driver(dsps_usbss_driver);
1049