xref: /linux/drivers/usb/musb/musb_dsps.c (revision c2115b2b16421d93d4993f3fe4c520e91d6fe801)
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>
18ded017eeSKishon Vijay Abraham I #include <linux/err.h>
199ecb8875SAjay Kumar Gupta #include <linux/platform_device.h>
209ecb8875SAjay Kumar Gupta #include <linux/dma-mapping.h>
219ecb8875SAjay Kumar Gupta #include <linux/pm_runtime.h>
229ecb8875SAjay Kumar Gupta #include <linux/module.h>
23d7078df6SFelipe Balbi #include <linux/usb/usb_phy_generic.h>
24e8c4a7acSFelipe Balbi #include <linux/platform_data/usb-omap.h>
250f53e481SFelipe Balbi #include <linux/sizes.h>
269ecb8875SAjay Kumar Gupta 
279ecb8875SAjay Kumar Gupta #include <linux/of.h>
289ecb8875SAjay Kumar Gupta #include <linux/of_device.h>
299ecb8875SAjay Kumar Gupta #include <linux/of_address.h>
3097238b35SSebastian Andrzej Siewior #include <linux/of_irq.h>
31c031a7d4SSebastian Andrzej Siewior #include <linux/usb/of.h>
329ecb8875SAjay Kumar Gupta 
3340f099e3SMarkus Pargmann #include <linux/debugfs.h>
3440f099e3SMarkus Pargmann 
359ecb8875SAjay Kumar Gupta #include "musb_core.h"
369ecb8875SAjay Kumar Gupta 
3765145677SAjay Kumar Gupta static const struct of_device_id musb_dsps_of_match[];
3865145677SAjay Kumar Gupta 
3909e03a89SLee Jones /*
409ecb8875SAjay Kumar Gupta  * DSPS musb wrapper register offset.
419ecb8875SAjay Kumar Gupta  * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
429ecb8875SAjay Kumar Gupta  * musb ips.
439ecb8875SAjay Kumar Gupta  */
449ecb8875SAjay Kumar Gupta struct dsps_musb_wrapper {
459ecb8875SAjay Kumar Gupta 	u16	revision;
469ecb8875SAjay Kumar Gupta 	u16	control;
479ecb8875SAjay Kumar Gupta 	u16	status;
489ecb8875SAjay Kumar Gupta 	u16	epintr_set;
499ecb8875SAjay Kumar Gupta 	u16	epintr_clear;
509ecb8875SAjay Kumar Gupta 	u16	epintr_status;
519ecb8875SAjay Kumar Gupta 	u16	coreintr_set;
529ecb8875SAjay Kumar Gupta 	u16	coreintr_clear;
539ecb8875SAjay Kumar Gupta 	u16	coreintr_status;
549ecb8875SAjay Kumar Gupta 	u16	phy_utmi;
559ecb8875SAjay Kumar Gupta 	u16	mode;
56b991f9b7SDaniel Mack 	u16	tx_mode;
57b991f9b7SDaniel Mack 	u16	rx_mode;
589ecb8875SAjay Kumar Gupta 
599ecb8875SAjay Kumar Gupta 	/* bit positions for control */
609ecb8875SAjay Kumar Gupta 	unsigned	reset:5;
619ecb8875SAjay Kumar Gupta 
629ecb8875SAjay Kumar Gupta 	/* bit positions for interrupt */
639ecb8875SAjay Kumar Gupta 	unsigned	usb_shift:5;
649ecb8875SAjay Kumar Gupta 	u32		usb_mask;
659ecb8875SAjay Kumar Gupta 	u32		usb_bitmap;
669ecb8875SAjay Kumar Gupta 	unsigned	drvvbus:5;
679ecb8875SAjay Kumar Gupta 
689ecb8875SAjay Kumar Gupta 	unsigned	txep_shift:5;
699ecb8875SAjay Kumar Gupta 	u32		txep_mask;
709ecb8875SAjay Kumar Gupta 	u32		txep_bitmap;
719ecb8875SAjay Kumar Gupta 
729ecb8875SAjay Kumar Gupta 	unsigned	rxep_shift:5;
739ecb8875SAjay Kumar Gupta 	u32		rxep_mask;
749ecb8875SAjay Kumar Gupta 	u32		rxep_bitmap;
759ecb8875SAjay Kumar Gupta 
769ecb8875SAjay Kumar Gupta 	/* bit positions for phy_utmi */
779ecb8875SAjay Kumar Gupta 	unsigned	otg_disable:5;
789ecb8875SAjay Kumar Gupta 
799ecb8875SAjay Kumar Gupta 	/* bit positions for mode */
809ecb8875SAjay Kumar Gupta 	unsigned	iddig:5;
81943c1397SFelipe Balbi 	unsigned	iddig_mux:5;
829ecb8875SAjay Kumar Gupta 	/* miscellaneous stuff */
839e204d88SFelipe Balbi 	unsigned	poll_timeout;
849ecb8875SAjay Kumar Gupta };
859ecb8875SAjay Kumar Gupta 
86869c5978SDaniel Mack /*
87869c5978SDaniel Mack  * register shadow for suspend
88869c5978SDaniel Mack  */
89869c5978SDaniel Mack struct dsps_context {
90869c5978SDaniel Mack 	u32 control;
91869c5978SDaniel Mack 	u32 epintr;
92869c5978SDaniel Mack 	u32 coreintr;
93869c5978SDaniel Mack 	u32 phy_utmi;
94869c5978SDaniel Mack 	u32 mode;
95869c5978SDaniel Mack 	u32 tx_mode;
96869c5978SDaniel Mack 	u32 rx_mode;
97869c5978SDaniel Mack };
98869c5978SDaniel Mack 
9909e03a89SLee Jones /*
1009ecb8875SAjay Kumar Gupta  * DSPS glue structure.
1019ecb8875SAjay Kumar Gupta  */
1029ecb8875SAjay Kumar Gupta struct dsps_glue {
1039ecb8875SAjay Kumar Gupta 	struct device *dev;
10497238b35SSebastian Andrzej Siewior 	struct platform_device *musb;	/* child musb pdev */
1059ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
106369469a9STony Lindgren 	int vbus_irq;			/* optional vbus irq */
10797238b35SSebastian Andrzej Siewior 	unsigned long last_timer;    /* last timer data for each instance */
108371254ceSGeorge Cherian 	bool sw_babble_enabled;
10925534828SAlexandre Bailon 	void __iomem *usbss_base;
110869c5978SDaniel Mack 
111869c5978SDaniel Mack 	struct dsps_context context;
11240f099e3SMarkus Pargmann 	struct debugfs_regset32 regset;
11340f099e3SMarkus Pargmann 	struct dentry *dbgfs_root;
11440f099e3SMarkus Pargmann };
11540f099e3SMarkus Pargmann 
11640f099e3SMarkus Pargmann static const struct debugfs_reg32 dsps_musb_regs[] = {
11740f099e3SMarkus Pargmann 	{ "revision",		0x00 },
11840f099e3SMarkus Pargmann 	{ "control",		0x14 },
11940f099e3SMarkus Pargmann 	{ "status",		0x18 },
12040f099e3SMarkus Pargmann 	{ "eoi",		0x24 },
12140f099e3SMarkus Pargmann 	{ "intr0_stat",		0x30 },
12240f099e3SMarkus Pargmann 	{ "intr1_stat",		0x34 },
12340f099e3SMarkus Pargmann 	{ "intr0_set",		0x38 },
12440f099e3SMarkus Pargmann 	{ "intr1_set",		0x3c },
12540f099e3SMarkus Pargmann 	{ "txmode",		0x70 },
12640f099e3SMarkus Pargmann 	{ "rxmode",		0x74 },
12740f099e3SMarkus Pargmann 	{ "autoreq",		0xd0 },
12840f099e3SMarkus Pargmann 	{ "srpfixtime",		0xd4 },
12940f099e3SMarkus Pargmann 	{ "tdown",		0xd8 },
13040f099e3SMarkus Pargmann 	{ "phy_utmi",		0xe0 },
13140f099e3SMarkus Pargmann 	{ "mode",		0xe8 },
1329ecb8875SAjay Kumar Gupta };
1339ecb8875SAjay Kumar Gupta 
134369469a9STony Lindgren static void dsps_mod_timer(struct dsps_glue *glue, int wait_ms)
135369469a9STony Lindgren {
136b82162bcSBin Liu 	struct musb *musb = platform_get_drvdata(glue->musb);
137369469a9STony Lindgren 	int wait;
138369469a9STony Lindgren 
139369469a9STony Lindgren 	if (wait_ms < 0)
140369469a9STony Lindgren 		wait = msecs_to_jiffies(glue->wrp->poll_timeout);
141369469a9STony Lindgren 	else
142369469a9STony Lindgren 		wait = msecs_to_jiffies(wait_ms);
143369469a9STony Lindgren 
144b82162bcSBin Liu 	mod_timer(&musb->dev_timer, jiffies + wait);
145369469a9STony Lindgren }
146369469a9STony Lindgren 
147369469a9STony Lindgren /*
148369469a9STony Lindgren  * If no vbus irq from the PMIC is configured, we need to poll VBUS status.
149369469a9STony Lindgren  */
150369469a9STony Lindgren static void dsps_mod_timer_optional(struct dsps_glue *glue)
151369469a9STony Lindgren {
152369469a9STony Lindgren 	if (glue->vbus_irq)
153369469a9STony Lindgren 		return;
154369469a9STony Lindgren 
155369469a9STony Lindgren 	dsps_mod_timer(glue, -1);
156369469a9STony Lindgren }
157369469a9STony Lindgren 
15825534828SAlexandre Bailon /* USBSS  / USB AM335x */
15925534828SAlexandre Bailon #define USBSS_IRQ_STATUS	0x28
16025534828SAlexandre Bailon #define USBSS_IRQ_ENABLER	0x2c
16125534828SAlexandre Bailon #define USBSS_IRQ_CLEARR	0x30
16225534828SAlexandre Bailon 
16325534828SAlexandre Bailon #define USBSS_IRQ_PD_COMP	(1 << 2)
16425534828SAlexandre Bailon 
16509e03a89SLee Jones /*
1669ecb8875SAjay Kumar Gupta  * dsps_musb_enable - enable interrupts
1679ecb8875SAjay Kumar Gupta  */
1689ecb8875SAjay Kumar Gupta static void dsps_musb_enable(struct musb *musb)
1699ecb8875SAjay Kumar Gupta {
1709ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
171e823d948SKefeng Wang 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
1729ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1739ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
1749ecb8875SAjay Kumar Gupta 	u32 epmask, coremask;
1759ecb8875SAjay Kumar Gupta 
1769ecb8875SAjay Kumar Gupta 	/* Workaround: setup IRQs through both register sets. */
1779ecb8875SAjay Kumar Gupta 	epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
1789ecb8875SAjay Kumar Gupta 	       ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
1799ecb8875SAjay Kumar Gupta 	coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
1809ecb8875SAjay Kumar Gupta 
181086b2882SBin Liu 	musb_writel(reg_base, wrp->epintr_set, epmask);
182086b2882SBin Liu 	musb_writel(reg_base, wrp->coreintr_set, coremask);
18354578ee8SBin Liu 	/*
18454578ee8SBin Liu 	 * start polling for runtime PM active and idle,
18554578ee8SBin Liu 	 * and for ID change in dual-role idle mode.
18654578ee8SBin Liu 	 */
18754578ee8SBin Liu 	if (musb->xceiv->otg->state == OTG_STATE_B_IDLE)
188369469a9STony Lindgren 		dsps_mod_timer(glue, -1);
1899ecb8875SAjay Kumar Gupta }
1909ecb8875SAjay Kumar Gupta 
19109e03a89SLee Jones /*
1929ecb8875SAjay Kumar Gupta  * dsps_musb_disable - disable HDRC and flush interrupts
1939ecb8875SAjay Kumar Gupta  */
1949ecb8875SAjay Kumar Gupta static void dsps_musb_disable(struct musb *musb)
1959ecb8875SAjay Kumar Gupta {
1969ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
197e823d948SKefeng Wang 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
1989ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1999ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
2009ecb8875SAjay Kumar Gupta 
201086b2882SBin Liu 	musb_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
202086b2882SBin Liu 	musb_writel(reg_base, wrp->epintr_clear,
2039ecb8875SAjay Kumar Gupta 			 wrp->txep_bitmap | wrp->rxep_bitmap);
204b82162bcSBin Liu 	del_timer_sync(&musb->dev_timer);
2059ecb8875SAjay Kumar Gupta }
2069ecb8875SAjay Kumar Gupta 
207ea2f35c0STony Lindgren /* Caller must take musb->lock */
208ea2f35c0STony Lindgren static int dsps_check_status(struct musb *musb, void *unused)
2099ecb8875SAjay Kumar Gupta {
2109ecb8875SAjay Kumar Gupta 	void __iomem *mregs = musb->mregs;
2119ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
212db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
2139ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
2149ecb8875SAjay Kumar Gupta 	u8 devctl;
2150f901c98SSebastian Andrzej Siewior 	int skip_session = 0;
2169ecb8875SAjay Kumar Gupta 
217369469a9STony Lindgren 	if (glue->vbus_irq)
218b82162bcSBin Liu 		del_timer(&musb->dev_timer);
219369469a9STony Lindgren 
2209ecb8875SAjay Kumar Gupta 	/*
2219ecb8875SAjay Kumar Gupta 	 * We poll because DSPS IP's won't expose several OTG-critical
2229ecb8875SAjay Kumar Gupta 	 * status change events (from the transceiver) otherwise.
2239ecb8875SAjay Kumar Gupta 	 */
224086b2882SBin Liu 	devctl = musb_readb(mregs, MUSB_DEVCTL);
2259ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
226e47d9254SAntoine Tenart 				usb_otg_state_string(musb->xceiv->otg->state));
2279ecb8875SAjay Kumar Gupta 
228e47d9254SAntoine Tenart 	switch (musb->xceiv->otg->state) {
2292f3fd2c5STony Lindgren 	case OTG_STATE_A_WAIT_VRISE:
2306010abf2SBin Liu 		if (musb->port_mode == MUSB_HOST) {
2316010abf2SBin Liu 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
232369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
2332f3fd2c5STony Lindgren 			break;
2346010abf2SBin Liu 		}
235df561f66SGustavo A. R. Silva 		fallthrough;
2366010abf2SBin Liu 
2379ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_BCON:
238b3addcf0SBin Liu 		/* keep VBUS on for host-only mode */
2397ad76955SBin Liu 		if (musb->port_mode == MUSB_HOST) {
240b3addcf0SBin Liu 			dsps_mod_timer_optional(glue);
241b3addcf0SBin Liu 			break;
242b3addcf0SBin Liu 		}
243086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
2440f901c98SSebastian Andrzej Siewior 		skip_session = 1;
245df561f66SGustavo A. R. Silva 		fallthrough;
2469ecb8875SAjay Kumar Gupta 
2470f901c98SSebastian Andrzej Siewior 	case OTG_STATE_A_IDLE:
2480f901c98SSebastian Andrzej Siewior 	case OTG_STATE_B_IDLE:
249369469a9STony Lindgren 		if (!glue->vbus_irq) {
2509ecb8875SAjay Kumar Gupta 			if (devctl & MUSB_DEVCTL_BDEVICE) {
251e47d9254SAntoine Tenart 				musb->xceiv->otg->state = OTG_STATE_B_IDLE;
2529ecb8875SAjay Kumar Gupta 				MUSB_DEV_MODE(musb);
2539ecb8875SAjay Kumar Gupta 			} else {
254e47d9254SAntoine Tenart 				musb->xceiv->otg->state = OTG_STATE_A_IDLE;
2559ecb8875SAjay Kumar Gupta 				MUSB_HST_MODE(musb);
2569ecb8875SAjay Kumar Gupta 			}
25754578ee8SBin Liu 
25854578ee8SBin Liu 			if (musb->port_mode == MUSB_PERIPHERAL)
25954578ee8SBin Liu 				skip_session = 1;
26054578ee8SBin Liu 
2610f901c98SSebastian Andrzej Siewior 			if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
262369469a9STony Lindgren 				musb_writeb(mregs, MUSB_DEVCTL,
263369469a9STony Lindgren 					    MUSB_DEVCTL_SESSION);
264369469a9STony Lindgren 		}
265369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
2669ecb8875SAjay Kumar Gupta 		break;
2679ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_VFALL:
268e47d9254SAntoine Tenart 		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
269086b2882SBin Liu 		musb_writel(musb->ctrl_base, wrp->coreintr_set,
2709ecb8875SAjay Kumar Gupta 			    MUSB_INTR_VBUSERROR << wrp->usb_shift);
2719ecb8875SAjay Kumar Gupta 		break;
2729ecb8875SAjay Kumar Gupta 	default:
2739ecb8875SAjay Kumar Gupta 		break;
2749ecb8875SAjay Kumar Gupta 	}
27565b3f50eSTony Lindgren 
276ea2f35c0STony Lindgren 	return 0;
277ea2f35c0STony Lindgren }
278ea2f35c0STony Lindgren 
27905678497SKees Cook static void otg_timer(struct timer_list *t)
280ea2f35c0STony Lindgren {
281b82162bcSBin Liu 	struct musb *musb = from_timer(musb, t, dev_timer);
282ea2f35c0STony Lindgren 	struct device *dev = musb->controller;
283ea2f35c0STony Lindgren 	unsigned long flags;
284ea2f35c0STony Lindgren 	int err;
285ea2f35c0STony Lindgren 
286ea2f35c0STony Lindgren 	err = pm_runtime_get(dev);
287ea2f35c0STony Lindgren 	if ((err != -EINPROGRESS) && err < 0) {
288ea2f35c0STony Lindgren 		dev_err(dev, "Poll could not pm_runtime_get: %i\n", err);
289ea2f35c0STony Lindgren 		pm_runtime_put_noidle(dev);
290ea2f35c0STony Lindgren 
291ea2f35c0STony Lindgren 		return;
292ea2f35c0STony Lindgren 	}
293ea2f35c0STony Lindgren 
294ea2f35c0STony Lindgren 	spin_lock_irqsave(&musb->lock, flags);
295ea2f35c0STony Lindgren 	err = musb_queue_resume_work(musb, dsps_check_status, NULL);
296ea2f35c0STony Lindgren 	if (err < 0)
297ea2f35c0STony Lindgren 		dev_err(dev, "%s resume work: %i\n", __func__, err);
298ea2f35c0STony Lindgren 	spin_unlock_irqrestore(&musb->lock, flags);
29965b3f50eSTony Lindgren 	pm_runtime_mark_last_busy(dev);
30065b3f50eSTony Lindgren 	pm_runtime_put_autosuspend(dev);
3019ecb8875SAjay Kumar Gupta }
3029ecb8875SAjay Kumar Gupta 
3034ab53a69SWei Yongjun static void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum)
304c48400baSBin Liu {
305c48400baSBin Liu 	u32 epintr;
306c48400baSBin Liu 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
307c48400baSBin Liu 	const struct dsps_musb_wrapper *wrp = glue->wrp;
308c48400baSBin Liu 
309c48400baSBin Liu 	/* musb->lock might already been held */
310c48400baSBin Liu 	epintr = (1 << epnum) << wrp->rxep_shift;
311c48400baSBin Liu 	musb_writel(musb->ctrl_base, wrp->epintr_status, epintr);
312c48400baSBin Liu }
313c48400baSBin Liu 
3149ecb8875SAjay Kumar Gupta static irqreturn_t dsps_interrupt(int irq, void *hci)
3159ecb8875SAjay Kumar Gupta {
3169ecb8875SAjay Kumar Gupta 	struct musb  *musb = hci;
3179ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
3189ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
319db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
3209ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
3219ecb8875SAjay Kumar Gupta 	unsigned long flags;
3229ecb8875SAjay Kumar Gupta 	irqreturn_t ret = IRQ_NONE;
3239ecb8875SAjay Kumar Gupta 	u32 epintr, usbintr;
3249ecb8875SAjay Kumar Gupta 
3259ecb8875SAjay Kumar Gupta 	spin_lock_irqsave(&musb->lock, flags);
3269ecb8875SAjay Kumar Gupta 
3279ecb8875SAjay Kumar Gupta 	/* Get endpoint interrupts */
328086b2882SBin Liu 	epintr = musb_readl(reg_base, wrp->epintr_status);
3299ecb8875SAjay Kumar Gupta 	musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
3309ecb8875SAjay Kumar Gupta 	musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
3319ecb8875SAjay Kumar Gupta 
3329ecb8875SAjay Kumar Gupta 	if (epintr)
333086b2882SBin Liu 		musb_writel(reg_base, wrp->epintr_status, epintr);
3349ecb8875SAjay Kumar Gupta 
3359ecb8875SAjay Kumar Gupta 	/* Get usb core interrupts */
336086b2882SBin Liu 	usbintr = musb_readl(reg_base, wrp->coreintr_status);
3379ecb8875SAjay Kumar Gupta 	if (!usbintr && !epintr)
3389be73baeSSebastian Andrzej Siewior 		goto out;
3399ecb8875SAjay Kumar Gupta 
3409ecb8875SAjay Kumar Gupta 	musb->int_usb =	(usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
3419ecb8875SAjay Kumar Gupta 	if (usbintr)
342086b2882SBin Liu 		musb_writel(reg_base, wrp->coreintr_status, usbintr);
3439ecb8875SAjay Kumar Gupta 
3449ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
3459ecb8875SAjay Kumar Gupta 			usbintr, epintr);
3461d57de30SDaniel Mack 
3479ecb8875SAjay Kumar Gupta 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
348086b2882SBin Liu 		int drvvbus = musb_readl(reg_base, wrp->status);
3499ecb8875SAjay Kumar Gupta 		void __iomem *mregs = musb->mregs;
350086b2882SBin Liu 		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
3519ecb8875SAjay Kumar Gupta 		int err;
3529ecb8875SAjay Kumar Gupta 
353032ec49fSFelipe Balbi 		err = musb->int_usb & MUSB_INTR_VBUSERROR;
3549ecb8875SAjay Kumar Gupta 		if (err) {
3559ecb8875SAjay Kumar Gupta 			/*
3569ecb8875SAjay Kumar Gupta 			 * The Mentor core doesn't debounce VBUS as needed
3579ecb8875SAjay Kumar Gupta 			 * to cope with device connect current spikes. This
3589ecb8875SAjay Kumar Gupta 			 * means it's not uncommon for bus-powered devices
3599ecb8875SAjay Kumar Gupta 			 * to get VBUS errors during enumeration.
3609ecb8875SAjay Kumar Gupta 			 *
3619ecb8875SAjay Kumar Gupta 			 * This is a workaround, but newer RTL from Mentor
3629ecb8875SAjay Kumar Gupta 			 * seems to allow a better one: "re"-starting sessions
3639ecb8875SAjay Kumar Gupta 			 * without waiting for VBUS to stop registering in
3649ecb8875SAjay Kumar Gupta 			 * devctl.
3659ecb8875SAjay Kumar Gupta 			 */
3669ecb8875SAjay Kumar Gupta 			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
367e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
368369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
3699ecb8875SAjay Kumar Gupta 			WARNING("VBUS error workaround (delay coming)\n");
370032ec49fSFelipe Balbi 		} else if (drvvbus) {
3719ecb8875SAjay Kumar Gupta 			MUSB_HST_MODE(musb);
372e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
373369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
3749ecb8875SAjay Kumar Gupta 		} else {
3759ecb8875SAjay Kumar Gupta 			musb->is_active = 0;
3769ecb8875SAjay Kumar Gupta 			MUSB_DEV_MODE(musb);
377e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_B_IDLE;
3789ecb8875SAjay Kumar Gupta 		}
3799ecb8875SAjay Kumar Gupta 
3809ecb8875SAjay Kumar Gupta 		/* NOTE: this must complete power-on within 100 ms. */
3819ecb8875SAjay Kumar Gupta 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
3829ecb8875SAjay Kumar Gupta 				drvvbus ? "on" : "off",
383e47d9254SAntoine Tenart 				usb_otg_state_string(musb->xceiv->otg->state),
3849ecb8875SAjay Kumar Gupta 				err ? " ERROR" : "",
3859ecb8875SAjay Kumar Gupta 				devctl);
3869ecb8875SAjay Kumar Gupta 		ret = IRQ_HANDLED;
3879ecb8875SAjay Kumar Gupta 	}
3889ecb8875SAjay Kumar Gupta 
3899ecb8875SAjay Kumar Gupta 	if (musb->int_tx || musb->int_rx || musb->int_usb)
3909ecb8875SAjay Kumar Gupta 		ret |= musb_interrupt(musb);
3919ecb8875SAjay Kumar Gupta 
3922f3fd2c5STony Lindgren 	/* Poll for ID change and connect */
3932f3fd2c5STony Lindgren 	switch (musb->xceiv->otg->state) {
3942f3fd2c5STony Lindgren 	case OTG_STATE_B_IDLE:
3952f3fd2c5STony Lindgren 	case OTG_STATE_A_WAIT_BCON:
396369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
3972f3fd2c5STony Lindgren 		break;
3982f3fd2c5STony Lindgren 	default:
3992f3fd2c5STony Lindgren 		break;
4002f3fd2c5STony Lindgren 	}
4012f3fd2c5STony Lindgren 
4029be73baeSSebastian Andrzej Siewior out:
4039ecb8875SAjay Kumar Gupta 	spin_unlock_irqrestore(&musb->lock, flags);
4049ecb8875SAjay Kumar Gupta 
4059ecb8875SAjay Kumar Gupta 	return ret;
4069ecb8875SAjay Kumar Gupta }
4079ecb8875SAjay Kumar Gupta 
40840f099e3SMarkus Pargmann static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue)
40940f099e3SMarkus Pargmann {
41040f099e3SMarkus Pargmann 	struct dentry *root;
41140f099e3SMarkus Pargmann 	char buf[128];
41240f099e3SMarkus Pargmann 
41340f099e3SMarkus Pargmann 	sprintf(buf, "%s.dsps", dev_name(musb->controller));
414b3c69ec8SChunfeng Yun 	root = debugfs_create_dir(buf, usb_debug_root);
41540f099e3SMarkus Pargmann 	glue->dbgfs_root = root;
41640f099e3SMarkus Pargmann 
41740f099e3SMarkus Pargmann 	glue->regset.regs = dsps_musb_regs;
41840f099e3SMarkus Pargmann 	glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs);
41940f099e3SMarkus Pargmann 	glue->regset.base = musb->ctrl_base;
42040f099e3SMarkus Pargmann 
4218a1ef171SGreg Kroah-Hartman 	debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset);
42240f099e3SMarkus Pargmann 	return 0;
42340f099e3SMarkus Pargmann }
42440f099e3SMarkus Pargmann 
4259ecb8875SAjay Kumar Gupta static int dsps_musb_init(struct musb *musb)
4269ecb8875SAjay Kumar Gupta {
4279ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
428db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
42997238b35SSebastian Andrzej Siewior 	struct platform_device *parent = to_platform_device(dev->parent);
4309ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
43197238b35SSebastian Andrzej Siewior 	void __iomem *reg_base;
432ffa13d2dSGeert Uytterhoeven 	struct resource *r;
4339ecb8875SAjay Kumar Gupta 	u32 rev, val;
43440f099e3SMarkus Pargmann 	int ret;
4359ecb8875SAjay Kumar Gupta 
436ffa13d2dSGeert Uytterhoeven 	r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
437ffa13d2dSGeert Uytterhoeven 	reg_base = devm_ioremap_resource(dev, r);
43851ef74f6SJulia Lawall 	if (IS_ERR(reg_base))
43951ef74f6SJulia Lawall 		return PTR_ERR(reg_base);
44097238b35SSebastian Andrzej Siewior 	musb->ctrl_base = reg_base;
4419ecb8875SAjay Kumar Gupta 
442d7554226SAfzal Mohammed 	/* NOP driver needs change if supporting dual instance */
443983f3cabSFelipe Balbi 	musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "phys", 0);
44497238b35SSebastian Andrzej Siewior 	if (IS_ERR(musb->xceiv))
44597238b35SSebastian Andrzej Siewior 		return PTR_ERR(musb->xceiv);
4469ecb8875SAjay Kumar Gupta 
447bb90600dSTony Lindgren 	musb->phy = devm_phy_get(dev->parent, "usb2-phy");
448bb90600dSTony Lindgren 
4499ecb8875SAjay Kumar Gupta 	/* Returns zero if e.g. not clocked */
450086b2882SBin Liu 	rev = musb_readl(reg_base, wrp->revision);
45197238b35SSebastian Andrzej Siewior 	if (!rev)
45297238b35SSebastian Andrzej Siewior 		return -ENODEV;
4539ecb8875SAjay Kumar Gupta 
454bb90600dSTony Lindgren 	if (IS_ERR(musb->phy))  {
455bb90600dSTony Lindgren 		musb->phy = NULL;
456bb90600dSTony Lindgren 	} else {
457bb90600dSTony Lindgren 		ret = phy_init(musb->phy);
458bb90600dSTony Lindgren 		if (ret < 0)
459bb90600dSTony Lindgren 			return ret;
460bb90600dSTony Lindgren 		ret = phy_power_on(musb->phy);
461bb90600dSTony Lindgren 		if (ret) {
462bb90600dSTony Lindgren 			phy_exit(musb->phy);
463bb90600dSTony Lindgren 			return ret;
464bb90600dSTony Lindgren 		}
465bb90600dSTony Lindgren 	}
466bb90600dSTony Lindgren 
467b82162bcSBin Liu 	timer_setup(&musb->dev_timer, otg_timer, 0);
4689ecb8875SAjay Kumar Gupta 
4699ecb8875SAjay Kumar Gupta 	/* Reset the musb */
470086b2882SBin Liu 	musb_writel(reg_base, wrp->control, (1 << wrp->reset));
4719ecb8875SAjay Kumar Gupta 
4729ecb8875SAjay Kumar Gupta 	musb->isr = dsps_interrupt;
4739ecb8875SAjay Kumar Gupta 
4749ecb8875SAjay Kumar Gupta 	/* reset the otgdisable bit, needed for host mode to work */
475086b2882SBin Liu 	val = musb_readl(reg_base, wrp->phy_utmi);
4769ecb8875SAjay Kumar Gupta 	val &= ~(1 << wrp->otg_disable);
477086b2882SBin Liu 	musb_writel(musb->ctrl_base, wrp->phy_utmi, val);
4789ecb8875SAjay Kumar Gupta 
479371254ceSGeorge Cherian 	/*
480371254ceSGeorge Cherian 	 *  Check whether the dsps version has babble control enabled.
481371254ceSGeorge Cherian 	 * In latest silicon revision the babble control logic is enabled.
482371254ceSGeorge Cherian 	 * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
483371254ceSGeorge Cherian 	 * logic enabled.
484371254ceSGeorge Cherian 	 */
485086b2882SBin Liu 	val = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
486f860f0b1SFelipe Balbi 	if (val & MUSB_BABBLE_RCV_DISABLE) {
487371254ceSGeorge Cherian 		glue->sw_babble_enabled = true;
488371254ceSGeorge Cherian 		val |= MUSB_BABBLE_SW_SESSION_CTRL;
489086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
490371254ceSGeorge Cherian 	}
491371254ceSGeorge Cherian 
492369469a9STony Lindgren 	dsps_mod_timer(glue, -1);
4932f3fd2c5STony Lindgren 
494e94a7369SSaurabh Karajgaonkar 	return dsps_musb_dbg_init(musb, glue);
4959ecb8875SAjay Kumar Gupta }
4969ecb8875SAjay Kumar Gupta 
4979ecb8875SAjay Kumar Gupta static int dsps_musb_exit(struct musb *musb)
4989ecb8875SAjay Kumar Gupta {
4999ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
500db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
5019ecb8875SAjay Kumar Gupta 
502b82162bcSBin Liu 	del_timer_sync(&musb->dev_timer);
503bb90600dSTony Lindgren 	phy_power_off(musb->phy);
504bb90600dSTony Lindgren 	phy_exit(musb->phy);
5050fca91b8SDaniel Mack 	debugfs_remove_recursive(glue->dbgfs_root);
5060fca91b8SDaniel Mack 
5079ecb8875SAjay Kumar Gupta 	return 0;
5089ecb8875SAjay Kumar Gupta }
5099ecb8875SAjay Kumar Gupta 
510943c1397SFelipe Balbi static int dsps_musb_set_mode(struct musb *musb, u8 mode)
511943c1397SFelipe Balbi {
512943c1397SFelipe Balbi 	struct device *dev = musb->controller;
513943c1397SFelipe Balbi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
514943c1397SFelipe Balbi 	const struct dsps_musb_wrapper *wrp = glue->wrp;
515943c1397SFelipe Balbi 	void __iomem *ctrl_base = musb->ctrl_base;
516943c1397SFelipe Balbi 	u32 reg;
517943c1397SFelipe Balbi 
518086b2882SBin Liu 	reg = musb_readl(ctrl_base, wrp->mode);
519943c1397SFelipe Balbi 
520943c1397SFelipe Balbi 	switch (mode) {
521943c1397SFelipe Balbi 	case MUSB_HOST:
522943c1397SFelipe Balbi 		reg &= ~(1 << wrp->iddig);
523943c1397SFelipe Balbi 
524943c1397SFelipe Balbi 		/*
525943c1397SFelipe Balbi 		 * if we're setting mode to host-only or device-only, we're
526943c1397SFelipe Balbi 		 * going to ignore whatever the PHY sends us and just force
527943c1397SFelipe Balbi 		 * ID pin status by SW
528943c1397SFelipe Balbi 		 */
529943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig_mux);
530943c1397SFelipe Balbi 
531086b2882SBin Liu 		musb_writel(ctrl_base, wrp->mode, reg);
532086b2882SBin Liu 		musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
533943c1397SFelipe Balbi 		break;
534943c1397SFelipe Balbi 	case MUSB_PERIPHERAL:
535943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig);
536943c1397SFelipe Balbi 
537943c1397SFelipe Balbi 		/*
538943c1397SFelipe Balbi 		 * if we're setting mode to host-only or device-only, we're
539943c1397SFelipe Balbi 		 * going to ignore whatever the PHY sends us and just force
540943c1397SFelipe Balbi 		 * ID pin status by SW
541943c1397SFelipe Balbi 		 */
542943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig_mux);
543943c1397SFelipe Balbi 
544086b2882SBin Liu 		musb_writel(ctrl_base, wrp->mode, reg);
545943c1397SFelipe Balbi 		break;
546943c1397SFelipe Balbi 	case MUSB_OTG:
547086b2882SBin Liu 		musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
548943c1397SFelipe Balbi 		break;
549943c1397SFelipe Balbi 	default:
550943c1397SFelipe Balbi 		dev_err(glue->dev, "unsupported mode %d\n", mode);
551943c1397SFelipe Balbi 		return -EINVAL;
552943c1397SFelipe Balbi 	}
553943c1397SFelipe Balbi 
554943c1397SFelipe Balbi 	return 0;
555943c1397SFelipe Balbi }
556943c1397SFelipe Balbi 
5573709ffcaSFelipe Balbi static bool dsps_sw_babble_control(struct musb *musb)
558371254ceSGeorge Cherian {
559371254ceSGeorge Cherian 	u8 babble_ctl;
560371254ceSGeorge Cherian 	bool session_restart =  false;
561371254ceSGeorge Cherian 
562086b2882SBin Liu 	babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
563371254ceSGeorge Cherian 	dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
564371254ceSGeorge Cherian 		babble_ctl);
565371254ceSGeorge Cherian 	/*
566371254ceSGeorge Cherian 	 * check line monitor flag to check whether babble is
567371254ceSGeorge Cherian 	 * due to noise
568371254ceSGeorge Cherian 	 */
569371254ceSGeorge Cherian 	dev_dbg(musb->controller, "STUCK_J is %s\n",
570371254ceSGeorge Cherian 		babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
571371254ceSGeorge Cherian 
572371254ceSGeorge Cherian 	if (babble_ctl & MUSB_BABBLE_STUCK_J) {
573371254ceSGeorge Cherian 		int timeout = 10;
574371254ceSGeorge Cherian 
575371254ceSGeorge Cherian 		/*
576371254ceSGeorge Cherian 		 * babble is due to noise, then set transmit idle (d7 bit)
577371254ceSGeorge Cherian 		 * to resume normal operation
578371254ceSGeorge Cherian 		 */
579086b2882SBin Liu 		babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
580371254ceSGeorge Cherian 		babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
581086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
582371254ceSGeorge Cherian 
583371254ceSGeorge Cherian 		/* wait till line monitor flag cleared */
584371254ceSGeorge Cherian 		dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
585371254ceSGeorge Cherian 		do {
586086b2882SBin Liu 			babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
587371254ceSGeorge Cherian 			udelay(1);
588371254ceSGeorge Cherian 		} while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
589371254ceSGeorge Cherian 
590371254ceSGeorge Cherian 		/* check whether stuck_at_j bit cleared */
591371254ceSGeorge Cherian 		if (babble_ctl & MUSB_BABBLE_STUCK_J) {
592371254ceSGeorge Cherian 			/*
593371254ceSGeorge Cherian 			 * real babble condition has occurred
594371254ceSGeorge Cherian 			 * restart the controller to start the
595371254ceSGeorge Cherian 			 * session again
596371254ceSGeorge Cherian 			 */
597371254ceSGeorge Cherian 			dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
598371254ceSGeorge Cherian 				babble_ctl);
599371254ceSGeorge Cherian 			session_restart = true;
600371254ceSGeorge Cherian 		}
601371254ceSGeorge Cherian 	} else {
602371254ceSGeorge Cherian 		session_restart = true;
603371254ceSGeorge Cherian 	}
604371254ceSGeorge Cherian 
605371254ceSGeorge Cherian 	return session_restart;
606371254ceSGeorge Cherian }
607371254ceSGeorge Cherian 
608b28a6432SFelipe Balbi static int dsps_musb_recover(struct musb *musb)
6091d57de30SDaniel Mack {
6101d57de30SDaniel Mack 	struct device *dev = musb->controller;
6111d57de30SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
612011d0dd5SFelipe Balbi 	int session_restart = 0;
6131d57de30SDaniel Mack 
614371254ceSGeorge Cherian 	if (glue->sw_babble_enabled)
6153709ffcaSFelipe Balbi 		session_restart = dsps_sw_babble_control(musb);
616011d0dd5SFelipe Balbi 	else
617371254ceSGeorge Cherian 		session_restart = 1;
61856700178SGeorge Cherian 
619d0cddae7SFelipe Balbi 	return session_restart ? 0 : -EPIPE;
6201d57de30SDaniel Mack }
6211d57de30SDaniel Mack 
6223e457371STony Lindgren /* Similar to am35x, dm81xx support only 32-bit read operation */
6233e457371STony Lindgren static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
6243e457371STony Lindgren {
6253e457371STony Lindgren 	void __iomem *fifo = hw_ep->fifo;
6263e457371STony Lindgren 
6273e457371STony Lindgren 	if (len >= 4) {
628d30323f8STony Lindgren 		ioread32_rep(fifo, dst, len >> 2);
6293e457371STony Lindgren 		dst += len & ~0x03;
6303e457371STony Lindgren 		len &= 0x03;
6313e457371STony Lindgren 	}
6323e457371STony Lindgren 
6333e457371STony Lindgren 	/* Read any remaining 1 to 3 bytes */
6343e457371STony Lindgren 	if (len > 0) {
6353e457371STony Lindgren 		u32 val = musb_readl(fifo, 0);
6363e457371STony Lindgren 		memcpy(dst, &val, len);
6373e457371STony Lindgren 	}
6383e457371STony Lindgren }
6393e457371STony Lindgren 
64025534828SAlexandre Bailon #ifdef CONFIG_USB_TI_CPPI41_DMA
64125534828SAlexandre Bailon static void dsps_dma_controller_callback(struct dma_controller *c)
64225534828SAlexandre Bailon {
64325534828SAlexandre Bailon 	struct musb *musb = c->musb;
64425534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
64525534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
64625534828SAlexandre Bailon 	u32 status;
64725534828SAlexandre Bailon 
64825534828SAlexandre Bailon 	status = musb_readl(usbss_base, USBSS_IRQ_STATUS);
64925534828SAlexandre Bailon 	if (status & USBSS_IRQ_PD_COMP)
65025534828SAlexandre Bailon 		musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP);
65125534828SAlexandre Bailon }
65225534828SAlexandre Bailon 
65325534828SAlexandre Bailon static struct dma_controller *
65425534828SAlexandre Bailon dsps_dma_controller_create(struct musb *musb, void __iomem *base)
65525534828SAlexandre Bailon {
65625534828SAlexandre Bailon 	struct dma_controller *controller;
65725534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
65825534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
65925534828SAlexandre Bailon 
66025534828SAlexandre Bailon 	controller = cppi41_dma_controller_create(musb, base);
66125534828SAlexandre Bailon 	if (IS_ERR_OR_NULL(controller))
66225534828SAlexandre Bailon 		return controller;
66325534828SAlexandre Bailon 
66425534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
66525534828SAlexandre Bailon 	controller->dma_callback = dsps_dma_controller_callback;
66625534828SAlexandre Bailon 
66725534828SAlexandre Bailon 	return controller;
66825534828SAlexandre Bailon }
66925534828SAlexandre Bailon 
67025534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
67125534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue)
67225534828SAlexandre Bailon {
67325534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
67425534828SAlexandre Bailon 
67525534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
67625534828SAlexandre Bailon }
67725534828SAlexandre Bailon 
67825534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue)
67925534828SAlexandre Bailon {
68025534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
68125534828SAlexandre Bailon 
68225534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
68325534828SAlexandre Bailon }
68425534828SAlexandre Bailon #endif
68525534828SAlexandre Bailon #else /* CONFIG_USB_TI_CPPI41_DMA */
68625534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
68725534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue) {}
68825534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue) {}
68925534828SAlexandre Bailon #endif
69025534828SAlexandre Bailon #endif /* CONFIG_USB_TI_CPPI41_DMA */
69125534828SAlexandre Bailon 
6929ecb8875SAjay Kumar Gupta static struct musb_platform_ops dsps_ops = {
693f8e9f34fSTony Lindgren 	.quirks		= MUSB_DMA_CPPI41 | MUSB_INDEXED_EP,
6949ecb8875SAjay Kumar Gupta 	.init		= dsps_musb_init,
6959ecb8875SAjay Kumar Gupta 	.exit		= dsps_musb_exit,
6969ecb8875SAjay Kumar Gupta 
6977f6283edSTony Lindgren #ifdef CONFIG_USB_TI_CPPI41_DMA
69825534828SAlexandre Bailon 	.dma_init	= dsps_dma_controller_create,
699783f3b4eSBin Liu 	.dma_exit	= cppi41_dma_controller_destroy,
7007f6283edSTony Lindgren #endif
7019ecb8875SAjay Kumar Gupta 	.enable		= dsps_musb_enable,
7029ecb8875SAjay Kumar Gupta 	.disable	= dsps_musb_disable,
7039ecb8875SAjay Kumar Gupta 
704943c1397SFelipe Balbi 	.set_mode	= dsps_musb_set_mode,
705b28a6432SFelipe Balbi 	.recover	= dsps_musb_recover,
706c48400baSBin Liu 	.clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
7079ecb8875SAjay Kumar Gupta };
7089ecb8875SAjay Kumar Gupta 
7099ecb8875SAjay Kumar Gupta static u64 musb_dmamask = DMA_BIT_MASK(32);
7109ecb8875SAjay Kumar Gupta 
71197238b35SSebastian Andrzej Siewior static int get_int_prop(struct device_node *dn, const char *s)
7129ecb8875SAjay Kumar Gupta {
71397238b35SSebastian Andrzej Siewior 	int ret;
71497238b35SSebastian Andrzej Siewior 	u32 val;
71597238b35SSebastian Andrzej Siewior 
71697238b35SSebastian Andrzej Siewior 	ret = of_property_read_u32(dn, s, &val);
71797238b35SSebastian Andrzej Siewior 	if (ret)
71897238b35SSebastian Andrzej Siewior 		return 0;
71997238b35SSebastian Andrzej Siewior 	return val;
72097238b35SSebastian Andrzej Siewior }
72197238b35SSebastian Andrzej Siewior 
72297238b35SSebastian Andrzej Siewior static int dsps_create_musb_pdev(struct dsps_glue *glue,
72397238b35SSebastian Andrzej Siewior 		struct platform_device *parent)
72497238b35SSebastian Andrzej Siewior {
72597238b35SSebastian Andrzej Siewior 	struct musb_hdrc_platform_data pdata;
72697238b35SSebastian Andrzej Siewior 	struct resource	resources[2];
727c031a7d4SSebastian Andrzej Siewior 	struct resource	*res;
72897238b35SSebastian Andrzej Siewior 	struct device *dev = &parent->dev;
72965145677SAjay Kumar Gupta 	struct musb_hdrc_config	*config;
7309ecb8875SAjay Kumar Gupta 	struct platform_device *musb;
73197238b35SSebastian Andrzej Siewior 	struct device_node *dn = parent->dev.of_node;
732606bf4d5STony Lindgren 	int ret, val;
7339ecb8875SAjay Kumar Gupta 
73497238b35SSebastian Andrzej Siewior 	memset(resources, 0, sizeof(resources));
735c031a7d4SSebastian Andrzej Siewior 	res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc");
736c031a7d4SSebastian Andrzej Siewior 	if (!res) {
73797238b35SSebastian Andrzej Siewior 		dev_err(dev, "failed to get memory.\n");
738c031a7d4SSebastian Andrzej Siewior 		return -EINVAL;
7399ecb8875SAjay Kumar Gupta 	}
740c031a7d4SSebastian Andrzej Siewior 	resources[0] = *res;
74197238b35SSebastian Andrzej Siewior 
742c031a7d4SSebastian Andrzej Siewior 	res = platform_get_resource_byname(parent, IORESOURCE_IRQ, "mc");
743c031a7d4SSebastian Andrzej Siewior 	if (!res) {
74497238b35SSebastian Andrzej Siewior 		dev_err(dev, "failed to get irq.\n");
745c031a7d4SSebastian Andrzej Siewior 		return -EINVAL;
74697238b35SSebastian Andrzej Siewior 	}
747c031a7d4SSebastian Andrzej Siewior 	resources[1] = *res;
7489ecb8875SAjay Kumar Gupta 
74965b3d52dSB, Ravi 	/* allocate the child platform device */
75045abfa68SBin Liu 	musb = platform_device_alloc("musb-hdrc",
75145abfa68SBin Liu 			(resources[0].start & 0xFFF) == 0x400 ? 0 : 1);
75265b3d52dSB, Ravi 	if (!musb) {
75365b3d52dSB, Ravi 		dev_err(dev, "failed to allocate musb device\n");
75497238b35SSebastian Andrzej Siewior 		return -ENOMEM;
75565b3d52dSB, Ravi 	}
7569ecb8875SAjay Kumar Gupta 
7579ecb8875SAjay Kumar Gupta 	musb->dev.parent		= dev;
7589ecb8875SAjay Kumar Gupta 	musb->dev.dma_mask		= &musb_dmamask;
7599ecb8875SAjay Kumar Gupta 	musb->dev.coherent_dma_mask	= musb_dmamask;
76049484abdSJohan Hovold 	device_set_of_node_from_dev(&musb->dev, &parent->dev);
7619ecb8875SAjay Kumar Gupta 
76297238b35SSebastian Andrzej Siewior 	glue->musb = musb;
7639ecb8875SAjay Kumar Gupta 
76497238b35SSebastian Andrzej Siewior 	ret = platform_device_add_resources(musb, resources,
76597238b35SSebastian Andrzej Siewior 			ARRAY_SIZE(resources));
7669ecb8875SAjay Kumar Gupta 	if (ret) {
7679ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add resources\n");
76897238b35SSebastian Andrzej Siewior 		goto err;
7699ecb8875SAjay Kumar Gupta 	}
7709ecb8875SAjay Kumar Gupta 
77197238b35SSebastian Andrzej Siewior 	config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL);
77265145677SAjay Kumar Gupta 	if (!config) {
773b25e5f1cSWei Yongjun 		ret = -ENOMEM;
77497238b35SSebastian Andrzej Siewior 		goto err;
77565145677SAjay Kumar Gupta 	}
77697238b35SSebastian Andrzej Siewior 	pdata.config = config;
77797238b35SSebastian Andrzej Siewior 	pdata.platform_ops = &dsps_ops;
77865145677SAjay Kumar Gupta 
779c031a7d4SSebastian Andrzej Siewior 	config->num_eps = get_int_prop(dn, "mentor,num-eps");
780c031a7d4SSebastian Andrzej Siewior 	config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
781869c5978SDaniel Mack 	config->host_port_deassert_reset_at_resume = 1;
78255479956SBin Liu 	pdata.mode = musb_get_mode(dev);
783c031a7d4SSebastian Andrzej Siewior 	/* DT keeps this entry in mA, musb expects it as per USB spec */
784c031a7d4SSebastian Andrzej Siewior 	pdata.power = get_int_prop(dn, "mentor,power") / 2;
785606bf4d5STony Lindgren 
786606bf4d5STony Lindgren 	ret = of_property_read_u32(dn, "mentor,multipoint", &val);
787606bf4d5STony Lindgren 	if (!ret && val)
788606bf4d5STony Lindgren 		config->multipoint = true;
78965145677SAjay Kumar Gupta 
79063863b98SHeikki Krogerus 	config->maximum_speed = usb_get_maximum_speed(&parent->dev);
79141932b9bSBin Liu 	switch (config->maximum_speed) {
79241932b9bSBin Liu 	case USB_SPEED_LOW:
79341932b9bSBin Liu 	case USB_SPEED_FULL:
79441932b9bSBin Liu 		break;
79541932b9bSBin Liu 	case USB_SPEED_SUPER:
79641932b9bSBin Liu 		dev_warn(dev, "ignore incorrect maximum_speed "
79741932b9bSBin Liu 				"(super-speed) setting in dts");
798df561f66SGustavo A. R. Silva 		fallthrough;
79941932b9bSBin Liu 	default:
80041932b9bSBin Liu 		config->maximum_speed = USB_SPEED_HIGH;
80141932b9bSBin Liu 	}
80241932b9bSBin Liu 
80397238b35SSebastian Andrzej Siewior 	ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
8049ecb8875SAjay Kumar Gupta 	if (ret) {
8059ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add platform_data\n");
80697238b35SSebastian Andrzej Siewior 		goto err;
8079ecb8875SAjay Kumar Gupta 	}
8089ecb8875SAjay Kumar Gupta 
8099ecb8875SAjay Kumar Gupta 	ret = platform_device_add(musb);
8109ecb8875SAjay Kumar Gupta 	if (ret) {
8119ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to register musb device\n");
81297238b35SSebastian Andrzej Siewior 		goto err;
8139ecb8875SAjay Kumar Gupta 	}
8149ecb8875SAjay Kumar Gupta 	return 0;
8159ecb8875SAjay Kumar Gupta 
81697238b35SSebastian Andrzej Siewior err:
8179ecb8875SAjay Kumar Gupta 	platform_device_put(musb);
8189ecb8875SAjay Kumar Gupta 	return ret;
8199ecb8875SAjay Kumar Gupta }
8209ecb8875SAjay Kumar Gupta 
821369469a9STony Lindgren static irqreturn_t dsps_vbus_threaded_irq(int irq, void *priv)
822369469a9STony Lindgren {
823369469a9STony Lindgren 	struct dsps_glue *glue = priv;
824369469a9STony Lindgren 	struct musb *musb = platform_get_drvdata(glue->musb);
825369469a9STony Lindgren 
826369469a9STony Lindgren 	if (!musb)
827369469a9STony Lindgren 		return IRQ_NONE;
828369469a9STony Lindgren 
829369469a9STony Lindgren 	dev_dbg(glue->dev, "VBUS interrupt\n");
830369469a9STony Lindgren 	dsps_mod_timer(glue, 0);
831369469a9STony Lindgren 
832369469a9STony Lindgren 	return IRQ_HANDLED;
833369469a9STony Lindgren }
834369469a9STony Lindgren 
835369469a9STony Lindgren static int dsps_setup_optional_vbus_irq(struct platform_device *pdev,
836369469a9STony Lindgren 					struct dsps_glue *glue)
837369469a9STony Lindgren {
838369469a9STony Lindgren 	int error;
839369469a9STony Lindgren 
840369469a9STony Lindgren 	glue->vbus_irq = platform_get_irq_byname(pdev, "vbus");
841369469a9STony Lindgren 	if (glue->vbus_irq == -EPROBE_DEFER)
842369469a9STony Lindgren 		return -EPROBE_DEFER;
843369469a9STony Lindgren 
844369469a9STony Lindgren 	if (glue->vbus_irq <= 0) {
845369469a9STony Lindgren 		glue->vbus_irq = 0;
846369469a9STony Lindgren 		return 0;
847369469a9STony Lindgren 	}
848369469a9STony Lindgren 
849369469a9STony Lindgren 	error = devm_request_threaded_irq(glue->dev, glue->vbus_irq,
850369469a9STony Lindgren 					  NULL, dsps_vbus_threaded_irq,
851369469a9STony Lindgren 					  IRQF_ONESHOT,
852369469a9STony Lindgren 					  "vbus", glue);
853369469a9STony Lindgren 	if (error) {
854369469a9STony Lindgren 		glue->vbus_irq = 0;
855369469a9STony Lindgren 		return error;
856369469a9STony Lindgren 	}
857369469a9STony Lindgren 	dev_dbg(glue->dev, "VBUS irq %i configured\n", glue->vbus_irq);
858369469a9STony Lindgren 
859369469a9STony Lindgren 	return 0;
860369469a9STony Lindgren }
861369469a9STony Lindgren 
86241ac7b3aSBill Pemberton static int dsps_probe(struct platform_device *pdev)
8639ecb8875SAjay Kumar Gupta {
86465145677SAjay Kumar Gupta 	const struct of_device_id *match;
86565145677SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp;
8669ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue;
86797238b35SSebastian Andrzej Siewior 	int ret;
8689ecb8875SAjay Kumar Gupta 
8694fc4b274SSebastian Andrzej Siewior 	if (!strcmp(pdev->name, "musb-hdrc"))
8704fc4b274SSebastian Andrzej Siewior 		return -ENODEV;
8714fc4b274SSebastian Andrzej Siewior 
872cc506036SFelipe Balbi 	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
87365145677SAjay Kumar Gupta 	if (!match) {
87465145677SAjay Kumar Gupta 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
87597238b35SSebastian Andrzej Siewior 		return -EINVAL;
87665145677SAjay Kumar Gupta 	}
87765145677SAjay Kumar Gupta 	wrp = match->data;
8789ecb8875SAjay Kumar Gupta 
8793e457371STony Lindgren 	if (of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816"))
8803e457371STony Lindgren 		dsps_ops.read_fifo = dsps_read_fifo32;
8813e457371STony Lindgren 
8829ecb8875SAjay Kumar Gupta 	/* allocate glue */
883de9db572SMarkus Pargmann 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
8840816ea2fSPeter Chen 	if (!glue)
88597238b35SSebastian Andrzej Siewior 		return -ENOMEM;
8869ecb8875SAjay Kumar Gupta 
8879ecb8875SAjay Kumar Gupta 	glue->dev = &pdev->dev;
88897238b35SSebastian Andrzej Siewior 	glue->wrp = wrp;
88925534828SAlexandre Bailon 	glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0);
89025534828SAlexandre Bailon 	if (!glue->usbss_base)
89125534828SAlexandre Bailon 		return -ENXIO;
8929ecb8875SAjay Kumar Gupta 
8939ecb8875SAjay Kumar Gupta 	platform_set_drvdata(pdev, glue);
8949ecb8875SAjay Kumar Gupta 	pm_runtime_enable(&pdev->dev);
89597238b35SSebastian Andrzej Siewior 	ret = dsps_create_musb_pdev(glue, pdev);
89697238b35SSebastian Andrzej Siewior 	if (ret)
89724752917STony Lindgren 		goto err;
89865b3f50eSTony Lindgren 
8997c75bde3SNadezda Lutovinova 	if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
9007c75bde3SNadezda Lutovinova 		ret = dsps_setup_optional_vbus_irq(pdev, glue);
9017c75bde3SNadezda Lutovinova 		if (ret)
902*c2115b2bSMiquel Raynal 			goto unregister_pdev;
9037c75bde3SNadezda Lutovinova 	}
9047c75bde3SNadezda Lutovinova 
9059ecb8875SAjay Kumar Gupta 	return 0;
9069ecb8875SAjay Kumar Gupta 
907*c2115b2bSMiquel Raynal unregister_pdev:
908*c2115b2bSMiquel Raynal 	platform_device_unregister(glue->musb);
90924752917STony Lindgren err:
9100e38c4edSAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
9116b7ad496SBin Liu 	iounmap(glue->usbss_base);
9129ecb8875SAjay Kumar Gupta 	return ret;
9139ecb8875SAjay Kumar Gupta }
91497238b35SSebastian Andrzej Siewior 
915fb4e98abSBill Pemberton static int dsps_remove(struct platform_device *pdev)
9169ecb8875SAjay Kumar Gupta {
9179ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
9189ecb8875SAjay Kumar Gupta 
91997238b35SSebastian Andrzej Siewior 	platform_device_unregister(glue->musb);
9209ecb8875SAjay Kumar Gupta 
9219ecb8875SAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
9226b7ad496SBin Liu 	iounmap(glue->usbss_base);
92340f099e3SMarkus Pargmann 
9249ecb8875SAjay Kumar Gupta 	return 0;
9259ecb8875SAjay Kumar Gupta }
9269ecb8875SAjay Kumar Gupta 
927fa7b4ca5SSebastian Andrzej Siewior static const struct dsps_musb_wrapper am33xx_driver_data = {
9289ecb8875SAjay Kumar Gupta 	.revision		= 0x00,
9299ecb8875SAjay Kumar Gupta 	.control		= 0x14,
9309ecb8875SAjay Kumar Gupta 	.status			= 0x18,
9319ecb8875SAjay Kumar Gupta 	.epintr_set		= 0x38,
9329ecb8875SAjay Kumar Gupta 	.epintr_clear		= 0x40,
9339ecb8875SAjay Kumar Gupta 	.epintr_status		= 0x30,
9349ecb8875SAjay Kumar Gupta 	.coreintr_set		= 0x3c,
9359ecb8875SAjay Kumar Gupta 	.coreintr_clear		= 0x44,
9369ecb8875SAjay Kumar Gupta 	.coreintr_status	= 0x34,
9379ecb8875SAjay Kumar Gupta 	.phy_utmi		= 0xe0,
9389ecb8875SAjay Kumar Gupta 	.mode			= 0xe8,
939b991f9b7SDaniel Mack 	.tx_mode		= 0x70,
940b991f9b7SDaniel Mack 	.rx_mode		= 0x74,
9419ecb8875SAjay Kumar Gupta 	.reset			= 0,
9429ecb8875SAjay Kumar Gupta 	.otg_disable		= 21,
9439ecb8875SAjay Kumar Gupta 	.iddig			= 8,
944943c1397SFelipe Balbi 	.iddig_mux		= 7,
9459ecb8875SAjay Kumar Gupta 	.usb_shift		= 0,
9469ecb8875SAjay Kumar Gupta 	.usb_mask		= 0x1ff,
9479ecb8875SAjay Kumar Gupta 	.usb_bitmap		= (0x1ff << 0),
9489ecb8875SAjay Kumar Gupta 	.drvvbus		= 8,
9499ecb8875SAjay Kumar Gupta 	.txep_shift		= 0,
9509ecb8875SAjay Kumar Gupta 	.txep_mask		= 0xffff,
9519ecb8875SAjay Kumar Gupta 	.txep_bitmap		= (0xffff << 0),
9529ecb8875SAjay Kumar Gupta 	.rxep_shift		= 16,
9539ecb8875SAjay Kumar Gupta 	.rxep_mask		= 0xfffe,
9549ecb8875SAjay Kumar Gupta 	.rxep_bitmap		= (0xfffe << 16),
9559e204d88SFelipe Balbi 	.poll_timeout		= 2000, /* ms */
9569ecb8875SAjay Kumar Gupta };
9579ecb8875SAjay Kumar Gupta 
9582f82686eSBill Pemberton static const struct of_device_id musb_dsps_of_match[] = {
95965145677SAjay Kumar Gupta 	{ .compatible = "ti,musb-am33xx",
9603e457371STony Lindgren 		.data = &am33xx_driver_data, },
9613e457371STony Lindgren 	{ .compatible = "ti,musb-dm816",
9623e457371STony Lindgren 		.data = &am33xx_driver_data, },
9639ecb8875SAjay Kumar Gupta 	{  },
9649ecb8875SAjay Kumar Gupta };
9659ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
9669ecb8875SAjay Kumar Gupta 
9675b783983SWolfram Sang #ifdef CONFIG_PM_SLEEP
968869c5978SDaniel Mack static int dsps_suspend(struct device *dev)
969869c5978SDaniel Mack {
970869c5978SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev);
971869c5978SDaniel Mack 	const struct dsps_musb_wrapper *wrp = glue->wrp;
972869c5978SDaniel Mack 	struct musb *musb = platform_get_drvdata(glue->musb);
973f042e9cbSSebastian Andrzej Siewior 	void __iomem *mbase;
974706d61b2SJohan Hovold 	int ret;
975f042e9cbSSebastian Andrzej Siewior 
976f042e9cbSSebastian Andrzej Siewior 	if (!musb)
977f042e9cbSSebastian Andrzej Siewior 		/* This can happen if the musb device is in -EPROBE_DEFER */
978f042e9cbSSebastian Andrzej Siewior 		return 0;
979f042e9cbSSebastian Andrzej Siewior 
980706d61b2SJohan Hovold 	ret = pm_runtime_get_sync(dev);
981706d61b2SJohan Hovold 	if (ret < 0) {
982706d61b2SJohan Hovold 		pm_runtime_put_noidle(dev);
983706d61b2SJohan Hovold 		return ret;
984706d61b2SJohan Hovold 	}
985706d61b2SJohan Hovold 
986b82162bcSBin Liu 	del_timer_sync(&musb->dev_timer);
987706d61b2SJohan Hovold 
988f042e9cbSSebastian Andrzej Siewior 	mbase = musb->ctrl_base;
989086b2882SBin Liu 	glue->context.control = musb_readl(mbase, wrp->control);
990086b2882SBin Liu 	glue->context.epintr = musb_readl(mbase, wrp->epintr_set);
991086b2882SBin Liu 	glue->context.coreintr = musb_readl(mbase, wrp->coreintr_set);
992086b2882SBin Liu 	glue->context.phy_utmi = musb_readl(mbase, wrp->phy_utmi);
993086b2882SBin Liu 	glue->context.mode = musb_readl(mbase, wrp->mode);
994086b2882SBin Liu 	glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode);
995086b2882SBin Liu 	glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode);
996869c5978SDaniel Mack 
99725534828SAlexandre Bailon 	dsps_dma_controller_suspend(glue);
99825534828SAlexandre Bailon 
999869c5978SDaniel Mack 	return 0;
1000869c5978SDaniel Mack }
1001869c5978SDaniel Mack 
1002869c5978SDaniel Mack static int dsps_resume(struct device *dev)
1003869c5978SDaniel Mack {
1004869c5978SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev);
1005869c5978SDaniel Mack 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1006869c5978SDaniel Mack 	struct musb *musb = platform_get_drvdata(glue->musb);
1007f042e9cbSSebastian Andrzej Siewior 	void __iomem *mbase;
1008869c5978SDaniel Mack 
1009f042e9cbSSebastian Andrzej Siewior 	if (!musb)
1010f042e9cbSSebastian Andrzej Siewior 		return 0;
1011f042e9cbSSebastian Andrzej Siewior 
101225534828SAlexandre Bailon 	dsps_dma_controller_resume(glue);
101325534828SAlexandre Bailon 
1014f042e9cbSSebastian Andrzej Siewior 	mbase = musb->ctrl_base;
1015086b2882SBin Liu 	musb_writel(mbase, wrp->control, glue->context.control);
1016086b2882SBin Liu 	musb_writel(mbase, wrp->epintr_set, glue->context.epintr);
1017086b2882SBin Liu 	musb_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
1018086b2882SBin Liu 	musb_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
1019086b2882SBin Liu 	musb_writel(mbase, wrp->mode, glue->context.mode);
1020086b2882SBin Liu 	musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
1021086b2882SBin Liu 	musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
1022e47d9254SAntoine Tenart 	if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
10237ad76955SBin Liu 	    musb->port_mode == MUSB_OTG)
1024369469a9STony Lindgren 		dsps_mod_timer(glue, -1);
1025869c5978SDaniel Mack 
1026706d61b2SJohan Hovold 	pm_runtime_put(dev);
1027706d61b2SJohan Hovold 
1028869c5978SDaniel Mack 	return 0;
1029869c5978SDaniel Mack }
1030869c5978SDaniel Mack #endif
1031869c5978SDaniel Mack 
1032869c5978SDaniel Mack static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
1033869c5978SDaniel Mack 
10349ecb8875SAjay Kumar Gupta static struct platform_driver dsps_usbss_driver = {
10359ecb8875SAjay Kumar Gupta 	.probe		= dsps_probe,
10367690417dSBill Pemberton 	.remove         = dsps_remove,
10379ecb8875SAjay Kumar Gupta 	.driver         = {
10389ecb8875SAjay Kumar Gupta 		.name   = "musb-dsps",
1039869c5978SDaniel Mack 		.pm	= &dsps_pm_ops,
1040b432cb83SSachin Kamat 		.of_match_table	= musb_dsps_of_match,
10419ecb8875SAjay Kumar Gupta 	},
10429ecb8875SAjay Kumar Gupta };
10439ecb8875SAjay Kumar Gupta 
10449ecb8875SAjay Kumar Gupta MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
10459ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
10469ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
10479ecb8875SAjay Kumar Gupta MODULE_LICENSE("GPL v2");
10489ecb8875SAjay Kumar Gupta 
104997238b35SSebastian Andrzej Siewior module_platform_driver(dsps_usbss_driver);
1050