xref: /linux/drivers/usb/musb/musb_dsps.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
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