xref: /linux/drivers/usb/musb/musb_dsps.c (revision e6547b5e5c2c493bbd3b6add3177e8498ff0e063)
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_device.h>
309ecb8875SAjay Kumar Gupta #include <linux/of_address.h>
3197238b35SSebastian Andrzej Siewior #include <linux/of_irq.h>
32c031a7d4SSebastian Andrzej Siewior #include <linux/usb/of.h>
339ecb8875SAjay Kumar Gupta 
3440f099e3SMarkus Pargmann #include <linux/debugfs.h>
3540f099e3SMarkus Pargmann 
369ecb8875SAjay Kumar Gupta #include "musb_core.h"
379ecb8875SAjay Kumar Gupta 
3865145677SAjay Kumar Gupta static const struct of_device_id musb_dsps_of_match[];
3965145677SAjay Kumar Gupta 
4009e03a89SLee Jones /*
419ecb8875SAjay Kumar Gupta  * DSPS musb wrapper register offset.
429ecb8875SAjay Kumar Gupta  * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
439ecb8875SAjay Kumar Gupta  * musb ips.
449ecb8875SAjay Kumar Gupta  */
459ecb8875SAjay Kumar Gupta struct dsps_musb_wrapper {
469ecb8875SAjay Kumar Gupta 	u16	revision;
479ecb8875SAjay Kumar Gupta 	u16	control;
489ecb8875SAjay Kumar Gupta 	u16	status;
499ecb8875SAjay Kumar Gupta 	u16	epintr_set;
509ecb8875SAjay Kumar Gupta 	u16	epintr_clear;
519ecb8875SAjay Kumar Gupta 	u16	epintr_status;
529ecb8875SAjay Kumar Gupta 	u16	coreintr_set;
539ecb8875SAjay Kumar Gupta 	u16	coreintr_clear;
549ecb8875SAjay Kumar Gupta 	u16	coreintr_status;
559ecb8875SAjay Kumar Gupta 	u16	phy_utmi;
569ecb8875SAjay Kumar Gupta 	u16	mode;
57b991f9b7SDaniel Mack 	u16	tx_mode;
58b991f9b7SDaniel Mack 	u16	rx_mode;
599ecb8875SAjay Kumar Gupta 
609ecb8875SAjay Kumar Gupta 	/* bit positions for control */
619ecb8875SAjay Kumar Gupta 	unsigned	reset:5;
629ecb8875SAjay Kumar Gupta 
639ecb8875SAjay Kumar Gupta 	/* bit positions for interrupt */
649ecb8875SAjay Kumar Gupta 	unsigned	usb_shift:5;
659ecb8875SAjay Kumar Gupta 	u32		usb_mask;
669ecb8875SAjay Kumar Gupta 	u32		usb_bitmap;
679ecb8875SAjay Kumar Gupta 	unsigned	drvvbus:5;
689ecb8875SAjay Kumar Gupta 
699ecb8875SAjay Kumar Gupta 	unsigned	txep_shift:5;
709ecb8875SAjay Kumar Gupta 	u32		txep_mask;
719ecb8875SAjay Kumar Gupta 	u32		txep_bitmap;
729ecb8875SAjay Kumar Gupta 
739ecb8875SAjay Kumar Gupta 	unsigned	rxep_shift:5;
749ecb8875SAjay Kumar Gupta 	u32		rxep_mask;
759ecb8875SAjay Kumar Gupta 	u32		rxep_bitmap;
769ecb8875SAjay Kumar Gupta 
779ecb8875SAjay Kumar Gupta 	/* bit positions for phy_utmi */
789ecb8875SAjay Kumar Gupta 	unsigned	otg_disable:5;
799ecb8875SAjay Kumar Gupta 
809ecb8875SAjay Kumar Gupta 	/* bit positions for mode */
819ecb8875SAjay Kumar Gupta 	unsigned	iddig:5;
82943c1397SFelipe Balbi 	unsigned	iddig_mux:5;
839ecb8875SAjay Kumar Gupta 	/* miscellaneous stuff */
849e204d88SFelipe Balbi 	unsigned	poll_timeout;
859ecb8875SAjay Kumar Gupta };
869ecb8875SAjay Kumar Gupta 
87869c5978SDaniel Mack /*
88869c5978SDaniel Mack  * register shadow for suspend
89869c5978SDaniel Mack  */
90869c5978SDaniel Mack struct dsps_context {
91869c5978SDaniel Mack 	u32 control;
92869c5978SDaniel Mack 	u32 epintr;
93869c5978SDaniel Mack 	u32 coreintr;
94869c5978SDaniel Mack 	u32 phy_utmi;
95869c5978SDaniel Mack 	u32 mode;
96869c5978SDaniel Mack 	u32 tx_mode;
97869c5978SDaniel Mack 	u32 rx_mode;
98869c5978SDaniel Mack };
99869c5978SDaniel Mack 
10009e03a89SLee Jones /*
1019ecb8875SAjay Kumar Gupta  * DSPS glue structure.
1029ecb8875SAjay Kumar Gupta  */
1039ecb8875SAjay Kumar Gupta struct dsps_glue {
1049ecb8875SAjay Kumar Gupta 	struct device *dev;
10597238b35SSebastian Andrzej Siewior 	struct platform_device *musb;	/* child musb pdev */
1069ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
107369469a9STony Lindgren 	int vbus_irq;			/* optional vbus irq */
10897238b35SSebastian Andrzej Siewior 	unsigned long last_timer;    /* last timer data for each instance */
109371254ceSGeorge Cherian 	bool sw_babble_enabled;
11025534828SAlexandre Bailon 	void __iomem *usbss_base;
111869c5978SDaniel Mack 
112869c5978SDaniel Mack 	struct dsps_context context;
11340f099e3SMarkus Pargmann 	struct debugfs_regset32 regset;
11440f099e3SMarkus Pargmann 	struct dentry *dbgfs_root;
11540f099e3SMarkus Pargmann };
11640f099e3SMarkus Pargmann 
11740f099e3SMarkus Pargmann static const struct debugfs_reg32 dsps_musb_regs[] = {
11840f099e3SMarkus Pargmann 	{ "revision",		0x00 },
11940f099e3SMarkus Pargmann 	{ "control",		0x14 },
12040f099e3SMarkus Pargmann 	{ "status",		0x18 },
12140f099e3SMarkus Pargmann 	{ "eoi",		0x24 },
12240f099e3SMarkus Pargmann 	{ "intr0_stat",		0x30 },
12340f099e3SMarkus Pargmann 	{ "intr1_stat",		0x34 },
12440f099e3SMarkus Pargmann 	{ "intr0_set",		0x38 },
12540f099e3SMarkus Pargmann 	{ "intr1_set",		0x3c },
12640f099e3SMarkus Pargmann 	{ "txmode",		0x70 },
12740f099e3SMarkus Pargmann 	{ "rxmode",		0x74 },
12840f099e3SMarkus Pargmann 	{ "autoreq",		0xd0 },
12940f099e3SMarkus Pargmann 	{ "srpfixtime",		0xd4 },
13040f099e3SMarkus Pargmann 	{ "tdown",		0xd8 },
13140f099e3SMarkus Pargmann 	{ "phy_utmi",		0xe0 },
13240f099e3SMarkus Pargmann 	{ "mode",		0xe8 },
1339ecb8875SAjay Kumar Gupta };
1349ecb8875SAjay Kumar Gupta 
135369469a9STony Lindgren static void dsps_mod_timer(struct dsps_glue *glue, int wait_ms)
136369469a9STony Lindgren {
137b82162bcSBin Liu 	struct musb *musb = platform_get_drvdata(glue->musb);
138369469a9STony Lindgren 	int wait;
139369469a9STony Lindgren 
140369469a9STony Lindgren 	if (wait_ms < 0)
141369469a9STony Lindgren 		wait = msecs_to_jiffies(glue->wrp->poll_timeout);
142369469a9STony Lindgren 	else
143369469a9STony Lindgren 		wait = msecs_to_jiffies(wait_ms);
144369469a9STony Lindgren 
145b82162bcSBin Liu 	mod_timer(&musb->dev_timer, jiffies + wait);
146369469a9STony Lindgren }
147369469a9STony Lindgren 
148369469a9STony Lindgren /*
149369469a9STony Lindgren  * If no vbus irq from the PMIC is configured, we need to poll VBUS status.
150369469a9STony Lindgren  */
151369469a9STony Lindgren static void dsps_mod_timer_optional(struct dsps_glue *glue)
152369469a9STony Lindgren {
153369469a9STony Lindgren 	if (glue->vbus_irq)
154369469a9STony Lindgren 		return;
155369469a9STony Lindgren 
156369469a9STony Lindgren 	dsps_mod_timer(glue, -1);
157369469a9STony Lindgren }
158369469a9STony Lindgren 
15925534828SAlexandre Bailon /* USBSS  / USB AM335x */
16025534828SAlexandre Bailon #define USBSS_IRQ_STATUS	0x28
16125534828SAlexandre Bailon #define USBSS_IRQ_ENABLER	0x2c
16225534828SAlexandre Bailon #define USBSS_IRQ_CLEARR	0x30
16325534828SAlexandre Bailon 
16425534828SAlexandre Bailon #define USBSS_IRQ_PD_COMP	(1 << 2)
16525534828SAlexandre Bailon 
16609e03a89SLee Jones /*
1679ecb8875SAjay Kumar Gupta  * dsps_musb_enable - enable interrupts
1689ecb8875SAjay Kumar Gupta  */
1699ecb8875SAjay Kumar Gupta static void dsps_musb_enable(struct musb *musb)
1709ecb8875SAjay Kumar Gupta {
1719ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
172e823d948SKefeng Wang 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
1739ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1749ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
1759ecb8875SAjay Kumar Gupta 	u32 epmask, coremask;
1769ecb8875SAjay Kumar Gupta 
1779ecb8875SAjay Kumar Gupta 	/* Workaround: setup IRQs through both register sets. */
1789ecb8875SAjay Kumar Gupta 	epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
1799ecb8875SAjay Kumar Gupta 	       ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
1809ecb8875SAjay Kumar Gupta 	coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
1819ecb8875SAjay Kumar Gupta 
182086b2882SBin Liu 	musb_writel(reg_base, wrp->epintr_set, epmask);
183086b2882SBin Liu 	musb_writel(reg_base, wrp->coreintr_set, coremask);
18454578ee8SBin Liu 	/*
18554578ee8SBin Liu 	 * start polling for runtime PM active and idle,
18654578ee8SBin Liu 	 * and for ID change in dual-role idle mode.
18754578ee8SBin Liu 	 */
18854578ee8SBin Liu 	if (musb->xceiv->otg->state == OTG_STATE_B_IDLE)
189369469a9STony Lindgren 		dsps_mod_timer(glue, -1);
1909ecb8875SAjay Kumar Gupta }
1919ecb8875SAjay Kumar Gupta 
19209e03a89SLee Jones /*
1939ecb8875SAjay Kumar Gupta  * dsps_musb_disable - disable HDRC and flush interrupts
1949ecb8875SAjay Kumar Gupta  */
1959ecb8875SAjay Kumar Gupta static void dsps_musb_disable(struct musb *musb)
1969ecb8875SAjay Kumar Gupta {
1979ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
198e823d948SKefeng Wang 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
1999ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
2009ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
2019ecb8875SAjay Kumar Gupta 
202086b2882SBin Liu 	musb_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
203086b2882SBin Liu 	musb_writel(reg_base, wrp->epintr_clear,
2049ecb8875SAjay Kumar Gupta 			 wrp->txep_bitmap | wrp->rxep_bitmap);
205b82162bcSBin Liu 	del_timer_sync(&musb->dev_timer);
2069ecb8875SAjay Kumar Gupta }
2079ecb8875SAjay Kumar Gupta 
208ea2f35c0STony Lindgren /* Caller must take musb->lock */
209ea2f35c0STony Lindgren static int dsps_check_status(struct musb *musb, void *unused)
2109ecb8875SAjay Kumar Gupta {
2119ecb8875SAjay Kumar Gupta 	void __iomem *mregs = musb->mregs;
2129ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
213db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
2149ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
2159ecb8875SAjay Kumar Gupta 	u8 devctl;
2160f901c98SSebastian Andrzej Siewior 	int skip_session = 0;
2179ecb8875SAjay Kumar Gupta 
218369469a9STony Lindgren 	if (glue->vbus_irq)
219b82162bcSBin Liu 		del_timer(&musb->dev_timer);
220369469a9STony Lindgren 
2219ecb8875SAjay Kumar Gupta 	/*
2229ecb8875SAjay Kumar Gupta 	 * We poll because DSPS IP's won't expose several OTG-critical
2239ecb8875SAjay Kumar Gupta 	 * status change events (from the transceiver) otherwise.
2249ecb8875SAjay Kumar Gupta 	 */
225086b2882SBin Liu 	devctl = musb_readb(mregs, MUSB_DEVCTL);
2269ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
227e47d9254SAntoine Tenart 				usb_otg_state_string(musb->xceiv->otg->state));
2289ecb8875SAjay Kumar Gupta 
229e47d9254SAntoine Tenart 	switch (musb->xceiv->otg->state) {
2302f3fd2c5STony Lindgren 	case OTG_STATE_A_WAIT_VRISE:
2316010abf2SBin Liu 		if (musb->port_mode == MUSB_HOST) {
2326010abf2SBin Liu 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
233369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
2342f3fd2c5STony Lindgren 			break;
2356010abf2SBin Liu 		}
236df561f66SGustavo A. R. Silva 		fallthrough;
2376010abf2SBin Liu 
2389ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_BCON:
239b3addcf0SBin Liu 		/* keep VBUS on for host-only mode */
2407ad76955SBin Liu 		if (musb->port_mode == MUSB_HOST) {
241b3addcf0SBin Liu 			dsps_mod_timer_optional(glue);
242b3addcf0SBin Liu 			break;
243b3addcf0SBin Liu 		}
244086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
2450f901c98SSebastian Andrzej Siewior 		skip_session = 1;
246df561f66SGustavo A. R. Silva 		fallthrough;
2479ecb8875SAjay Kumar Gupta 
2480f901c98SSebastian Andrzej Siewior 	case OTG_STATE_A_IDLE:
2490f901c98SSebastian Andrzej Siewior 	case OTG_STATE_B_IDLE:
250369469a9STony Lindgren 		if (!glue->vbus_irq) {
2519ecb8875SAjay Kumar Gupta 			if (devctl & MUSB_DEVCTL_BDEVICE) {
252e47d9254SAntoine Tenart 				musb->xceiv->otg->state = OTG_STATE_B_IDLE;
2539ecb8875SAjay Kumar Gupta 				MUSB_DEV_MODE(musb);
2549ecb8875SAjay Kumar Gupta 			} else {
255e47d9254SAntoine Tenart 				musb->xceiv->otg->state = OTG_STATE_A_IDLE;
2569ecb8875SAjay Kumar Gupta 				MUSB_HST_MODE(musb);
2579ecb8875SAjay Kumar Gupta 			}
25854578ee8SBin Liu 
25954578ee8SBin Liu 			if (musb->port_mode == MUSB_PERIPHERAL)
26054578ee8SBin Liu 				skip_session = 1;
26154578ee8SBin Liu 
2620f901c98SSebastian Andrzej Siewior 			if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
263369469a9STony Lindgren 				musb_writeb(mregs, MUSB_DEVCTL,
264369469a9STony Lindgren 					    MUSB_DEVCTL_SESSION);
265369469a9STony Lindgren 		}
266369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
2679ecb8875SAjay Kumar Gupta 		break;
2689ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_VFALL:
269e47d9254SAntoine Tenart 		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
270086b2882SBin Liu 		musb_writel(musb->ctrl_base, wrp->coreintr_set,
2719ecb8875SAjay Kumar Gupta 			    MUSB_INTR_VBUSERROR << wrp->usb_shift);
2729ecb8875SAjay Kumar Gupta 		break;
2739ecb8875SAjay Kumar Gupta 	default:
2749ecb8875SAjay Kumar Gupta 		break;
2759ecb8875SAjay Kumar Gupta 	}
27665b3f50eSTony Lindgren 
277ea2f35c0STony Lindgren 	return 0;
278ea2f35c0STony Lindgren }
279ea2f35c0STony Lindgren 
28005678497SKees Cook static void otg_timer(struct timer_list *t)
281ea2f35c0STony Lindgren {
282b82162bcSBin Liu 	struct musb *musb = from_timer(musb, t, dev_timer);
283ea2f35c0STony Lindgren 	struct device *dev = musb->controller;
284ea2f35c0STony Lindgren 	unsigned long flags;
285ea2f35c0STony Lindgren 	int err;
286ea2f35c0STony Lindgren 
287ea2f35c0STony Lindgren 	err = pm_runtime_get(dev);
288ea2f35c0STony Lindgren 	if ((err != -EINPROGRESS) && err < 0) {
289ea2f35c0STony Lindgren 		dev_err(dev, "Poll could not pm_runtime_get: %i\n", err);
290ea2f35c0STony Lindgren 		pm_runtime_put_noidle(dev);
291ea2f35c0STony Lindgren 
292ea2f35c0STony Lindgren 		return;
293ea2f35c0STony Lindgren 	}
294ea2f35c0STony Lindgren 
295ea2f35c0STony Lindgren 	spin_lock_irqsave(&musb->lock, flags);
296ea2f35c0STony Lindgren 	err = musb_queue_resume_work(musb, dsps_check_status, NULL);
297ea2f35c0STony Lindgren 	if (err < 0)
298ea2f35c0STony Lindgren 		dev_err(dev, "%s resume work: %i\n", __func__, err);
299ea2f35c0STony Lindgren 	spin_unlock_irqrestore(&musb->lock, flags);
30065b3f50eSTony Lindgren 	pm_runtime_mark_last_busy(dev);
30165b3f50eSTony Lindgren 	pm_runtime_put_autosuspend(dev);
3029ecb8875SAjay Kumar Gupta }
3039ecb8875SAjay Kumar Gupta 
3044ab53a69SWei Yongjun static void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum)
305c48400baSBin Liu {
306c48400baSBin Liu 	u32 epintr;
307c48400baSBin Liu 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
308c48400baSBin Liu 	const struct dsps_musb_wrapper *wrp = glue->wrp;
309c48400baSBin Liu 
310c48400baSBin Liu 	/* musb->lock might already been held */
311c48400baSBin Liu 	epintr = (1 << epnum) << wrp->rxep_shift;
312c48400baSBin Liu 	musb_writel(musb->ctrl_base, wrp->epintr_status, epintr);
313c48400baSBin Liu }
314c48400baSBin Liu 
3159ecb8875SAjay Kumar Gupta static irqreturn_t dsps_interrupt(int irq, void *hci)
3169ecb8875SAjay Kumar Gupta {
3179ecb8875SAjay Kumar Gupta 	struct musb  *musb = hci;
3189ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
3199ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
320db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
3219ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
3229ecb8875SAjay Kumar Gupta 	unsigned long flags;
3239ecb8875SAjay Kumar Gupta 	irqreturn_t ret = IRQ_NONE;
3249ecb8875SAjay Kumar Gupta 	u32 epintr, usbintr;
3259ecb8875SAjay Kumar Gupta 
3269ecb8875SAjay Kumar Gupta 	spin_lock_irqsave(&musb->lock, flags);
3279ecb8875SAjay Kumar Gupta 
3289ecb8875SAjay Kumar Gupta 	/* Get endpoint interrupts */
329086b2882SBin Liu 	epintr = musb_readl(reg_base, wrp->epintr_status);
3309ecb8875SAjay Kumar Gupta 	musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
3319ecb8875SAjay Kumar Gupta 	musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
3329ecb8875SAjay Kumar Gupta 
3339ecb8875SAjay Kumar Gupta 	if (epintr)
334086b2882SBin Liu 		musb_writel(reg_base, wrp->epintr_status, epintr);
3359ecb8875SAjay Kumar Gupta 
3369ecb8875SAjay Kumar Gupta 	/* Get usb core interrupts */
337086b2882SBin Liu 	usbintr = musb_readl(reg_base, wrp->coreintr_status);
3389ecb8875SAjay Kumar Gupta 	if (!usbintr && !epintr)
3399be73baeSSebastian Andrzej Siewior 		goto out;
3409ecb8875SAjay Kumar Gupta 
3419ecb8875SAjay Kumar Gupta 	musb->int_usb =	(usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
3429ecb8875SAjay Kumar Gupta 	if (usbintr)
343086b2882SBin Liu 		musb_writel(reg_base, wrp->coreintr_status, usbintr);
3449ecb8875SAjay Kumar Gupta 
3459ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
3469ecb8875SAjay Kumar Gupta 			usbintr, epintr);
3471d57de30SDaniel Mack 
3489ecb8875SAjay Kumar Gupta 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
349086b2882SBin Liu 		int drvvbus = musb_readl(reg_base, wrp->status);
3509ecb8875SAjay Kumar Gupta 		void __iomem *mregs = musb->mregs;
351086b2882SBin Liu 		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
3529ecb8875SAjay Kumar Gupta 		int err;
3539ecb8875SAjay Kumar Gupta 
354032ec49fSFelipe Balbi 		err = musb->int_usb & MUSB_INTR_VBUSERROR;
3559ecb8875SAjay Kumar Gupta 		if (err) {
3569ecb8875SAjay Kumar Gupta 			/*
3579ecb8875SAjay Kumar Gupta 			 * The Mentor core doesn't debounce VBUS as needed
3589ecb8875SAjay Kumar Gupta 			 * to cope with device connect current spikes. This
3599ecb8875SAjay Kumar Gupta 			 * means it's not uncommon for bus-powered devices
3609ecb8875SAjay Kumar Gupta 			 * to get VBUS errors during enumeration.
3619ecb8875SAjay Kumar Gupta 			 *
3629ecb8875SAjay Kumar Gupta 			 * This is a workaround, but newer RTL from Mentor
3639ecb8875SAjay Kumar Gupta 			 * seems to allow a better one: "re"-starting sessions
3649ecb8875SAjay Kumar Gupta 			 * without waiting for VBUS to stop registering in
3659ecb8875SAjay Kumar Gupta 			 * devctl.
3669ecb8875SAjay Kumar Gupta 			 */
3679ecb8875SAjay Kumar Gupta 			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
368e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
369369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
3709ecb8875SAjay Kumar Gupta 			WARNING("VBUS error workaround (delay coming)\n");
371032ec49fSFelipe Balbi 		} else if (drvvbus) {
3729ecb8875SAjay Kumar Gupta 			MUSB_HST_MODE(musb);
373e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
374369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
3759ecb8875SAjay Kumar Gupta 		} else {
3769ecb8875SAjay Kumar Gupta 			musb->is_active = 0;
3779ecb8875SAjay Kumar Gupta 			MUSB_DEV_MODE(musb);
378e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_B_IDLE;
3799ecb8875SAjay Kumar Gupta 		}
3809ecb8875SAjay Kumar Gupta 
3819ecb8875SAjay Kumar Gupta 		/* NOTE: this must complete power-on within 100 ms. */
3829ecb8875SAjay Kumar Gupta 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
3839ecb8875SAjay Kumar Gupta 				drvvbus ? "on" : "off",
384e47d9254SAntoine Tenart 				usb_otg_state_string(musb->xceiv->otg->state),
3859ecb8875SAjay Kumar Gupta 				err ? " ERROR" : "",
3869ecb8875SAjay Kumar Gupta 				devctl);
3879ecb8875SAjay Kumar Gupta 		ret = IRQ_HANDLED;
3889ecb8875SAjay Kumar Gupta 	}
3899ecb8875SAjay Kumar Gupta 
3909ecb8875SAjay Kumar Gupta 	if (musb->int_tx || musb->int_rx || musb->int_usb)
3919ecb8875SAjay Kumar Gupta 		ret |= musb_interrupt(musb);
3929ecb8875SAjay Kumar Gupta 
3932f3fd2c5STony Lindgren 	/* Poll for ID change and connect */
3942f3fd2c5STony Lindgren 	switch (musb->xceiv->otg->state) {
3952f3fd2c5STony Lindgren 	case OTG_STATE_B_IDLE:
3962f3fd2c5STony Lindgren 	case OTG_STATE_A_WAIT_BCON:
397369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
3982f3fd2c5STony Lindgren 		break;
3992f3fd2c5STony Lindgren 	default:
4002f3fd2c5STony Lindgren 		break;
4012f3fd2c5STony Lindgren 	}
4022f3fd2c5STony Lindgren 
4039be73baeSSebastian Andrzej Siewior out:
4049ecb8875SAjay Kumar Gupta 	spin_unlock_irqrestore(&musb->lock, flags);
4059ecb8875SAjay Kumar Gupta 
4069ecb8875SAjay Kumar Gupta 	return ret;
4079ecb8875SAjay Kumar Gupta }
4089ecb8875SAjay Kumar Gupta 
40940f099e3SMarkus Pargmann static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue)
41040f099e3SMarkus Pargmann {
41140f099e3SMarkus Pargmann 	struct dentry *root;
41240f099e3SMarkus Pargmann 	char buf[128];
41340f099e3SMarkus Pargmann 
41440f099e3SMarkus Pargmann 	sprintf(buf, "%s.dsps", dev_name(musb->controller));
415b3c69ec8SChunfeng Yun 	root = debugfs_create_dir(buf, usb_debug_root);
41640f099e3SMarkus Pargmann 	glue->dbgfs_root = root;
41740f099e3SMarkus Pargmann 
41840f099e3SMarkus Pargmann 	glue->regset.regs = dsps_musb_regs;
41940f099e3SMarkus Pargmann 	glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs);
42040f099e3SMarkus Pargmann 	glue->regset.base = musb->ctrl_base;
42140f099e3SMarkus Pargmann 
4228a1ef171SGreg Kroah-Hartman 	debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset);
42340f099e3SMarkus Pargmann 	return 0;
42440f099e3SMarkus Pargmann }
42540f099e3SMarkus Pargmann 
4269ecb8875SAjay Kumar Gupta static int dsps_musb_init(struct musb *musb)
4279ecb8875SAjay Kumar Gupta {
4289ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
429db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
43097238b35SSebastian Andrzej Siewior 	struct platform_device *parent = to_platform_device(dev->parent);
4319ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
43297238b35SSebastian Andrzej Siewior 	void __iomem *reg_base;
433ffa13d2dSGeert Uytterhoeven 	struct resource *r;
4349ecb8875SAjay Kumar Gupta 	u32 rev, val;
43540f099e3SMarkus Pargmann 	int ret;
4369ecb8875SAjay Kumar Gupta 
437ffa13d2dSGeert Uytterhoeven 	r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
438ffa13d2dSGeert Uytterhoeven 	reg_base = devm_ioremap_resource(dev, r);
43951ef74f6SJulia Lawall 	if (IS_ERR(reg_base))
44051ef74f6SJulia Lawall 		return PTR_ERR(reg_base);
44197238b35SSebastian Andrzej Siewior 	musb->ctrl_base = reg_base;
4429ecb8875SAjay Kumar Gupta 
443d7554226SAfzal Mohammed 	/* NOP driver needs change if supporting dual instance */
444983f3cabSFelipe Balbi 	musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "phys", 0);
44597238b35SSebastian Andrzej Siewior 	if (IS_ERR(musb->xceiv))
44697238b35SSebastian Andrzej Siewior 		return PTR_ERR(musb->xceiv);
4479ecb8875SAjay Kumar Gupta 
448bb90600dSTony Lindgren 	musb->phy = devm_phy_get(dev->parent, "usb2-phy");
449bb90600dSTony Lindgren 
4509ecb8875SAjay Kumar Gupta 	/* Returns zero if e.g. not clocked */
451086b2882SBin Liu 	rev = musb_readl(reg_base, wrp->revision);
45297238b35SSebastian Andrzej Siewior 	if (!rev)
45397238b35SSebastian Andrzej Siewior 		return -ENODEV;
4549ecb8875SAjay Kumar Gupta 
455bb90600dSTony Lindgren 	if (IS_ERR(musb->phy))  {
456bb90600dSTony Lindgren 		musb->phy = NULL;
457bb90600dSTony Lindgren 	} else {
458bb90600dSTony Lindgren 		ret = phy_init(musb->phy);
459bb90600dSTony Lindgren 		if (ret < 0)
460bb90600dSTony Lindgren 			return ret;
461bb90600dSTony Lindgren 		ret = phy_power_on(musb->phy);
462bb90600dSTony Lindgren 		if (ret) {
463bb90600dSTony Lindgren 			phy_exit(musb->phy);
464bb90600dSTony Lindgren 			return ret;
465bb90600dSTony Lindgren 		}
466bb90600dSTony Lindgren 	}
467bb90600dSTony Lindgren 
468b82162bcSBin Liu 	timer_setup(&musb->dev_timer, otg_timer, 0);
4699ecb8875SAjay Kumar Gupta 
4709ecb8875SAjay Kumar Gupta 	/* Reset the musb */
471086b2882SBin Liu 	musb_writel(reg_base, wrp->control, (1 << wrp->reset));
4729ecb8875SAjay Kumar Gupta 
4739ecb8875SAjay Kumar Gupta 	musb->isr = dsps_interrupt;
4749ecb8875SAjay Kumar Gupta 
4759ecb8875SAjay Kumar Gupta 	/* reset the otgdisable bit, needed for host mode to work */
476086b2882SBin Liu 	val = musb_readl(reg_base, wrp->phy_utmi);
4779ecb8875SAjay Kumar Gupta 	val &= ~(1 << wrp->otg_disable);
478086b2882SBin Liu 	musb_writel(musb->ctrl_base, wrp->phy_utmi, val);
4799ecb8875SAjay Kumar Gupta 
480371254ceSGeorge Cherian 	/*
481371254ceSGeorge Cherian 	 *  Check whether the dsps version has babble control enabled.
482371254ceSGeorge Cherian 	 * In latest silicon revision the babble control logic is enabled.
483371254ceSGeorge Cherian 	 * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
484371254ceSGeorge Cherian 	 * logic enabled.
485371254ceSGeorge Cherian 	 */
486086b2882SBin Liu 	val = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
487f860f0b1SFelipe Balbi 	if (val & MUSB_BABBLE_RCV_DISABLE) {
488371254ceSGeorge Cherian 		glue->sw_babble_enabled = true;
489371254ceSGeorge Cherian 		val |= MUSB_BABBLE_SW_SESSION_CTRL;
490086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
491371254ceSGeorge Cherian 	}
492371254ceSGeorge Cherian 
493369469a9STony Lindgren 	dsps_mod_timer(glue, -1);
4942f3fd2c5STony Lindgren 
495e94a7369SSaurabh Karajgaonkar 	return dsps_musb_dbg_init(musb, glue);
4969ecb8875SAjay Kumar Gupta }
4979ecb8875SAjay Kumar Gupta 
4989ecb8875SAjay Kumar Gupta static int dsps_musb_exit(struct musb *musb)
4999ecb8875SAjay Kumar Gupta {
5009ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
501db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
5029ecb8875SAjay Kumar Gupta 
503b82162bcSBin Liu 	del_timer_sync(&musb->dev_timer);
504bb90600dSTony Lindgren 	phy_power_off(musb->phy);
505bb90600dSTony Lindgren 	phy_exit(musb->phy);
5060fca91b8SDaniel Mack 	debugfs_remove_recursive(glue->dbgfs_root);
5070fca91b8SDaniel Mack 
5089ecb8875SAjay Kumar Gupta 	return 0;
5099ecb8875SAjay Kumar Gupta }
5109ecb8875SAjay Kumar Gupta 
511943c1397SFelipe Balbi static int dsps_musb_set_mode(struct musb *musb, u8 mode)
512943c1397SFelipe Balbi {
513943c1397SFelipe Balbi 	struct device *dev = musb->controller;
514943c1397SFelipe Balbi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
515943c1397SFelipe Balbi 	const struct dsps_musb_wrapper *wrp = glue->wrp;
516943c1397SFelipe Balbi 	void __iomem *ctrl_base = musb->ctrl_base;
517943c1397SFelipe Balbi 	u32 reg;
518943c1397SFelipe Balbi 
519086b2882SBin Liu 	reg = musb_readl(ctrl_base, wrp->mode);
520943c1397SFelipe Balbi 
521943c1397SFelipe Balbi 	switch (mode) {
522943c1397SFelipe Balbi 	case MUSB_HOST:
523943c1397SFelipe Balbi 		reg &= ~(1 << wrp->iddig);
524943c1397SFelipe Balbi 
525943c1397SFelipe Balbi 		/*
526943c1397SFelipe Balbi 		 * if we're setting mode to host-only or device-only, we're
527943c1397SFelipe Balbi 		 * going to ignore whatever the PHY sends us and just force
528943c1397SFelipe Balbi 		 * ID pin status by SW
529943c1397SFelipe Balbi 		 */
530943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig_mux);
531943c1397SFelipe Balbi 
532086b2882SBin Liu 		musb_writel(ctrl_base, wrp->mode, reg);
533086b2882SBin Liu 		musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
534943c1397SFelipe Balbi 		break;
535943c1397SFelipe Balbi 	case MUSB_PERIPHERAL:
536943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig);
537943c1397SFelipe Balbi 
538943c1397SFelipe Balbi 		/*
539943c1397SFelipe Balbi 		 * if we're setting mode to host-only or device-only, we're
540943c1397SFelipe Balbi 		 * going to ignore whatever the PHY sends us and just force
541943c1397SFelipe Balbi 		 * ID pin status by SW
542943c1397SFelipe Balbi 		 */
543943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig_mux);
544943c1397SFelipe Balbi 
545086b2882SBin Liu 		musb_writel(ctrl_base, wrp->mode, reg);
546943c1397SFelipe Balbi 		break;
547943c1397SFelipe Balbi 	case MUSB_OTG:
548086b2882SBin Liu 		musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
549943c1397SFelipe Balbi 		break;
550943c1397SFelipe Balbi 	default:
551943c1397SFelipe Balbi 		dev_err(glue->dev, "unsupported mode %d\n", mode);
552943c1397SFelipe Balbi 		return -EINVAL;
553943c1397SFelipe Balbi 	}
554943c1397SFelipe Balbi 
555943c1397SFelipe Balbi 	return 0;
556943c1397SFelipe Balbi }
557943c1397SFelipe Balbi 
5583709ffcaSFelipe Balbi static bool dsps_sw_babble_control(struct musb *musb)
559371254ceSGeorge Cherian {
560371254ceSGeorge Cherian 	u8 babble_ctl;
561371254ceSGeorge Cherian 	bool session_restart =  false;
562371254ceSGeorge Cherian 
563086b2882SBin Liu 	babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
564371254ceSGeorge Cherian 	dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
565371254ceSGeorge Cherian 		babble_ctl);
566371254ceSGeorge Cherian 	/*
567371254ceSGeorge Cherian 	 * check line monitor flag to check whether babble is
568371254ceSGeorge Cherian 	 * due to noise
569371254ceSGeorge Cherian 	 */
570371254ceSGeorge Cherian 	dev_dbg(musb->controller, "STUCK_J is %s\n",
571371254ceSGeorge Cherian 		babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
572371254ceSGeorge Cherian 
573371254ceSGeorge Cherian 	if (babble_ctl & MUSB_BABBLE_STUCK_J) {
574371254ceSGeorge Cherian 		int timeout = 10;
575371254ceSGeorge Cherian 
576371254ceSGeorge Cherian 		/*
577371254ceSGeorge Cherian 		 * babble is due to noise, then set transmit idle (d7 bit)
578371254ceSGeorge Cherian 		 * to resume normal operation
579371254ceSGeorge Cherian 		 */
580086b2882SBin Liu 		babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
581371254ceSGeorge Cherian 		babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
582086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
583371254ceSGeorge Cherian 
584371254ceSGeorge Cherian 		/* wait till line monitor flag cleared */
585371254ceSGeorge Cherian 		dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
586371254ceSGeorge Cherian 		do {
587086b2882SBin Liu 			babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
588371254ceSGeorge Cherian 			udelay(1);
589371254ceSGeorge Cherian 		} while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
590371254ceSGeorge Cherian 
591371254ceSGeorge Cherian 		/* check whether stuck_at_j bit cleared */
592371254ceSGeorge Cherian 		if (babble_ctl & MUSB_BABBLE_STUCK_J) {
593371254ceSGeorge Cherian 			/*
594371254ceSGeorge Cherian 			 * real babble condition has occurred
595371254ceSGeorge Cherian 			 * restart the controller to start the
596371254ceSGeorge Cherian 			 * session again
597371254ceSGeorge Cherian 			 */
598371254ceSGeorge Cherian 			dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
599371254ceSGeorge Cherian 				babble_ctl);
600371254ceSGeorge Cherian 			session_restart = true;
601371254ceSGeorge Cherian 		}
602371254ceSGeorge Cherian 	} else {
603371254ceSGeorge Cherian 		session_restart = true;
604371254ceSGeorge Cherian 	}
605371254ceSGeorge Cherian 
606371254ceSGeorge Cherian 	return session_restart;
607371254ceSGeorge Cherian }
608371254ceSGeorge Cherian 
609b28a6432SFelipe Balbi static int dsps_musb_recover(struct musb *musb)
6101d57de30SDaniel Mack {
6111d57de30SDaniel Mack 	struct device *dev = musb->controller;
6121d57de30SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
613011d0dd5SFelipe Balbi 	int session_restart = 0;
6141d57de30SDaniel Mack 
615371254ceSGeorge Cherian 	if (glue->sw_babble_enabled)
6163709ffcaSFelipe Balbi 		session_restart = dsps_sw_babble_control(musb);
617011d0dd5SFelipe Balbi 	else
618371254ceSGeorge Cherian 		session_restart = 1;
61956700178SGeorge Cherian 
620d0cddae7SFelipe Balbi 	return session_restart ? 0 : -EPIPE;
6211d57de30SDaniel Mack }
6221d57de30SDaniel Mack 
6233e457371STony Lindgren /* Similar to am35x, dm81xx support only 32-bit read operation */
6243e457371STony Lindgren static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
6253e457371STony Lindgren {
6263e457371STony Lindgren 	void __iomem *fifo = hw_ep->fifo;
6273e457371STony Lindgren 
6283e457371STony Lindgren 	if (len >= 4) {
629d30323f8STony Lindgren 		ioread32_rep(fifo, dst, len >> 2);
6303e457371STony Lindgren 		dst += len & ~0x03;
6313e457371STony Lindgren 		len &= 0x03;
6323e457371STony Lindgren 	}
6333e457371STony Lindgren 
6343e457371STony Lindgren 	/* Read any remaining 1 to 3 bytes */
6353e457371STony Lindgren 	if (len > 0) {
6363e457371STony Lindgren 		u32 val = musb_readl(fifo, 0);
6373e457371STony Lindgren 		memcpy(dst, &val, len);
6383e457371STony Lindgren 	}
6393e457371STony Lindgren }
6403e457371STony Lindgren 
64125534828SAlexandre Bailon #ifdef CONFIG_USB_TI_CPPI41_DMA
64225534828SAlexandre Bailon static void dsps_dma_controller_callback(struct dma_controller *c)
64325534828SAlexandre Bailon {
64425534828SAlexandre Bailon 	struct musb *musb = c->musb;
64525534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
64625534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
64725534828SAlexandre Bailon 	u32 status;
64825534828SAlexandre Bailon 
64925534828SAlexandre Bailon 	status = musb_readl(usbss_base, USBSS_IRQ_STATUS);
65025534828SAlexandre Bailon 	if (status & USBSS_IRQ_PD_COMP)
65125534828SAlexandre Bailon 		musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP);
65225534828SAlexandre Bailon }
65325534828SAlexandre Bailon 
65425534828SAlexandre Bailon static struct dma_controller *
65525534828SAlexandre Bailon dsps_dma_controller_create(struct musb *musb, void __iomem *base)
65625534828SAlexandre Bailon {
65725534828SAlexandre Bailon 	struct dma_controller *controller;
65825534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
65925534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
66025534828SAlexandre Bailon 
66125534828SAlexandre Bailon 	controller = cppi41_dma_controller_create(musb, base);
66225534828SAlexandre Bailon 	if (IS_ERR_OR_NULL(controller))
66325534828SAlexandre Bailon 		return controller;
66425534828SAlexandre Bailon 
66525534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
66625534828SAlexandre Bailon 	controller->dma_callback = dsps_dma_controller_callback;
66725534828SAlexandre Bailon 
66825534828SAlexandre Bailon 	return controller;
66925534828SAlexandre Bailon }
67025534828SAlexandre Bailon 
67125534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
67225534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue)
67325534828SAlexandre Bailon {
67425534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
67525534828SAlexandre Bailon 
67625534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
67725534828SAlexandre Bailon }
67825534828SAlexandre Bailon 
67925534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue)
68025534828SAlexandre Bailon {
68125534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
68225534828SAlexandre Bailon 
68325534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
68425534828SAlexandre Bailon }
68525534828SAlexandre Bailon #endif
68625534828SAlexandre Bailon #else /* CONFIG_USB_TI_CPPI41_DMA */
68725534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
68825534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue) {}
68925534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue) {}
69025534828SAlexandre Bailon #endif
69125534828SAlexandre Bailon #endif /* CONFIG_USB_TI_CPPI41_DMA */
69225534828SAlexandre Bailon 
6939ecb8875SAjay Kumar Gupta static struct musb_platform_ops dsps_ops = {
694f8e9f34fSTony Lindgren 	.quirks		= MUSB_DMA_CPPI41 | MUSB_INDEXED_EP,
6959ecb8875SAjay Kumar Gupta 	.init		= dsps_musb_init,
6969ecb8875SAjay Kumar Gupta 	.exit		= dsps_musb_exit,
6979ecb8875SAjay Kumar Gupta 
6987f6283edSTony Lindgren #ifdef CONFIG_USB_TI_CPPI41_DMA
69925534828SAlexandre Bailon 	.dma_init	= dsps_dma_controller_create,
700783f3b4eSBin Liu 	.dma_exit	= cppi41_dma_controller_destroy,
7017f6283edSTony Lindgren #endif
7029ecb8875SAjay Kumar Gupta 	.enable		= dsps_musb_enable,
7039ecb8875SAjay Kumar Gupta 	.disable	= dsps_musb_disable,
7049ecb8875SAjay Kumar Gupta 
705943c1397SFelipe Balbi 	.set_mode	= dsps_musb_set_mode,
706b28a6432SFelipe Balbi 	.recover	= dsps_musb_recover,
707c48400baSBin Liu 	.clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
7089ecb8875SAjay Kumar Gupta };
7099ecb8875SAjay Kumar Gupta 
7109ecb8875SAjay Kumar Gupta static u64 musb_dmamask = DMA_BIT_MASK(32);
7119ecb8875SAjay Kumar Gupta 
71297238b35SSebastian Andrzej Siewior static int get_int_prop(struct device_node *dn, const char *s)
7139ecb8875SAjay Kumar Gupta {
71497238b35SSebastian Andrzej Siewior 	int ret;
71597238b35SSebastian Andrzej Siewior 	u32 val;
71697238b35SSebastian Andrzej Siewior 
71797238b35SSebastian Andrzej Siewior 	ret = of_property_read_u32(dn, s, &val);
71897238b35SSebastian Andrzej Siewior 	if (ret)
71997238b35SSebastian Andrzej Siewior 		return 0;
72097238b35SSebastian Andrzej Siewior 	return val;
72197238b35SSebastian Andrzej Siewior }
72297238b35SSebastian Andrzej Siewior 
72397238b35SSebastian Andrzej Siewior static int dsps_create_musb_pdev(struct dsps_glue *glue,
72497238b35SSebastian Andrzej Siewior 		struct platform_device *parent)
72597238b35SSebastian Andrzej Siewior {
72697238b35SSebastian Andrzej Siewior 	struct musb_hdrc_platform_data pdata;
72797238b35SSebastian Andrzej Siewior 	struct resource	resources[2];
728c031a7d4SSebastian Andrzej Siewior 	struct resource	*res;
72997238b35SSebastian Andrzej Siewior 	struct device *dev = &parent->dev;
73065145677SAjay Kumar Gupta 	struct musb_hdrc_config	*config;
7319ecb8875SAjay Kumar Gupta 	struct platform_device *musb;
73297238b35SSebastian Andrzej Siewior 	struct device_node *dn = parent->dev.of_node;
733606bf4d5STony Lindgren 	int ret, val;
7349ecb8875SAjay Kumar Gupta 
73597238b35SSebastian Andrzej Siewior 	memset(resources, 0, sizeof(resources));
736c031a7d4SSebastian Andrzej Siewior 	res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc");
737c031a7d4SSebastian Andrzej Siewior 	if (!res) {
73897238b35SSebastian Andrzej Siewior 		dev_err(dev, "failed to get memory.\n");
739c031a7d4SSebastian Andrzej Siewior 		return -EINVAL;
7409ecb8875SAjay Kumar Gupta 	}
741c031a7d4SSebastian Andrzej Siewior 	resources[0] = *res;
74297238b35SSebastian Andrzej Siewior 
743ce1d37cbSLad Prabhakar 	ret = platform_get_irq_byname(parent, "mc");
744ce1d37cbSLad Prabhakar 	if (ret < 0)
745ce1d37cbSLad Prabhakar 		return ret;
746ce1d37cbSLad Prabhakar 
747ce1d37cbSLad Prabhakar 	resources[1].start = ret;
748ce1d37cbSLad Prabhakar 	resources[1].end = ret;
749ce1d37cbSLad Prabhakar 	resources[1].flags = IORESOURCE_IRQ | irq_get_trigger_type(ret);
750ce1d37cbSLad Prabhakar 	resources[1].name = "mc";
7519ecb8875SAjay Kumar Gupta 
75265b3d52dSB, Ravi 	/* allocate the child platform device */
75345abfa68SBin Liu 	musb = platform_device_alloc("musb-hdrc",
75445abfa68SBin Liu 			(resources[0].start & 0xFFF) == 0x400 ? 0 : 1);
75565b3d52dSB, Ravi 	if (!musb) {
75665b3d52dSB, Ravi 		dev_err(dev, "failed to allocate musb device\n");
75797238b35SSebastian Andrzej Siewior 		return -ENOMEM;
75865b3d52dSB, Ravi 	}
7599ecb8875SAjay Kumar Gupta 
7609ecb8875SAjay Kumar Gupta 	musb->dev.parent		= dev;
7619ecb8875SAjay Kumar Gupta 	musb->dev.dma_mask		= &musb_dmamask;
7629ecb8875SAjay Kumar Gupta 	musb->dev.coherent_dma_mask	= musb_dmamask;
76349484abdSJohan Hovold 	device_set_of_node_from_dev(&musb->dev, &parent->dev);
7649ecb8875SAjay Kumar Gupta 
76597238b35SSebastian Andrzej Siewior 	glue->musb = musb;
7669ecb8875SAjay Kumar Gupta 
76797238b35SSebastian Andrzej Siewior 	ret = platform_device_add_resources(musb, resources,
76897238b35SSebastian Andrzej Siewior 			ARRAY_SIZE(resources));
7699ecb8875SAjay Kumar Gupta 	if (ret) {
7709ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add resources\n");
77197238b35SSebastian Andrzej Siewior 		goto err;
7729ecb8875SAjay Kumar Gupta 	}
7739ecb8875SAjay Kumar Gupta 
77497238b35SSebastian Andrzej Siewior 	config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL);
77565145677SAjay Kumar Gupta 	if (!config) {
776b25e5f1cSWei Yongjun 		ret = -ENOMEM;
77797238b35SSebastian Andrzej Siewior 		goto err;
77865145677SAjay Kumar Gupta 	}
77997238b35SSebastian Andrzej Siewior 	pdata.config = config;
78097238b35SSebastian Andrzej Siewior 	pdata.platform_ops = &dsps_ops;
78165145677SAjay Kumar Gupta 
782c031a7d4SSebastian Andrzej Siewior 	config->num_eps = get_int_prop(dn, "mentor,num-eps");
783c031a7d4SSebastian Andrzej Siewior 	config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
784869c5978SDaniel Mack 	config->host_port_deassert_reset_at_resume = 1;
78555479956SBin Liu 	pdata.mode = musb_get_mode(dev);
786c031a7d4SSebastian Andrzej Siewior 	/* DT keeps this entry in mA, musb expects it as per USB spec */
787c031a7d4SSebastian Andrzej Siewior 	pdata.power = get_int_prop(dn, "mentor,power") / 2;
788606bf4d5STony Lindgren 
789606bf4d5STony Lindgren 	ret = of_property_read_u32(dn, "mentor,multipoint", &val);
790606bf4d5STony Lindgren 	if (!ret && val)
791606bf4d5STony Lindgren 		config->multipoint = true;
79265145677SAjay Kumar Gupta 
79363863b98SHeikki Krogerus 	config->maximum_speed = usb_get_maximum_speed(&parent->dev);
79441932b9bSBin Liu 	switch (config->maximum_speed) {
79541932b9bSBin Liu 	case USB_SPEED_LOW:
79641932b9bSBin Liu 	case USB_SPEED_FULL:
79741932b9bSBin Liu 		break;
79841932b9bSBin Liu 	case USB_SPEED_SUPER:
79941932b9bSBin Liu 		dev_warn(dev, "ignore incorrect maximum_speed "
80041932b9bSBin Liu 				"(super-speed) setting in dts");
801df561f66SGustavo A. R. Silva 		fallthrough;
80241932b9bSBin Liu 	default:
80341932b9bSBin Liu 		config->maximum_speed = USB_SPEED_HIGH;
80441932b9bSBin Liu 	}
80541932b9bSBin Liu 
80697238b35SSebastian Andrzej Siewior 	ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
8079ecb8875SAjay Kumar Gupta 	if (ret) {
8089ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add platform_data\n");
80997238b35SSebastian Andrzej Siewior 		goto err;
8109ecb8875SAjay Kumar Gupta 	}
8119ecb8875SAjay Kumar Gupta 
8129ecb8875SAjay Kumar Gupta 	ret = platform_device_add(musb);
8139ecb8875SAjay Kumar Gupta 	if (ret) {
8149ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to register musb device\n");
81597238b35SSebastian Andrzej Siewior 		goto err;
8169ecb8875SAjay Kumar Gupta 	}
8179ecb8875SAjay Kumar Gupta 	return 0;
8189ecb8875SAjay Kumar Gupta 
81997238b35SSebastian Andrzej Siewior err:
8209ecb8875SAjay Kumar Gupta 	platform_device_put(musb);
8219ecb8875SAjay Kumar Gupta 	return ret;
8229ecb8875SAjay Kumar Gupta }
8239ecb8875SAjay Kumar Gupta 
824369469a9STony Lindgren static irqreturn_t dsps_vbus_threaded_irq(int irq, void *priv)
825369469a9STony Lindgren {
826369469a9STony Lindgren 	struct dsps_glue *glue = priv;
827369469a9STony Lindgren 	struct musb *musb = platform_get_drvdata(glue->musb);
828369469a9STony Lindgren 
829369469a9STony Lindgren 	if (!musb)
830369469a9STony Lindgren 		return IRQ_NONE;
831369469a9STony Lindgren 
832369469a9STony Lindgren 	dev_dbg(glue->dev, "VBUS interrupt\n");
833369469a9STony Lindgren 	dsps_mod_timer(glue, 0);
834369469a9STony Lindgren 
835369469a9STony Lindgren 	return IRQ_HANDLED;
836369469a9STony Lindgren }
837369469a9STony Lindgren 
838369469a9STony Lindgren static int dsps_setup_optional_vbus_irq(struct platform_device *pdev,
839369469a9STony Lindgren 					struct dsps_glue *glue)
840369469a9STony Lindgren {
841369469a9STony Lindgren 	int error;
842369469a9STony Lindgren 
843369469a9STony Lindgren 	glue->vbus_irq = platform_get_irq_byname(pdev, "vbus");
844369469a9STony Lindgren 	if (glue->vbus_irq == -EPROBE_DEFER)
845369469a9STony Lindgren 		return -EPROBE_DEFER;
846369469a9STony Lindgren 
847369469a9STony Lindgren 	if (glue->vbus_irq <= 0) {
848369469a9STony Lindgren 		glue->vbus_irq = 0;
849369469a9STony Lindgren 		return 0;
850369469a9STony Lindgren 	}
851369469a9STony Lindgren 
852369469a9STony Lindgren 	error = devm_request_threaded_irq(glue->dev, glue->vbus_irq,
853369469a9STony Lindgren 					  NULL, dsps_vbus_threaded_irq,
854369469a9STony Lindgren 					  IRQF_ONESHOT,
855369469a9STony Lindgren 					  "vbus", glue);
856369469a9STony Lindgren 	if (error) {
857369469a9STony Lindgren 		glue->vbus_irq = 0;
858369469a9STony Lindgren 		return error;
859369469a9STony Lindgren 	}
860369469a9STony Lindgren 	dev_dbg(glue->dev, "VBUS irq %i configured\n", glue->vbus_irq);
861369469a9STony Lindgren 
862369469a9STony Lindgren 	return 0;
863369469a9STony Lindgren }
864369469a9STony Lindgren 
86541ac7b3aSBill Pemberton static int dsps_probe(struct platform_device *pdev)
8669ecb8875SAjay Kumar Gupta {
86765145677SAjay Kumar Gupta 	const struct of_device_id *match;
86865145677SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp;
8699ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue;
87097238b35SSebastian Andrzej Siewior 	int ret;
8719ecb8875SAjay Kumar Gupta 
8724fc4b274SSebastian Andrzej Siewior 	if (!strcmp(pdev->name, "musb-hdrc"))
8734fc4b274SSebastian Andrzej Siewior 		return -ENODEV;
8744fc4b274SSebastian Andrzej Siewior 
875cc506036SFelipe Balbi 	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
87665145677SAjay Kumar Gupta 	if (!match) {
87765145677SAjay Kumar Gupta 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
87897238b35SSebastian Andrzej Siewior 		return -EINVAL;
87965145677SAjay Kumar Gupta 	}
88065145677SAjay Kumar Gupta 	wrp = match->data;
8819ecb8875SAjay Kumar Gupta 
8823e457371STony Lindgren 	if (of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816"))
8833e457371STony Lindgren 		dsps_ops.read_fifo = dsps_read_fifo32;
8843e457371STony Lindgren 
8859ecb8875SAjay Kumar Gupta 	/* allocate glue */
886de9db572SMarkus Pargmann 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
8870816ea2fSPeter Chen 	if (!glue)
88897238b35SSebastian Andrzej Siewior 		return -ENOMEM;
8899ecb8875SAjay Kumar Gupta 
8909ecb8875SAjay Kumar Gupta 	glue->dev = &pdev->dev;
89197238b35SSebastian Andrzej Siewior 	glue->wrp = wrp;
89225534828SAlexandre Bailon 	glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0);
89325534828SAlexandre Bailon 	if (!glue->usbss_base)
89425534828SAlexandre Bailon 		return -ENXIO;
8959ecb8875SAjay Kumar Gupta 
8969ecb8875SAjay Kumar Gupta 	platform_set_drvdata(pdev, glue);
8979ecb8875SAjay Kumar Gupta 	pm_runtime_enable(&pdev->dev);
89897238b35SSebastian Andrzej Siewior 	ret = dsps_create_musb_pdev(glue, pdev);
89997238b35SSebastian Andrzej Siewior 	if (ret)
90024752917STony Lindgren 		goto err;
90165b3f50eSTony Lindgren 
9027c75bde3SNadezda Lutovinova 	if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
9037c75bde3SNadezda Lutovinova 		ret = dsps_setup_optional_vbus_irq(pdev, glue);
9047c75bde3SNadezda Lutovinova 		if (ret)
905c2115b2bSMiquel Raynal 			goto unregister_pdev;
9067c75bde3SNadezda Lutovinova 	}
9077c75bde3SNadezda Lutovinova 
9089ecb8875SAjay Kumar Gupta 	return 0;
9099ecb8875SAjay Kumar Gupta 
910c2115b2bSMiquel Raynal unregister_pdev:
911c2115b2bSMiquel Raynal 	platform_device_unregister(glue->musb);
91224752917STony Lindgren err:
9130e38c4edSAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
9146b7ad496SBin Liu 	iounmap(glue->usbss_base);
9159ecb8875SAjay Kumar Gupta 	return ret;
9169ecb8875SAjay Kumar Gupta }
91797238b35SSebastian Andrzej Siewior 
918*e6547b5eSUwe Kleine-König static void dsps_remove(struct platform_device *pdev)
9199ecb8875SAjay Kumar Gupta {
9209ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
9219ecb8875SAjay Kumar Gupta 
92297238b35SSebastian Andrzej Siewior 	platform_device_unregister(glue->musb);
9239ecb8875SAjay Kumar Gupta 
9249ecb8875SAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
9256b7ad496SBin Liu 	iounmap(glue->usbss_base);
9269ecb8875SAjay Kumar Gupta }
9279ecb8875SAjay Kumar Gupta 
928fa7b4ca5SSebastian Andrzej Siewior static const struct dsps_musb_wrapper am33xx_driver_data = {
9299ecb8875SAjay Kumar Gupta 	.revision		= 0x00,
9309ecb8875SAjay Kumar Gupta 	.control		= 0x14,
9319ecb8875SAjay Kumar Gupta 	.status			= 0x18,
9329ecb8875SAjay Kumar Gupta 	.epintr_set		= 0x38,
9339ecb8875SAjay Kumar Gupta 	.epintr_clear		= 0x40,
9349ecb8875SAjay Kumar Gupta 	.epintr_status		= 0x30,
9359ecb8875SAjay Kumar Gupta 	.coreintr_set		= 0x3c,
9369ecb8875SAjay Kumar Gupta 	.coreintr_clear		= 0x44,
9379ecb8875SAjay Kumar Gupta 	.coreintr_status	= 0x34,
9389ecb8875SAjay Kumar Gupta 	.phy_utmi		= 0xe0,
9399ecb8875SAjay Kumar Gupta 	.mode			= 0xe8,
940b991f9b7SDaniel Mack 	.tx_mode		= 0x70,
941b991f9b7SDaniel Mack 	.rx_mode		= 0x74,
9429ecb8875SAjay Kumar Gupta 	.reset			= 0,
9439ecb8875SAjay Kumar Gupta 	.otg_disable		= 21,
9449ecb8875SAjay Kumar Gupta 	.iddig			= 8,
945943c1397SFelipe Balbi 	.iddig_mux		= 7,
9469ecb8875SAjay Kumar Gupta 	.usb_shift		= 0,
9479ecb8875SAjay Kumar Gupta 	.usb_mask		= 0x1ff,
9489ecb8875SAjay Kumar Gupta 	.usb_bitmap		= (0x1ff << 0),
9499ecb8875SAjay Kumar Gupta 	.drvvbus		= 8,
9509ecb8875SAjay Kumar Gupta 	.txep_shift		= 0,
9519ecb8875SAjay Kumar Gupta 	.txep_mask		= 0xffff,
9529ecb8875SAjay Kumar Gupta 	.txep_bitmap		= (0xffff << 0),
9539ecb8875SAjay Kumar Gupta 	.rxep_shift		= 16,
9549ecb8875SAjay Kumar Gupta 	.rxep_mask		= 0xfffe,
9559ecb8875SAjay Kumar Gupta 	.rxep_bitmap		= (0xfffe << 16),
9569e204d88SFelipe Balbi 	.poll_timeout		= 2000, /* ms */
9579ecb8875SAjay Kumar Gupta };
9589ecb8875SAjay Kumar Gupta 
9592f82686eSBill Pemberton static const struct of_device_id musb_dsps_of_match[] = {
96065145677SAjay Kumar Gupta 	{ .compatible = "ti,musb-am33xx",
9613e457371STony Lindgren 		.data = &am33xx_driver_data, },
9623e457371STony Lindgren 	{ .compatible = "ti,musb-dm816",
9633e457371STony Lindgren 		.data = &am33xx_driver_data, },
9649ecb8875SAjay Kumar Gupta 	{  },
9659ecb8875SAjay Kumar Gupta };
9669ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
9679ecb8875SAjay Kumar Gupta 
9685b783983SWolfram Sang #ifdef CONFIG_PM_SLEEP
969869c5978SDaniel Mack static int dsps_suspend(struct device *dev)
970869c5978SDaniel Mack {
971869c5978SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev);
972869c5978SDaniel Mack 	const struct dsps_musb_wrapper *wrp = glue->wrp;
973869c5978SDaniel Mack 	struct musb *musb = platform_get_drvdata(glue->musb);
974f042e9cbSSebastian Andrzej Siewior 	void __iomem *mbase;
975706d61b2SJohan Hovold 	int ret;
976f042e9cbSSebastian Andrzej Siewior 
977f042e9cbSSebastian Andrzej Siewior 	if (!musb)
978f042e9cbSSebastian Andrzej Siewior 		/* This can happen if the musb device is in -EPROBE_DEFER */
979f042e9cbSSebastian Andrzej Siewior 		return 0;
980f042e9cbSSebastian Andrzej Siewior 
981706d61b2SJohan Hovold 	ret = pm_runtime_get_sync(dev);
982706d61b2SJohan Hovold 	if (ret < 0) {
983706d61b2SJohan Hovold 		pm_runtime_put_noidle(dev);
984706d61b2SJohan Hovold 		return ret;
985706d61b2SJohan Hovold 	}
986706d61b2SJohan Hovold 
987b82162bcSBin Liu 	del_timer_sync(&musb->dev_timer);
988706d61b2SJohan Hovold 
989f042e9cbSSebastian Andrzej Siewior 	mbase = musb->ctrl_base;
990086b2882SBin Liu 	glue->context.control = musb_readl(mbase, wrp->control);
991086b2882SBin Liu 	glue->context.epintr = musb_readl(mbase, wrp->epintr_set);
992086b2882SBin Liu 	glue->context.coreintr = musb_readl(mbase, wrp->coreintr_set);
993086b2882SBin Liu 	glue->context.phy_utmi = musb_readl(mbase, wrp->phy_utmi);
994086b2882SBin Liu 	glue->context.mode = musb_readl(mbase, wrp->mode);
995086b2882SBin Liu 	glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode);
996086b2882SBin Liu 	glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode);
997869c5978SDaniel Mack 
99825534828SAlexandre Bailon 	dsps_dma_controller_suspend(glue);
99925534828SAlexandre Bailon 
1000869c5978SDaniel Mack 	return 0;
1001869c5978SDaniel Mack }
1002869c5978SDaniel Mack 
1003869c5978SDaniel Mack static int dsps_resume(struct device *dev)
1004869c5978SDaniel Mack {
1005869c5978SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev);
1006869c5978SDaniel Mack 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1007869c5978SDaniel Mack 	struct musb *musb = platform_get_drvdata(glue->musb);
1008f042e9cbSSebastian Andrzej Siewior 	void __iomem *mbase;
1009869c5978SDaniel Mack 
1010f042e9cbSSebastian Andrzej Siewior 	if (!musb)
1011f042e9cbSSebastian Andrzej Siewior 		return 0;
1012f042e9cbSSebastian Andrzej Siewior 
101325534828SAlexandre Bailon 	dsps_dma_controller_resume(glue);
101425534828SAlexandre Bailon 
1015f042e9cbSSebastian Andrzej Siewior 	mbase = musb->ctrl_base;
1016086b2882SBin Liu 	musb_writel(mbase, wrp->control, glue->context.control);
1017086b2882SBin Liu 	musb_writel(mbase, wrp->epintr_set, glue->context.epintr);
1018086b2882SBin Liu 	musb_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
1019086b2882SBin Liu 	musb_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
1020086b2882SBin Liu 	musb_writel(mbase, wrp->mode, glue->context.mode);
1021086b2882SBin Liu 	musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
1022086b2882SBin Liu 	musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
1023e47d9254SAntoine Tenart 	if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
10247ad76955SBin Liu 	    musb->port_mode == MUSB_OTG)
1025369469a9STony Lindgren 		dsps_mod_timer(glue, -1);
1026869c5978SDaniel Mack 
1027706d61b2SJohan Hovold 	pm_runtime_put(dev);
1028706d61b2SJohan Hovold 
1029869c5978SDaniel Mack 	return 0;
1030869c5978SDaniel Mack }
1031869c5978SDaniel Mack #endif
1032869c5978SDaniel Mack 
1033869c5978SDaniel Mack static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
1034869c5978SDaniel Mack 
10359ecb8875SAjay Kumar Gupta static struct platform_driver dsps_usbss_driver = {
10369ecb8875SAjay Kumar Gupta 	.probe		= dsps_probe,
1037*e6547b5eSUwe Kleine-König 	.remove_new     = dsps_remove,
10389ecb8875SAjay Kumar Gupta 	.driver         = {
10399ecb8875SAjay Kumar Gupta 		.name   = "musb-dsps",
1040869c5978SDaniel Mack 		.pm	= &dsps_pm_ops,
1041b432cb83SSachin Kamat 		.of_match_table	= musb_dsps_of_match,
10429ecb8875SAjay Kumar Gupta 	},
10439ecb8875SAjay Kumar Gupta };
10449ecb8875SAjay Kumar Gupta 
10459ecb8875SAjay Kumar Gupta MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
10469ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
10479ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
10489ecb8875SAjay Kumar Gupta MODULE_LICENSE("GPL v2");
10499ecb8875SAjay Kumar Gupta 
105097238b35SSebastian Andrzej Siewior module_platform_driver(dsps_usbss_driver);
1051