xref: /linux/drivers/usb/musb/musb_dsps.c (revision 05678497276e1ff9394f7f815d80b1f2d47e92f4)
19ecb8875SAjay Kumar Gupta /*
29ecb8875SAjay Kumar Gupta  * Texas Instruments DSPS platforms "glue layer"
39ecb8875SAjay Kumar Gupta  *
49ecb8875SAjay Kumar Gupta  * Copyright (C) 2012, by Texas Instruments
59ecb8875SAjay Kumar Gupta  *
69ecb8875SAjay Kumar Gupta  * Based on the am35x "glue layer" code.
79ecb8875SAjay Kumar Gupta  *
89ecb8875SAjay Kumar Gupta  * This file is part of the Inventra Controller Driver for Linux.
99ecb8875SAjay Kumar Gupta  *
109ecb8875SAjay Kumar Gupta  * The Inventra Controller Driver for Linux is free software; you
119ecb8875SAjay Kumar Gupta  * can redistribute it and/or modify it under the terms of the GNU
129ecb8875SAjay Kumar Gupta  * General Public License version 2 as published by the Free Software
139ecb8875SAjay Kumar Gupta  * Foundation.
149ecb8875SAjay Kumar Gupta  *
159ecb8875SAjay Kumar Gupta  * The Inventra Controller Driver for Linux is distributed in
169ecb8875SAjay Kumar Gupta  * the hope that it will be useful, but WITHOUT ANY WARRANTY;
179ecb8875SAjay Kumar Gupta  * without even the implied warranty of MERCHANTABILITY or
189ecb8875SAjay Kumar Gupta  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
199ecb8875SAjay Kumar Gupta  * License for more details.
209ecb8875SAjay Kumar Gupta  *
219ecb8875SAjay Kumar Gupta  * You should have received a copy of the GNU General Public License
229ecb8875SAjay Kumar Gupta  * along with The Inventra Controller Driver for Linux ; if not,
239ecb8875SAjay Kumar Gupta  * write to the Free Software Foundation, Inc., 59 Temple Place,
249ecb8875SAjay Kumar Gupta  * Suite 330, Boston, MA  02111-1307  USA
259ecb8875SAjay Kumar Gupta  *
269ecb8875SAjay Kumar Gupta  * musb_dsps.c will be a common file for all the TI DSPS platforms
279ecb8875SAjay Kumar Gupta  * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
289ecb8875SAjay Kumar Gupta  * For now only ti81x is using this and in future davinci.c, am35x.c
299ecb8875SAjay Kumar Gupta  * da8xx.c would be merged to this file after testing.
309ecb8875SAjay Kumar Gupta  */
319ecb8875SAjay Kumar Gupta 
329ecb8875SAjay Kumar Gupta #include <linux/io.h>
33ded017eeSKishon Vijay Abraham I #include <linux/err.h>
349ecb8875SAjay Kumar Gupta #include <linux/platform_device.h>
359ecb8875SAjay Kumar Gupta #include <linux/dma-mapping.h>
369ecb8875SAjay Kumar Gupta #include <linux/pm_runtime.h>
379ecb8875SAjay Kumar Gupta #include <linux/module.h>
38d7078df6SFelipe Balbi #include <linux/usb/usb_phy_generic.h>
39e8c4a7acSFelipe Balbi #include <linux/platform_data/usb-omap.h>
400f53e481SFelipe Balbi #include <linux/sizes.h>
419ecb8875SAjay Kumar Gupta 
429ecb8875SAjay Kumar Gupta #include <linux/of.h>
439ecb8875SAjay Kumar Gupta #include <linux/of_device.h>
449ecb8875SAjay Kumar Gupta #include <linux/of_address.h>
4597238b35SSebastian Andrzej Siewior #include <linux/of_irq.h>
46c031a7d4SSebastian Andrzej Siewior #include <linux/usb/of.h>
479ecb8875SAjay Kumar Gupta 
4840f099e3SMarkus Pargmann #include <linux/debugfs.h>
4940f099e3SMarkus Pargmann 
509ecb8875SAjay Kumar Gupta #include "musb_core.h"
519ecb8875SAjay Kumar Gupta 
5265145677SAjay Kumar Gupta static const struct of_device_id musb_dsps_of_match[];
5365145677SAjay Kumar Gupta 
549ecb8875SAjay Kumar Gupta /**
559ecb8875SAjay Kumar Gupta  * DSPS musb wrapper register offset.
569ecb8875SAjay Kumar Gupta  * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
579ecb8875SAjay Kumar Gupta  * musb ips.
589ecb8875SAjay Kumar Gupta  */
599ecb8875SAjay Kumar Gupta struct dsps_musb_wrapper {
609ecb8875SAjay Kumar Gupta 	u16	revision;
619ecb8875SAjay Kumar Gupta 	u16	control;
629ecb8875SAjay Kumar Gupta 	u16	status;
639ecb8875SAjay Kumar Gupta 	u16	epintr_set;
649ecb8875SAjay Kumar Gupta 	u16	epintr_clear;
659ecb8875SAjay Kumar Gupta 	u16	epintr_status;
669ecb8875SAjay Kumar Gupta 	u16	coreintr_set;
679ecb8875SAjay Kumar Gupta 	u16	coreintr_clear;
689ecb8875SAjay Kumar Gupta 	u16	coreintr_status;
699ecb8875SAjay Kumar Gupta 	u16	phy_utmi;
709ecb8875SAjay Kumar Gupta 	u16	mode;
71b991f9b7SDaniel Mack 	u16	tx_mode;
72b991f9b7SDaniel Mack 	u16	rx_mode;
739ecb8875SAjay Kumar Gupta 
749ecb8875SAjay Kumar Gupta 	/* bit positions for control */
759ecb8875SAjay Kumar Gupta 	unsigned	reset:5;
769ecb8875SAjay Kumar Gupta 
779ecb8875SAjay Kumar Gupta 	/* bit positions for interrupt */
789ecb8875SAjay Kumar Gupta 	unsigned	usb_shift:5;
799ecb8875SAjay Kumar Gupta 	u32		usb_mask;
809ecb8875SAjay Kumar Gupta 	u32		usb_bitmap;
819ecb8875SAjay Kumar Gupta 	unsigned	drvvbus:5;
829ecb8875SAjay Kumar Gupta 
839ecb8875SAjay Kumar Gupta 	unsigned	txep_shift:5;
849ecb8875SAjay Kumar Gupta 	u32		txep_mask;
859ecb8875SAjay Kumar Gupta 	u32		txep_bitmap;
869ecb8875SAjay Kumar Gupta 
879ecb8875SAjay Kumar Gupta 	unsigned	rxep_shift:5;
889ecb8875SAjay Kumar Gupta 	u32		rxep_mask;
899ecb8875SAjay Kumar Gupta 	u32		rxep_bitmap;
909ecb8875SAjay Kumar Gupta 
919ecb8875SAjay Kumar Gupta 	/* bit positions for phy_utmi */
929ecb8875SAjay Kumar Gupta 	unsigned	otg_disable:5;
939ecb8875SAjay Kumar Gupta 
949ecb8875SAjay Kumar Gupta 	/* bit positions for mode */
959ecb8875SAjay Kumar Gupta 	unsigned	iddig:5;
96943c1397SFelipe Balbi 	unsigned	iddig_mux:5;
979ecb8875SAjay Kumar Gupta 	/* miscellaneous stuff */
989e204d88SFelipe Balbi 	unsigned	poll_timeout;
999ecb8875SAjay Kumar Gupta };
1009ecb8875SAjay Kumar Gupta 
101869c5978SDaniel Mack /*
102869c5978SDaniel Mack  * register shadow for suspend
103869c5978SDaniel Mack  */
104869c5978SDaniel Mack struct dsps_context {
105869c5978SDaniel Mack 	u32 control;
106869c5978SDaniel Mack 	u32 epintr;
107869c5978SDaniel Mack 	u32 coreintr;
108869c5978SDaniel Mack 	u32 phy_utmi;
109869c5978SDaniel Mack 	u32 mode;
110869c5978SDaniel Mack 	u32 tx_mode;
111869c5978SDaniel Mack 	u32 rx_mode;
112869c5978SDaniel Mack };
113869c5978SDaniel Mack 
1149ecb8875SAjay Kumar Gupta /**
1159ecb8875SAjay Kumar Gupta  * DSPS glue structure.
1169ecb8875SAjay Kumar Gupta  */
1179ecb8875SAjay Kumar Gupta struct dsps_glue {
1189ecb8875SAjay Kumar Gupta 	struct device *dev;
11997238b35SSebastian Andrzej Siewior 	struct platform_device *musb;	/* child musb pdev */
1209ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
121369469a9STony Lindgren 	int vbus_irq;			/* optional vbus irq */
12297238b35SSebastian Andrzej Siewior 	struct timer_list timer;	/* otg_workaround timer */
12397238b35SSebastian Andrzej Siewior 	unsigned long last_timer;    /* last timer data for each instance */
124371254ceSGeorge Cherian 	bool sw_babble_enabled;
12525534828SAlexandre Bailon 	void __iomem *usbss_base;
126869c5978SDaniel Mack 
127869c5978SDaniel Mack 	struct dsps_context context;
12840f099e3SMarkus Pargmann 	struct debugfs_regset32 regset;
12940f099e3SMarkus Pargmann 	struct dentry *dbgfs_root;
13040f099e3SMarkus Pargmann };
13140f099e3SMarkus Pargmann 
13240f099e3SMarkus Pargmann static const struct debugfs_reg32 dsps_musb_regs[] = {
13340f099e3SMarkus Pargmann 	{ "revision",		0x00 },
13440f099e3SMarkus Pargmann 	{ "control",		0x14 },
13540f099e3SMarkus Pargmann 	{ "status",		0x18 },
13640f099e3SMarkus Pargmann 	{ "eoi",		0x24 },
13740f099e3SMarkus Pargmann 	{ "intr0_stat",		0x30 },
13840f099e3SMarkus Pargmann 	{ "intr1_stat",		0x34 },
13940f099e3SMarkus Pargmann 	{ "intr0_set",		0x38 },
14040f099e3SMarkus Pargmann 	{ "intr1_set",		0x3c },
14140f099e3SMarkus Pargmann 	{ "txmode",		0x70 },
14240f099e3SMarkus Pargmann 	{ "rxmode",		0x74 },
14340f099e3SMarkus Pargmann 	{ "autoreq",		0xd0 },
14440f099e3SMarkus Pargmann 	{ "srpfixtime",		0xd4 },
14540f099e3SMarkus Pargmann 	{ "tdown",		0xd8 },
14640f099e3SMarkus Pargmann 	{ "phy_utmi",		0xe0 },
14740f099e3SMarkus Pargmann 	{ "mode",		0xe8 },
1489ecb8875SAjay Kumar Gupta };
1499ecb8875SAjay Kumar Gupta 
150369469a9STony Lindgren static void dsps_mod_timer(struct dsps_glue *glue, int wait_ms)
151369469a9STony Lindgren {
152369469a9STony Lindgren 	int wait;
153369469a9STony Lindgren 
154369469a9STony Lindgren 	if (wait_ms < 0)
155369469a9STony Lindgren 		wait = msecs_to_jiffies(glue->wrp->poll_timeout);
156369469a9STony Lindgren 	else
157369469a9STony Lindgren 		wait = msecs_to_jiffies(wait_ms);
158369469a9STony Lindgren 
159369469a9STony Lindgren 	mod_timer(&glue->timer, jiffies + wait);
160369469a9STony Lindgren }
161369469a9STony Lindgren 
162369469a9STony Lindgren /*
163369469a9STony Lindgren  * If no vbus irq from the PMIC is configured, we need to poll VBUS status.
164369469a9STony Lindgren  */
165369469a9STony Lindgren static void dsps_mod_timer_optional(struct dsps_glue *glue)
166369469a9STony Lindgren {
167369469a9STony Lindgren 	if (glue->vbus_irq)
168369469a9STony Lindgren 		return;
169369469a9STony Lindgren 
170369469a9STony Lindgren 	dsps_mod_timer(glue, -1);
171369469a9STony Lindgren }
172369469a9STony Lindgren 
17325534828SAlexandre Bailon /* USBSS  / USB AM335x */
17425534828SAlexandre Bailon #define USBSS_IRQ_STATUS	0x28
17525534828SAlexandre Bailon #define USBSS_IRQ_ENABLER	0x2c
17625534828SAlexandre Bailon #define USBSS_IRQ_CLEARR	0x30
17725534828SAlexandre Bailon 
17825534828SAlexandre Bailon #define USBSS_IRQ_PD_COMP	(1 << 2)
17925534828SAlexandre Bailon 
1809ecb8875SAjay Kumar Gupta /**
1819ecb8875SAjay Kumar Gupta  * dsps_musb_enable - enable interrupts
1829ecb8875SAjay Kumar Gupta  */
1839ecb8875SAjay Kumar Gupta static void dsps_musb_enable(struct musb *musb)
1849ecb8875SAjay Kumar Gupta {
1859ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
1869ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
1879ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
1889ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1899ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
1909ecb8875SAjay Kumar Gupta 	u32 epmask, coremask;
1919ecb8875SAjay Kumar Gupta 
1929ecb8875SAjay Kumar Gupta 	/* Workaround: setup IRQs through both register sets. */
1939ecb8875SAjay Kumar Gupta 	epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
1949ecb8875SAjay Kumar Gupta 	       ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
1959ecb8875SAjay Kumar Gupta 	coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
1969ecb8875SAjay Kumar Gupta 
197086b2882SBin Liu 	musb_writel(reg_base, wrp->epintr_set, epmask);
198086b2882SBin Liu 	musb_writel(reg_base, wrp->coreintr_set, coremask);
199b8239dccSBin Liu 	/* start polling for ID change in dual-role idle mode */
200b8239dccSBin Liu 	if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
201b8239dccSBin Liu 			musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
202369469a9STony Lindgren 		dsps_mod_timer(glue, -1);
2039ecb8875SAjay Kumar Gupta }
2049ecb8875SAjay Kumar Gupta 
2059ecb8875SAjay Kumar Gupta /**
2069ecb8875SAjay Kumar Gupta  * dsps_musb_disable - disable HDRC and flush interrupts
2079ecb8875SAjay Kumar Gupta  */
2089ecb8875SAjay Kumar Gupta static void dsps_musb_disable(struct musb *musb)
2099ecb8875SAjay Kumar Gupta {
2109ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
2119ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
2129ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
2139ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
2149ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
2159ecb8875SAjay Kumar Gupta 
216086b2882SBin Liu 	musb_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
217086b2882SBin Liu 	musb_writel(reg_base, wrp->epintr_clear,
2189ecb8875SAjay Kumar Gupta 			 wrp->txep_bitmap | wrp->rxep_bitmap);
219ea2f35c0STony Lindgren 	del_timer_sync(&glue->timer);
2209ecb8875SAjay Kumar Gupta }
2219ecb8875SAjay Kumar Gupta 
222ea2f35c0STony Lindgren /* Caller must take musb->lock */
223ea2f35c0STony Lindgren static int dsps_check_status(struct musb *musb, void *unused)
2249ecb8875SAjay Kumar Gupta {
2259ecb8875SAjay Kumar Gupta 	void __iomem *mregs = musb->mregs;
2269ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
227db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
2289ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
2299ecb8875SAjay Kumar Gupta 	u8 devctl;
2300f901c98SSebastian Andrzej Siewior 	int skip_session = 0;
2319ecb8875SAjay Kumar Gupta 
232369469a9STony Lindgren 	if (glue->vbus_irq)
233369469a9STony Lindgren 		del_timer(&glue->timer);
234369469a9STony Lindgren 
2359ecb8875SAjay Kumar Gupta 	/*
2369ecb8875SAjay Kumar Gupta 	 * We poll because DSPS IP's won't expose several OTG-critical
2379ecb8875SAjay Kumar Gupta 	 * status change events (from the transceiver) otherwise.
2389ecb8875SAjay Kumar Gupta 	 */
239086b2882SBin Liu 	devctl = musb_readb(mregs, MUSB_DEVCTL);
2409ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
241e47d9254SAntoine Tenart 				usb_otg_state_string(musb->xceiv->otg->state));
2429ecb8875SAjay Kumar Gupta 
243e47d9254SAntoine Tenart 	switch (musb->xceiv->otg->state) {
2442f3fd2c5STony Lindgren 	case OTG_STATE_A_WAIT_VRISE:
245369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
2462f3fd2c5STony Lindgren 		break;
2479ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_BCON:
248b3addcf0SBin Liu 		/* keep VBUS on for host-only mode */
249b3addcf0SBin Liu 		if (musb->port_mode == MUSB_PORT_MODE_HOST) {
250b3addcf0SBin Liu 			dsps_mod_timer_optional(glue);
251b3addcf0SBin Liu 			break;
252b3addcf0SBin Liu 		}
253086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
2540f901c98SSebastian Andrzej Siewior 		skip_session = 1;
2550f901c98SSebastian Andrzej Siewior 		/* fall */
2569ecb8875SAjay Kumar Gupta 
2570f901c98SSebastian Andrzej Siewior 	case OTG_STATE_A_IDLE:
2580f901c98SSebastian Andrzej Siewior 	case OTG_STATE_B_IDLE:
259369469a9STony Lindgren 		if (!glue->vbus_irq) {
2609ecb8875SAjay Kumar Gupta 			if (devctl & MUSB_DEVCTL_BDEVICE) {
261e47d9254SAntoine Tenart 				musb->xceiv->otg->state = OTG_STATE_B_IDLE;
2629ecb8875SAjay Kumar Gupta 				MUSB_DEV_MODE(musb);
2639ecb8875SAjay Kumar Gupta 			} else {
264e47d9254SAntoine Tenart 				musb->xceiv->otg->state = OTG_STATE_A_IDLE;
2659ecb8875SAjay Kumar Gupta 				MUSB_HST_MODE(musb);
2669ecb8875SAjay Kumar Gupta 			}
2670f901c98SSebastian Andrzej Siewior 			if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
268369469a9STony Lindgren 				musb_writeb(mregs, MUSB_DEVCTL,
269369469a9STony Lindgren 					    MUSB_DEVCTL_SESSION);
270369469a9STony Lindgren 		}
271369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
2729ecb8875SAjay Kumar Gupta 		break;
2739ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_VFALL:
274e47d9254SAntoine Tenart 		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
275086b2882SBin Liu 		musb_writel(musb->ctrl_base, wrp->coreintr_set,
2769ecb8875SAjay Kumar Gupta 			    MUSB_INTR_VBUSERROR << wrp->usb_shift);
2779ecb8875SAjay Kumar Gupta 		break;
2789ecb8875SAjay Kumar Gupta 	default:
2799ecb8875SAjay Kumar Gupta 		break;
2809ecb8875SAjay Kumar Gupta 	}
28165b3f50eSTony Lindgren 
282ea2f35c0STony Lindgren 	return 0;
283ea2f35c0STony Lindgren }
284ea2f35c0STony Lindgren 
285*05678497SKees Cook static void otg_timer(struct timer_list *t)
286ea2f35c0STony Lindgren {
287*05678497SKees Cook 	struct dsps_glue *glue = from_timer(glue, t, timer);
288*05678497SKees Cook 	struct musb *musb = platform_get_drvdata(glue->musb);
289ea2f35c0STony Lindgren 	struct device *dev = musb->controller;
290ea2f35c0STony Lindgren 	unsigned long flags;
291ea2f35c0STony Lindgren 	int err;
292ea2f35c0STony Lindgren 
293ea2f35c0STony Lindgren 	err = pm_runtime_get(dev);
294ea2f35c0STony Lindgren 	if ((err != -EINPROGRESS) && err < 0) {
295ea2f35c0STony Lindgren 		dev_err(dev, "Poll could not pm_runtime_get: %i\n", err);
296ea2f35c0STony Lindgren 		pm_runtime_put_noidle(dev);
297ea2f35c0STony Lindgren 
298ea2f35c0STony Lindgren 		return;
299ea2f35c0STony Lindgren 	}
300ea2f35c0STony Lindgren 
301ea2f35c0STony Lindgren 	spin_lock_irqsave(&musb->lock, flags);
302ea2f35c0STony Lindgren 	err = musb_queue_resume_work(musb, dsps_check_status, NULL);
303ea2f35c0STony Lindgren 	if (err < 0)
304ea2f35c0STony Lindgren 		dev_err(dev, "%s resume work: %i\n", __func__, err);
305ea2f35c0STony Lindgren 	spin_unlock_irqrestore(&musb->lock, flags);
30665b3f50eSTony Lindgren 	pm_runtime_mark_last_busy(dev);
30765b3f50eSTony Lindgren 	pm_runtime_put_autosuspend(dev);
3089ecb8875SAjay Kumar Gupta }
3099ecb8875SAjay Kumar Gupta 
3104ab53a69SWei Yongjun static void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum)
311c48400baSBin Liu {
312c48400baSBin Liu 	u32 epintr;
313c48400baSBin Liu 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
314c48400baSBin Liu 	const struct dsps_musb_wrapper *wrp = glue->wrp;
315c48400baSBin Liu 
316c48400baSBin Liu 	/* musb->lock might already been held */
317c48400baSBin Liu 	epintr = (1 << epnum) << wrp->rxep_shift;
318c48400baSBin Liu 	musb_writel(musb->ctrl_base, wrp->epintr_status, epintr);
319c48400baSBin Liu }
320c48400baSBin Liu 
3219ecb8875SAjay Kumar Gupta static irqreturn_t dsps_interrupt(int irq, void *hci)
3229ecb8875SAjay Kumar Gupta {
3239ecb8875SAjay Kumar Gupta 	struct musb  *musb = hci;
3249ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
3259ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
326db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
3279ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
3289ecb8875SAjay Kumar Gupta 	unsigned long flags;
3299ecb8875SAjay Kumar Gupta 	irqreturn_t ret = IRQ_NONE;
3309ecb8875SAjay Kumar Gupta 	u32 epintr, usbintr;
3319ecb8875SAjay Kumar Gupta 
3329ecb8875SAjay Kumar Gupta 	spin_lock_irqsave(&musb->lock, flags);
3339ecb8875SAjay Kumar Gupta 
3349ecb8875SAjay Kumar Gupta 	/* Get endpoint interrupts */
335086b2882SBin Liu 	epintr = musb_readl(reg_base, wrp->epintr_status);
3369ecb8875SAjay Kumar Gupta 	musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
3379ecb8875SAjay Kumar Gupta 	musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
3389ecb8875SAjay Kumar Gupta 
3399ecb8875SAjay Kumar Gupta 	if (epintr)
340086b2882SBin Liu 		musb_writel(reg_base, wrp->epintr_status, epintr);
3419ecb8875SAjay Kumar Gupta 
3429ecb8875SAjay Kumar Gupta 	/* Get usb core interrupts */
343086b2882SBin Liu 	usbintr = musb_readl(reg_base, wrp->coreintr_status);
3449ecb8875SAjay Kumar Gupta 	if (!usbintr && !epintr)
3459be73baeSSebastian Andrzej Siewior 		goto out;
3469ecb8875SAjay Kumar Gupta 
3479ecb8875SAjay Kumar Gupta 	musb->int_usb =	(usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
3489ecb8875SAjay Kumar Gupta 	if (usbintr)
349086b2882SBin Liu 		musb_writel(reg_base, wrp->coreintr_status, usbintr);
3509ecb8875SAjay Kumar Gupta 
3519ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
3529ecb8875SAjay Kumar Gupta 			usbintr, epintr);
3531d57de30SDaniel Mack 
3549ecb8875SAjay Kumar Gupta 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
355086b2882SBin Liu 		int drvvbus = musb_readl(reg_base, wrp->status);
3569ecb8875SAjay Kumar Gupta 		void __iomem *mregs = musb->mregs;
357086b2882SBin Liu 		u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
3589ecb8875SAjay Kumar Gupta 		int err;
3599ecb8875SAjay Kumar Gupta 
360032ec49fSFelipe Balbi 		err = musb->int_usb & MUSB_INTR_VBUSERROR;
3619ecb8875SAjay Kumar Gupta 		if (err) {
3629ecb8875SAjay Kumar Gupta 			/*
3639ecb8875SAjay Kumar Gupta 			 * The Mentor core doesn't debounce VBUS as needed
3649ecb8875SAjay Kumar Gupta 			 * to cope with device connect current spikes. This
3659ecb8875SAjay Kumar Gupta 			 * means it's not uncommon for bus-powered devices
3669ecb8875SAjay Kumar Gupta 			 * to get VBUS errors during enumeration.
3679ecb8875SAjay Kumar Gupta 			 *
3689ecb8875SAjay Kumar Gupta 			 * This is a workaround, but newer RTL from Mentor
3699ecb8875SAjay Kumar Gupta 			 * seems to allow a better one: "re"-starting sessions
3709ecb8875SAjay Kumar Gupta 			 * without waiting for VBUS to stop registering in
3719ecb8875SAjay Kumar Gupta 			 * devctl.
3729ecb8875SAjay Kumar Gupta 			 */
3739ecb8875SAjay Kumar Gupta 			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
374e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL;
375369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
3769ecb8875SAjay Kumar Gupta 			WARNING("VBUS error workaround (delay coming)\n");
377032ec49fSFelipe Balbi 		} else if (drvvbus) {
3789ecb8875SAjay Kumar Gupta 			MUSB_HST_MODE(musb);
3799ecb8875SAjay Kumar Gupta 			musb->xceiv->otg->default_a = 1;
380e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
381369469a9STony Lindgren 			dsps_mod_timer_optional(glue);
3829ecb8875SAjay Kumar Gupta 		} else {
3839ecb8875SAjay Kumar Gupta 			musb->is_active = 0;
3849ecb8875SAjay Kumar Gupta 			MUSB_DEV_MODE(musb);
3859ecb8875SAjay Kumar Gupta 			musb->xceiv->otg->default_a = 0;
386e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_B_IDLE;
3879ecb8875SAjay Kumar Gupta 		}
3889ecb8875SAjay Kumar Gupta 
3899ecb8875SAjay Kumar Gupta 		/* NOTE: this must complete power-on within 100 ms. */
3909ecb8875SAjay Kumar Gupta 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
3919ecb8875SAjay Kumar Gupta 				drvvbus ? "on" : "off",
392e47d9254SAntoine Tenart 				usb_otg_state_string(musb->xceiv->otg->state),
3939ecb8875SAjay Kumar Gupta 				err ? " ERROR" : "",
3949ecb8875SAjay Kumar Gupta 				devctl);
3959ecb8875SAjay Kumar Gupta 		ret = IRQ_HANDLED;
3969ecb8875SAjay Kumar Gupta 	}
3979ecb8875SAjay Kumar Gupta 
3989ecb8875SAjay Kumar Gupta 	if (musb->int_tx || musb->int_rx || musb->int_usb)
3999ecb8875SAjay Kumar Gupta 		ret |= musb_interrupt(musb);
4009ecb8875SAjay Kumar Gupta 
4012f3fd2c5STony Lindgren 	/* Poll for ID change and connect */
4022f3fd2c5STony Lindgren 	switch (musb->xceiv->otg->state) {
4032f3fd2c5STony Lindgren 	case OTG_STATE_B_IDLE:
4042f3fd2c5STony Lindgren 	case OTG_STATE_A_WAIT_BCON:
405369469a9STony Lindgren 		dsps_mod_timer_optional(glue);
4062f3fd2c5STony Lindgren 		break;
4072f3fd2c5STony Lindgren 	default:
4082f3fd2c5STony Lindgren 		break;
4092f3fd2c5STony Lindgren 	}
4102f3fd2c5STony Lindgren 
4119be73baeSSebastian Andrzej Siewior out:
4129ecb8875SAjay Kumar Gupta 	spin_unlock_irqrestore(&musb->lock, flags);
4139ecb8875SAjay Kumar Gupta 
4149ecb8875SAjay Kumar Gupta 	return ret;
4159ecb8875SAjay Kumar Gupta }
4169ecb8875SAjay Kumar Gupta 
41740f099e3SMarkus Pargmann static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue)
41840f099e3SMarkus Pargmann {
41940f099e3SMarkus Pargmann 	struct dentry *root;
42040f099e3SMarkus Pargmann 	struct dentry *file;
42140f099e3SMarkus Pargmann 	char buf[128];
42240f099e3SMarkus Pargmann 
42340f099e3SMarkus Pargmann 	sprintf(buf, "%s.dsps", dev_name(musb->controller));
42440f099e3SMarkus Pargmann 	root = debugfs_create_dir(buf, NULL);
42540f099e3SMarkus Pargmann 	if (!root)
42640f099e3SMarkus Pargmann 		return -ENOMEM;
42740f099e3SMarkus Pargmann 	glue->dbgfs_root = root;
42840f099e3SMarkus Pargmann 
42940f099e3SMarkus Pargmann 	glue->regset.regs = dsps_musb_regs;
43040f099e3SMarkus Pargmann 	glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs);
43140f099e3SMarkus Pargmann 	glue->regset.base = musb->ctrl_base;
43240f099e3SMarkus Pargmann 
43340f099e3SMarkus Pargmann 	file = debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset);
43440f099e3SMarkus Pargmann 	if (!file) {
43540f099e3SMarkus Pargmann 		debugfs_remove_recursive(root);
43640f099e3SMarkus Pargmann 		return -ENOMEM;
43740f099e3SMarkus Pargmann 	}
43840f099e3SMarkus Pargmann 	return 0;
43940f099e3SMarkus Pargmann }
44040f099e3SMarkus Pargmann 
4419ecb8875SAjay Kumar Gupta static int dsps_musb_init(struct musb *musb)
4429ecb8875SAjay Kumar Gupta {
4439ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
444db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
44597238b35SSebastian Andrzej Siewior 	struct platform_device *parent = to_platform_device(dev->parent);
4469ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
44797238b35SSebastian Andrzej Siewior 	void __iomem *reg_base;
44897238b35SSebastian Andrzej Siewior 	struct resource *r;
4499ecb8875SAjay Kumar Gupta 	u32 rev, val;
45040f099e3SMarkus Pargmann 	int ret;
4519ecb8875SAjay Kumar Gupta 
45297238b35SSebastian Andrzej Siewior 	r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
45397238b35SSebastian Andrzej Siewior 	reg_base = devm_ioremap_resource(dev, r);
45451ef74f6SJulia Lawall 	if (IS_ERR(reg_base))
45551ef74f6SJulia Lawall 		return PTR_ERR(reg_base);
45697238b35SSebastian Andrzej Siewior 	musb->ctrl_base = reg_base;
4579ecb8875SAjay Kumar Gupta 
458d7554226SAfzal Mohammed 	/* NOP driver needs change if supporting dual instance */
459983f3cabSFelipe Balbi 	musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "phys", 0);
46097238b35SSebastian Andrzej Siewior 	if (IS_ERR(musb->xceiv))
46197238b35SSebastian Andrzej Siewior 		return PTR_ERR(musb->xceiv);
4629ecb8875SAjay Kumar Gupta 
463bb90600dSTony Lindgren 	musb->phy = devm_phy_get(dev->parent, "usb2-phy");
464bb90600dSTony Lindgren 
4659ecb8875SAjay Kumar Gupta 	/* Returns zero if e.g. not clocked */
466086b2882SBin Liu 	rev = musb_readl(reg_base, wrp->revision);
46797238b35SSebastian Andrzej Siewior 	if (!rev)
46897238b35SSebastian Andrzej Siewior 		return -ENODEV;
4699ecb8875SAjay Kumar Gupta 
4707557a57fSSebastian Andrzej Siewior 	usb_phy_init(musb->xceiv);
471bb90600dSTony Lindgren 	if (IS_ERR(musb->phy))  {
472bb90600dSTony Lindgren 		musb->phy = NULL;
473bb90600dSTony Lindgren 	} else {
474bb90600dSTony Lindgren 		ret = phy_init(musb->phy);
475bb90600dSTony Lindgren 		if (ret < 0)
476bb90600dSTony Lindgren 			return ret;
477bb90600dSTony Lindgren 		ret = phy_power_on(musb->phy);
478bb90600dSTony Lindgren 		if (ret) {
479bb90600dSTony Lindgren 			phy_exit(musb->phy);
480bb90600dSTony Lindgren 			return ret;
481bb90600dSTony Lindgren 		}
482bb90600dSTony Lindgren 	}
483bb90600dSTony Lindgren 
484*05678497SKees Cook 	timer_setup(&glue->timer, otg_timer, 0);
4859ecb8875SAjay Kumar Gupta 
4869ecb8875SAjay Kumar Gupta 	/* Reset the musb */
487086b2882SBin Liu 	musb_writel(reg_base, wrp->control, (1 << wrp->reset));
4889ecb8875SAjay Kumar Gupta 
4899ecb8875SAjay Kumar Gupta 	musb->isr = dsps_interrupt;
4909ecb8875SAjay Kumar Gupta 
4919ecb8875SAjay Kumar Gupta 	/* reset the otgdisable bit, needed for host mode to work */
492086b2882SBin Liu 	val = musb_readl(reg_base, wrp->phy_utmi);
4939ecb8875SAjay Kumar Gupta 	val &= ~(1 << wrp->otg_disable);
494086b2882SBin Liu 	musb_writel(musb->ctrl_base, wrp->phy_utmi, val);
4959ecb8875SAjay Kumar Gupta 
496371254ceSGeorge Cherian 	/*
497371254ceSGeorge Cherian 	 *  Check whether the dsps version has babble control enabled.
498371254ceSGeorge Cherian 	 * In latest silicon revision the babble control logic is enabled.
499371254ceSGeorge Cherian 	 * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control
500371254ceSGeorge Cherian 	 * logic enabled.
501371254ceSGeorge Cherian 	 */
502086b2882SBin Liu 	val = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
503f860f0b1SFelipe Balbi 	if (val & MUSB_BABBLE_RCV_DISABLE) {
504371254ceSGeorge Cherian 		glue->sw_babble_enabled = true;
505371254ceSGeorge Cherian 		val |= MUSB_BABBLE_SW_SESSION_CTRL;
506086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
507371254ceSGeorge Cherian 	}
508371254ceSGeorge Cherian 
509369469a9STony Lindgren 	dsps_mod_timer(glue, -1);
5102f3fd2c5STony Lindgren 
511e94a7369SSaurabh Karajgaonkar 	return dsps_musb_dbg_init(musb, glue);
5129ecb8875SAjay Kumar Gupta }
5139ecb8875SAjay Kumar Gupta 
5149ecb8875SAjay Kumar Gupta static int dsps_musb_exit(struct musb *musb)
5159ecb8875SAjay Kumar Gupta {
5169ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
517db4a9320SB, Ravi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
5189ecb8875SAjay Kumar Gupta 
51997238b35SSebastian Andrzej Siewior 	del_timer_sync(&glue->timer);
5207557a57fSSebastian Andrzej Siewior 	usb_phy_shutdown(musb->xceiv);
521bb90600dSTony Lindgren 	phy_power_off(musb->phy);
522bb90600dSTony Lindgren 	phy_exit(musb->phy);
5230fca91b8SDaniel Mack 	debugfs_remove_recursive(glue->dbgfs_root);
5240fca91b8SDaniel Mack 
5259ecb8875SAjay Kumar Gupta 	return 0;
5269ecb8875SAjay Kumar Gupta }
5279ecb8875SAjay Kumar Gupta 
528943c1397SFelipe Balbi static int dsps_musb_set_mode(struct musb *musb, u8 mode)
529943c1397SFelipe Balbi {
530943c1397SFelipe Balbi 	struct device *dev = musb->controller;
531943c1397SFelipe Balbi 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
532943c1397SFelipe Balbi 	const struct dsps_musb_wrapper *wrp = glue->wrp;
533943c1397SFelipe Balbi 	void __iomem *ctrl_base = musb->ctrl_base;
534943c1397SFelipe Balbi 	u32 reg;
535943c1397SFelipe Balbi 
536086b2882SBin Liu 	reg = musb_readl(ctrl_base, wrp->mode);
537943c1397SFelipe Balbi 
538943c1397SFelipe Balbi 	switch (mode) {
539943c1397SFelipe Balbi 	case MUSB_HOST:
540943c1397SFelipe Balbi 		reg &= ~(1 << wrp->iddig);
541943c1397SFelipe Balbi 
542943c1397SFelipe Balbi 		/*
543943c1397SFelipe Balbi 		 * if we're setting mode to host-only or device-only, we're
544943c1397SFelipe Balbi 		 * going to ignore whatever the PHY sends us and just force
545943c1397SFelipe Balbi 		 * ID pin status by SW
546943c1397SFelipe Balbi 		 */
547943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig_mux);
548943c1397SFelipe Balbi 
549086b2882SBin Liu 		musb_writel(ctrl_base, wrp->mode, reg);
550086b2882SBin Liu 		musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
551943c1397SFelipe Balbi 		break;
552943c1397SFelipe Balbi 	case MUSB_PERIPHERAL:
553943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig);
554943c1397SFelipe Balbi 
555943c1397SFelipe Balbi 		/*
556943c1397SFelipe Balbi 		 * if we're setting mode to host-only or device-only, we're
557943c1397SFelipe Balbi 		 * going to ignore whatever the PHY sends us and just force
558943c1397SFelipe Balbi 		 * ID pin status by SW
559943c1397SFelipe Balbi 		 */
560943c1397SFelipe Balbi 		reg |= (1 << wrp->iddig_mux);
561943c1397SFelipe Balbi 
562086b2882SBin Liu 		musb_writel(ctrl_base, wrp->mode, reg);
563943c1397SFelipe Balbi 		break;
564943c1397SFelipe Balbi 	case MUSB_OTG:
565086b2882SBin Liu 		musb_writel(ctrl_base, wrp->phy_utmi, 0x02);
566943c1397SFelipe Balbi 		break;
567943c1397SFelipe Balbi 	default:
568943c1397SFelipe Balbi 		dev_err(glue->dev, "unsupported mode %d\n", mode);
569943c1397SFelipe Balbi 		return -EINVAL;
570943c1397SFelipe Balbi 	}
571943c1397SFelipe Balbi 
572943c1397SFelipe Balbi 	return 0;
573943c1397SFelipe Balbi }
574943c1397SFelipe Balbi 
5753709ffcaSFelipe Balbi static bool dsps_sw_babble_control(struct musb *musb)
576371254ceSGeorge Cherian {
577371254ceSGeorge Cherian 	u8 babble_ctl;
578371254ceSGeorge Cherian 	bool session_restart =  false;
579371254ceSGeorge Cherian 
580086b2882SBin Liu 	babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
581371254ceSGeorge Cherian 	dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n",
582371254ceSGeorge Cherian 		babble_ctl);
583371254ceSGeorge Cherian 	/*
584371254ceSGeorge Cherian 	 * check line monitor flag to check whether babble is
585371254ceSGeorge Cherian 	 * due to noise
586371254ceSGeorge Cherian 	 */
587371254ceSGeorge Cherian 	dev_dbg(musb->controller, "STUCK_J is %s\n",
588371254ceSGeorge Cherian 		babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset");
589371254ceSGeorge Cherian 
590371254ceSGeorge Cherian 	if (babble_ctl & MUSB_BABBLE_STUCK_J) {
591371254ceSGeorge Cherian 		int timeout = 10;
592371254ceSGeorge Cherian 
593371254ceSGeorge Cherian 		/*
594371254ceSGeorge Cherian 		 * babble is due to noise, then set transmit idle (d7 bit)
595371254ceSGeorge Cherian 		 * to resume normal operation
596371254ceSGeorge Cherian 		 */
597086b2882SBin Liu 		babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
598371254ceSGeorge Cherian 		babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE;
599086b2882SBin Liu 		musb_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl);
600371254ceSGeorge Cherian 
601371254ceSGeorge Cherian 		/* wait till line monitor flag cleared */
602371254ceSGeorge Cherian 		dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n");
603371254ceSGeorge Cherian 		do {
604086b2882SBin Liu 			babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL);
605371254ceSGeorge Cherian 			udelay(1);
606371254ceSGeorge Cherian 		} while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--);
607371254ceSGeorge Cherian 
608371254ceSGeorge Cherian 		/* check whether stuck_at_j bit cleared */
609371254ceSGeorge Cherian 		if (babble_ctl & MUSB_BABBLE_STUCK_J) {
610371254ceSGeorge Cherian 			/*
611371254ceSGeorge Cherian 			 * real babble condition has occurred
612371254ceSGeorge Cherian 			 * restart the controller to start the
613371254ceSGeorge Cherian 			 * session again
614371254ceSGeorge Cherian 			 */
615371254ceSGeorge Cherian 			dev_dbg(musb->controller, "J not cleared, misc (%x)\n",
616371254ceSGeorge Cherian 				babble_ctl);
617371254ceSGeorge Cherian 			session_restart = true;
618371254ceSGeorge Cherian 		}
619371254ceSGeorge Cherian 	} else {
620371254ceSGeorge Cherian 		session_restart = true;
621371254ceSGeorge Cherian 	}
622371254ceSGeorge Cherian 
623371254ceSGeorge Cherian 	return session_restart;
624371254ceSGeorge Cherian }
625371254ceSGeorge Cherian 
626b28a6432SFelipe Balbi static int dsps_musb_recover(struct musb *musb)
6271d57de30SDaniel Mack {
6281d57de30SDaniel Mack 	struct device *dev = musb->controller;
6291d57de30SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
630011d0dd5SFelipe Balbi 	int session_restart = 0;
6311d57de30SDaniel Mack 
632371254ceSGeorge Cherian 	if (glue->sw_babble_enabled)
6333709ffcaSFelipe Balbi 		session_restart = dsps_sw_babble_control(musb);
634011d0dd5SFelipe Balbi 	else
635371254ceSGeorge Cherian 		session_restart = 1;
63656700178SGeorge Cherian 
637d0cddae7SFelipe Balbi 	return session_restart ? 0 : -EPIPE;
6381d57de30SDaniel Mack }
6391d57de30SDaniel Mack 
6403e457371STony Lindgren /* Similar to am35x, dm81xx support only 32-bit read operation */
6413e457371STony Lindgren static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
6423e457371STony Lindgren {
6433e457371STony Lindgren 	void __iomem *fifo = hw_ep->fifo;
6443e457371STony Lindgren 
6453e457371STony Lindgren 	if (len >= 4) {
646d30323f8STony Lindgren 		ioread32_rep(fifo, dst, len >> 2);
6473e457371STony Lindgren 		dst += len & ~0x03;
6483e457371STony Lindgren 		len &= 0x03;
6493e457371STony Lindgren 	}
6503e457371STony Lindgren 
6513e457371STony Lindgren 	/* Read any remaining 1 to 3 bytes */
6523e457371STony Lindgren 	if (len > 0) {
6533e457371STony Lindgren 		u32 val = musb_readl(fifo, 0);
6543e457371STony Lindgren 		memcpy(dst, &val, len);
6553e457371STony Lindgren 	}
6563e457371STony Lindgren }
6573e457371STony Lindgren 
65825534828SAlexandre Bailon #ifdef CONFIG_USB_TI_CPPI41_DMA
65925534828SAlexandre Bailon static void dsps_dma_controller_callback(struct dma_controller *c)
66025534828SAlexandre Bailon {
66125534828SAlexandre Bailon 	struct musb *musb = c->musb;
66225534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
66325534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
66425534828SAlexandre Bailon 	u32 status;
66525534828SAlexandre Bailon 
66625534828SAlexandre Bailon 	status = musb_readl(usbss_base, USBSS_IRQ_STATUS);
66725534828SAlexandre Bailon 	if (status & USBSS_IRQ_PD_COMP)
66825534828SAlexandre Bailon 		musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP);
66925534828SAlexandre Bailon }
67025534828SAlexandre Bailon 
67125534828SAlexandre Bailon static struct dma_controller *
67225534828SAlexandre Bailon dsps_dma_controller_create(struct musb *musb, void __iomem *base)
67325534828SAlexandre Bailon {
67425534828SAlexandre Bailon 	struct dma_controller *controller;
67525534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
67625534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
67725534828SAlexandre Bailon 
67825534828SAlexandre Bailon 	controller = cppi41_dma_controller_create(musb, base);
67925534828SAlexandre Bailon 	if (IS_ERR_OR_NULL(controller))
68025534828SAlexandre Bailon 		return controller;
68125534828SAlexandre Bailon 
68225534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
68325534828SAlexandre Bailon 	controller->dma_callback = dsps_dma_controller_callback;
68425534828SAlexandre Bailon 
68525534828SAlexandre Bailon 	return controller;
68625534828SAlexandre Bailon }
68725534828SAlexandre Bailon 
68825534828SAlexandre Bailon static void dsps_dma_controller_destroy(struct dma_controller *c)
68925534828SAlexandre Bailon {
69025534828SAlexandre Bailon 	struct musb *musb = c->musb;
69125534828SAlexandre Bailon 	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
69225534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
69325534828SAlexandre Bailon 
69425534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
69525534828SAlexandre Bailon 	cppi41_dma_controller_destroy(c);
69625534828SAlexandre Bailon }
69725534828SAlexandre Bailon 
69825534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
69925534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue)
70025534828SAlexandre Bailon {
70125534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
70225534828SAlexandre Bailon 
70325534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
70425534828SAlexandre Bailon }
70525534828SAlexandre Bailon 
70625534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue)
70725534828SAlexandre Bailon {
70825534828SAlexandre Bailon 	void __iomem *usbss_base = glue->usbss_base;
70925534828SAlexandre Bailon 
71025534828SAlexandre Bailon 	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP);
71125534828SAlexandre Bailon }
71225534828SAlexandre Bailon #endif
71325534828SAlexandre Bailon #else /* CONFIG_USB_TI_CPPI41_DMA */
71425534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP
71525534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue) {}
71625534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue) {}
71725534828SAlexandre Bailon #endif
71825534828SAlexandre Bailon #endif /* CONFIG_USB_TI_CPPI41_DMA */
71925534828SAlexandre Bailon 
7209ecb8875SAjay Kumar Gupta static struct musb_platform_ops dsps_ops = {
721f8e9f34fSTony Lindgren 	.quirks		= MUSB_DMA_CPPI41 | MUSB_INDEXED_EP,
7229ecb8875SAjay Kumar Gupta 	.init		= dsps_musb_init,
7239ecb8875SAjay Kumar Gupta 	.exit		= dsps_musb_exit,
7249ecb8875SAjay Kumar Gupta 
7257f6283edSTony Lindgren #ifdef CONFIG_USB_TI_CPPI41_DMA
72625534828SAlexandre Bailon 	.dma_init	= dsps_dma_controller_create,
72725534828SAlexandre Bailon 	.dma_exit	= dsps_dma_controller_destroy,
7287f6283edSTony Lindgren #endif
7299ecb8875SAjay Kumar Gupta 	.enable		= dsps_musb_enable,
7309ecb8875SAjay Kumar Gupta 	.disable	= dsps_musb_disable,
7319ecb8875SAjay Kumar Gupta 
732943c1397SFelipe Balbi 	.set_mode	= dsps_musb_set_mode,
733b28a6432SFelipe Balbi 	.recover	= dsps_musb_recover,
734c48400baSBin Liu 	.clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
7359ecb8875SAjay Kumar Gupta };
7369ecb8875SAjay Kumar Gupta 
7379ecb8875SAjay Kumar Gupta static u64 musb_dmamask = DMA_BIT_MASK(32);
7389ecb8875SAjay Kumar Gupta 
73997238b35SSebastian Andrzej Siewior static int get_int_prop(struct device_node *dn, const char *s)
7409ecb8875SAjay Kumar Gupta {
74197238b35SSebastian Andrzej Siewior 	int ret;
74297238b35SSebastian Andrzej Siewior 	u32 val;
74397238b35SSebastian Andrzej Siewior 
74497238b35SSebastian Andrzej Siewior 	ret = of_property_read_u32(dn, s, &val);
74597238b35SSebastian Andrzej Siewior 	if (ret)
74697238b35SSebastian Andrzej Siewior 		return 0;
74797238b35SSebastian Andrzej Siewior 	return val;
74897238b35SSebastian Andrzej Siewior }
74997238b35SSebastian Andrzej Siewior 
750c031a7d4SSebastian Andrzej Siewior static int get_musb_port_mode(struct device *dev)
751c031a7d4SSebastian Andrzej Siewior {
752c031a7d4SSebastian Andrzej Siewior 	enum usb_dr_mode mode;
753c031a7d4SSebastian Andrzej Siewior 
75406e7114fSHeikki Krogerus 	mode = usb_get_dr_mode(dev);
755c031a7d4SSebastian Andrzej Siewior 	switch (mode) {
756c031a7d4SSebastian Andrzej Siewior 	case USB_DR_MODE_HOST:
757c031a7d4SSebastian Andrzej Siewior 		return MUSB_PORT_MODE_HOST;
758c031a7d4SSebastian Andrzej Siewior 
759c031a7d4SSebastian Andrzej Siewior 	case USB_DR_MODE_PERIPHERAL:
760c031a7d4SSebastian Andrzej Siewior 		return MUSB_PORT_MODE_GADGET;
761c031a7d4SSebastian Andrzej Siewior 
762c031a7d4SSebastian Andrzej Siewior 	case USB_DR_MODE_UNKNOWN:
763c031a7d4SSebastian Andrzej Siewior 	case USB_DR_MODE_OTG:
764c031a7d4SSebastian Andrzej Siewior 	default:
765c031a7d4SSebastian Andrzej Siewior 		return MUSB_PORT_MODE_DUAL_ROLE;
7662b84f92bSJoe Perches 	}
767c031a7d4SSebastian Andrzej Siewior }
768c031a7d4SSebastian Andrzej Siewior 
76997238b35SSebastian Andrzej Siewior static int dsps_create_musb_pdev(struct dsps_glue *glue,
77097238b35SSebastian Andrzej Siewior 		struct platform_device *parent)
77197238b35SSebastian Andrzej Siewior {
77297238b35SSebastian Andrzej Siewior 	struct musb_hdrc_platform_data pdata;
77397238b35SSebastian Andrzej Siewior 	struct resource	resources[2];
774c031a7d4SSebastian Andrzej Siewior 	struct resource	*res;
77597238b35SSebastian Andrzej Siewior 	struct device *dev = &parent->dev;
77665145677SAjay Kumar Gupta 	struct musb_hdrc_config	*config;
7779ecb8875SAjay Kumar Gupta 	struct platform_device *musb;
77897238b35SSebastian Andrzej Siewior 	struct device_node *dn = parent->dev.of_node;
779606bf4d5STony Lindgren 	int ret, val;
7809ecb8875SAjay Kumar Gupta 
78197238b35SSebastian Andrzej Siewior 	memset(resources, 0, sizeof(resources));
782c031a7d4SSebastian Andrzej Siewior 	res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc");
783c031a7d4SSebastian Andrzej Siewior 	if (!res) {
78497238b35SSebastian Andrzej Siewior 		dev_err(dev, "failed to get memory.\n");
785c031a7d4SSebastian Andrzej Siewior 		return -EINVAL;
7869ecb8875SAjay Kumar Gupta 	}
787c031a7d4SSebastian Andrzej Siewior 	resources[0] = *res;
78897238b35SSebastian Andrzej Siewior 
789c031a7d4SSebastian Andrzej Siewior 	res = platform_get_resource_byname(parent, IORESOURCE_IRQ, "mc");
790c031a7d4SSebastian Andrzej Siewior 	if (!res) {
79197238b35SSebastian Andrzej Siewior 		dev_err(dev, "failed to get irq.\n");
792c031a7d4SSebastian Andrzej Siewior 		return -EINVAL;
79397238b35SSebastian Andrzej Siewior 	}
794c031a7d4SSebastian Andrzej Siewior 	resources[1] = *res;
7959ecb8875SAjay Kumar Gupta 
79665b3d52dSB, Ravi 	/* allocate the child platform device */
79745abfa68SBin Liu 	musb = platform_device_alloc("musb-hdrc",
79845abfa68SBin Liu 			(resources[0].start & 0xFFF) == 0x400 ? 0 : 1);
79965b3d52dSB, Ravi 	if (!musb) {
80065b3d52dSB, Ravi 		dev_err(dev, "failed to allocate musb device\n");
80197238b35SSebastian Andrzej Siewior 		return -ENOMEM;
80265b3d52dSB, Ravi 	}
8039ecb8875SAjay Kumar Gupta 
8049ecb8875SAjay Kumar Gupta 	musb->dev.parent		= dev;
8059ecb8875SAjay Kumar Gupta 	musb->dev.dma_mask		= &musb_dmamask;
8069ecb8875SAjay Kumar Gupta 	musb->dev.coherent_dma_mask	= musb_dmamask;
8079ecb8875SAjay Kumar Gupta 
80897238b35SSebastian Andrzej Siewior 	glue->musb = musb;
8099ecb8875SAjay Kumar Gupta 
81097238b35SSebastian Andrzej Siewior 	ret = platform_device_add_resources(musb, resources,
81197238b35SSebastian Andrzej Siewior 			ARRAY_SIZE(resources));
8129ecb8875SAjay Kumar Gupta 	if (ret) {
8139ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add resources\n");
81497238b35SSebastian Andrzej Siewior 		goto err;
8159ecb8875SAjay Kumar Gupta 	}
8169ecb8875SAjay Kumar Gupta 
81797238b35SSebastian Andrzej Siewior 	config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL);
81865145677SAjay Kumar Gupta 	if (!config) {
819b25e5f1cSWei Yongjun 		ret = -ENOMEM;
82097238b35SSebastian Andrzej Siewior 		goto err;
82165145677SAjay Kumar Gupta 	}
82297238b35SSebastian Andrzej Siewior 	pdata.config = config;
82397238b35SSebastian Andrzej Siewior 	pdata.platform_ops = &dsps_ops;
82465145677SAjay Kumar Gupta 
825c031a7d4SSebastian Andrzej Siewior 	config->num_eps = get_int_prop(dn, "mentor,num-eps");
826c031a7d4SSebastian Andrzej Siewior 	config->ram_bits = get_int_prop(dn, "mentor,ram-bits");
827869c5978SDaniel Mack 	config->host_port_deassert_reset_at_resume = 1;
828c031a7d4SSebastian Andrzej Siewior 	pdata.mode = get_musb_port_mode(dev);
829c031a7d4SSebastian Andrzej Siewior 	/* DT keeps this entry in mA, musb expects it as per USB spec */
830c031a7d4SSebastian Andrzej Siewior 	pdata.power = get_int_prop(dn, "mentor,power") / 2;
831606bf4d5STony Lindgren 
832606bf4d5STony Lindgren 	ret = of_property_read_u32(dn, "mentor,multipoint", &val);
833606bf4d5STony Lindgren 	if (!ret && val)
834606bf4d5STony Lindgren 		config->multipoint = true;
83565145677SAjay Kumar Gupta 
83663863b98SHeikki Krogerus 	config->maximum_speed = usb_get_maximum_speed(&parent->dev);
83741932b9bSBin Liu 	switch (config->maximum_speed) {
83841932b9bSBin Liu 	case USB_SPEED_LOW:
83941932b9bSBin Liu 	case USB_SPEED_FULL:
84041932b9bSBin Liu 		break;
84141932b9bSBin Liu 	case USB_SPEED_SUPER:
84241932b9bSBin Liu 		dev_warn(dev, "ignore incorrect maximum_speed "
84341932b9bSBin Liu 				"(super-speed) setting in dts");
84441932b9bSBin Liu 		/* fall through */
84541932b9bSBin Liu 	default:
84641932b9bSBin Liu 		config->maximum_speed = USB_SPEED_HIGH;
84741932b9bSBin Liu 	}
84841932b9bSBin Liu 
84997238b35SSebastian Andrzej Siewior 	ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
8509ecb8875SAjay Kumar Gupta 	if (ret) {
8519ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add platform_data\n");
85297238b35SSebastian Andrzej Siewior 		goto err;
8539ecb8875SAjay Kumar Gupta 	}
8549ecb8875SAjay Kumar Gupta 
8559ecb8875SAjay Kumar Gupta 	ret = platform_device_add(musb);
8569ecb8875SAjay Kumar Gupta 	if (ret) {
8579ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to register musb device\n");
85897238b35SSebastian Andrzej Siewior 		goto err;
8599ecb8875SAjay Kumar Gupta 	}
8609ecb8875SAjay Kumar Gupta 	return 0;
8619ecb8875SAjay Kumar Gupta 
86297238b35SSebastian Andrzej Siewior err:
8639ecb8875SAjay Kumar Gupta 	platform_device_put(musb);
8649ecb8875SAjay Kumar Gupta 	return ret;
8659ecb8875SAjay Kumar Gupta }
8669ecb8875SAjay Kumar Gupta 
867369469a9STony Lindgren static irqreturn_t dsps_vbus_threaded_irq(int irq, void *priv)
868369469a9STony Lindgren {
869369469a9STony Lindgren 	struct dsps_glue *glue = priv;
870369469a9STony Lindgren 	struct musb *musb = platform_get_drvdata(glue->musb);
871369469a9STony Lindgren 
872369469a9STony Lindgren 	if (!musb)
873369469a9STony Lindgren 		return IRQ_NONE;
874369469a9STony Lindgren 
875369469a9STony Lindgren 	dev_dbg(glue->dev, "VBUS interrupt\n");
876369469a9STony Lindgren 	dsps_mod_timer(glue, 0);
877369469a9STony Lindgren 
878369469a9STony Lindgren 	return IRQ_HANDLED;
879369469a9STony Lindgren }
880369469a9STony Lindgren 
881369469a9STony Lindgren static int dsps_setup_optional_vbus_irq(struct platform_device *pdev,
882369469a9STony Lindgren 					struct dsps_glue *glue)
883369469a9STony Lindgren {
884369469a9STony Lindgren 	int error;
885369469a9STony Lindgren 
886369469a9STony Lindgren 	glue->vbus_irq = platform_get_irq_byname(pdev, "vbus");
887369469a9STony Lindgren 	if (glue->vbus_irq == -EPROBE_DEFER)
888369469a9STony Lindgren 		return -EPROBE_DEFER;
889369469a9STony Lindgren 
890369469a9STony Lindgren 	if (glue->vbus_irq <= 0) {
891369469a9STony Lindgren 		glue->vbus_irq = 0;
892369469a9STony Lindgren 		return 0;
893369469a9STony Lindgren 	}
894369469a9STony Lindgren 
895369469a9STony Lindgren 	error = devm_request_threaded_irq(glue->dev, glue->vbus_irq,
896369469a9STony Lindgren 					  NULL, dsps_vbus_threaded_irq,
897369469a9STony Lindgren 					  IRQF_ONESHOT,
898369469a9STony Lindgren 					  "vbus", glue);
899369469a9STony Lindgren 	if (error) {
900369469a9STony Lindgren 		glue->vbus_irq = 0;
901369469a9STony Lindgren 		return error;
902369469a9STony Lindgren 	}
903369469a9STony Lindgren 	dev_dbg(glue->dev, "VBUS irq %i configured\n", glue->vbus_irq);
904369469a9STony Lindgren 
905369469a9STony Lindgren 	return 0;
906369469a9STony Lindgren }
907369469a9STony Lindgren 
90841ac7b3aSBill Pemberton static int dsps_probe(struct platform_device *pdev)
9099ecb8875SAjay Kumar Gupta {
91065145677SAjay Kumar Gupta 	const struct of_device_id *match;
91165145677SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp;
9129ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue;
91397238b35SSebastian Andrzej Siewior 	int ret;
9149ecb8875SAjay Kumar Gupta 
9154fc4b274SSebastian Andrzej Siewior 	if (!strcmp(pdev->name, "musb-hdrc"))
9164fc4b274SSebastian Andrzej Siewior 		return -ENODEV;
9174fc4b274SSebastian Andrzej Siewior 
918cc506036SFelipe Balbi 	match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
91965145677SAjay Kumar Gupta 	if (!match) {
92065145677SAjay Kumar Gupta 		dev_err(&pdev->dev, "fail to get matching of_match struct\n");
92197238b35SSebastian Andrzej Siewior 		return -EINVAL;
92265145677SAjay Kumar Gupta 	}
92365145677SAjay Kumar Gupta 	wrp = match->data;
9249ecb8875SAjay Kumar Gupta 
9253e457371STony Lindgren 	if (of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816"))
9263e457371STony Lindgren 		dsps_ops.read_fifo = dsps_read_fifo32;
9273e457371STony Lindgren 
9289ecb8875SAjay Kumar Gupta 	/* allocate glue */
929de9db572SMarkus Pargmann 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
9300816ea2fSPeter Chen 	if (!glue)
93197238b35SSebastian Andrzej Siewior 		return -ENOMEM;
9329ecb8875SAjay Kumar Gupta 
9339ecb8875SAjay Kumar Gupta 	glue->dev = &pdev->dev;
93497238b35SSebastian Andrzej Siewior 	glue->wrp = wrp;
93525534828SAlexandre Bailon 	glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0);
93625534828SAlexandre Bailon 	if (!glue->usbss_base)
93725534828SAlexandre Bailon 		return -ENXIO;
9389ecb8875SAjay Kumar Gupta 
939369469a9STony Lindgren 	if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {
940369469a9STony Lindgren 		ret = dsps_setup_optional_vbus_irq(pdev, glue);
941369469a9STony Lindgren 		if (ret)
9426b7ad496SBin Liu 			goto err_iounmap;
943369469a9STony Lindgren 	}
944369469a9STony Lindgren 
9459ecb8875SAjay Kumar Gupta 	platform_set_drvdata(pdev, glue);
9469ecb8875SAjay Kumar Gupta 	pm_runtime_enable(&pdev->dev);
94797238b35SSebastian Andrzej Siewior 	ret = dsps_create_musb_pdev(glue, pdev);
94897238b35SSebastian Andrzej Siewior 	if (ret)
94924752917STony Lindgren 		goto err;
95065b3f50eSTony Lindgren 
9519ecb8875SAjay Kumar Gupta 	return 0;
9529ecb8875SAjay Kumar Gupta 
95324752917STony Lindgren err:
9540e38c4edSAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
9556b7ad496SBin Liu err_iounmap:
9566b7ad496SBin Liu 	iounmap(glue->usbss_base);
9579ecb8875SAjay Kumar Gupta 	return ret;
9589ecb8875SAjay Kumar Gupta }
95997238b35SSebastian Andrzej Siewior 
960fb4e98abSBill Pemberton static int dsps_remove(struct platform_device *pdev)
9619ecb8875SAjay Kumar Gupta {
9629ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
9639ecb8875SAjay Kumar Gupta 
96497238b35SSebastian Andrzej Siewior 	platform_device_unregister(glue->musb);
9659ecb8875SAjay Kumar Gupta 
9669ecb8875SAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
9676b7ad496SBin Liu 	iounmap(glue->usbss_base);
96840f099e3SMarkus Pargmann 
9699ecb8875SAjay Kumar Gupta 	return 0;
9709ecb8875SAjay Kumar Gupta }
9719ecb8875SAjay Kumar Gupta 
972fa7b4ca5SSebastian Andrzej Siewior static const struct dsps_musb_wrapper am33xx_driver_data = {
9739ecb8875SAjay Kumar Gupta 	.revision		= 0x00,
9749ecb8875SAjay Kumar Gupta 	.control		= 0x14,
9759ecb8875SAjay Kumar Gupta 	.status			= 0x18,
9769ecb8875SAjay Kumar Gupta 	.epintr_set		= 0x38,
9779ecb8875SAjay Kumar Gupta 	.epintr_clear		= 0x40,
9789ecb8875SAjay Kumar Gupta 	.epintr_status		= 0x30,
9799ecb8875SAjay Kumar Gupta 	.coreintr_set		= 0x3c,
9809ecb8875SAjay Kumar Gupta 	.coreintr_clear		= 0x44,
9819ecb8875SAjay Kumar Gupta 	.coreintr_status	= 0x34,
9829ecb8875SAjay Kumar Gupta 	.phy_utmi		= 0xe0,
9839ecb8875SAjay Kumar Gupta 	.mode			= 0xe8,
984b991f9b7SDaniel Mack 	.tx_mode		= 0x70,
985b991f9b7SDaniel Mack 	.rx_mode		= 0x74,
9869ecb8875SAjay Kumar Gupta 	.reset			= 0,
9879ecb8875SAjay Kumar Gupta 	.otg_disable		= 21,
9889ecb8875SAjay Kumar Gupta 	.iddig			= 8,
989943c1397SFelipe Balbi 	.iddig_mux		= 7,
9909ecb8875SAjay Kumar Gupta 	.usb_shift		= 0,
9919ecb8875SAjay Kumar Gupta 	.usb_mask		= 0x1ff,
9929ecb8875SAjay Kumar Gupta 	.usb_bitmap		= (0x1ff << 0),
9939ecb8875SAjay Kumar Gupta 	.drvvbus		= 8,
9949ecb8875SAjay Kumar Gupta 	.txep_shift		= 0,
9959ecb8875SAjay Kumar Gupta 	.txep_mask		= 0xffff,
9969ecb8875SAjay Kumar Gupta 	.txep_bitmap		= (0xffff << 0),
9979ecb8875SAjay Kumar Gupta 	.rxep_shift		= 16,
9989ecb8875SAjay Kumar Gupta 	.rxep_mask		= 0xfffe,
9999ecb8875SAjay Kumar Gupta 	.rxep_bitmap		= (0xfffe << 16),
10009e204d88SFelipe Balbi 	.poll_timeout		= 2000, /* ms */
10019ecb8875SAjay Kumar Gupta };
10029ecb8875SAjay Kumar Gupta 
10032f82686eSBill Pemberton static const struct of_device_id musb_dsps_of_match[] = {
100465145677SAjay Kumar Gupta 	{ .compatible = "ti,musb-am33xx",
10053e457371STony Lindgren 		.data = &am33xx_driver_data, },
10063e457371STony Lindgren 	{ .compatible = "ti,musb-dm816",
10073e457371STony Lindgren 		.data = &am33xx_driver_data, },
10089ecb8875SAjay Kumar Gupta 	{  },
10099ecb8875SAjay Kumar Gupta };
10109ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
10119ecb8875SAjay Kumar Gupta 
10125b783983SWolfram Sang #ifdef CONFIG_PM_SLEEP
1013869c5978SDaniel Mack static int dsps_suspend(struct device *dev)
1014869c5978SDaniel Mack {
1015869c5978SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev);
1016869c5978SDaniel Mack 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1017869c5978SDaniel Mack 	struct musb *musb = platform_get_drvdata(glue->musb);
1018f042e9cbSSebastian Andrzej Siewior 	void __iomem *mbase;
1019706d61b2SJohan Hovold 	int ret;
1020f042e9cbSSebastian Andrzej Siewior 
1021f042e9cbSSebastian Andrzej Siewior 	if (!musb)
1022f042e9cbSSebastian Andrzej Siewior 		/* This can happen if the musb device is in -EPROBE_DEFER */
1023f042e9cbSSebastian Andrzej Siewior 		return 0;
1024f042e9cbSSebastian Andrzej Siewior 
1025706d61b2SJohan Hovold 	ret = pm_runtime_get_sync(dev);
1026706d61b2SJohan Hovold 	if (ret < 0) {
1027706d61b2SJohan Hovold 		pm_runtime_put_noidle(dev);
1028706d61b2SJohan Hovold 		return ret;
1029706d61b2SJohan Hovold 	}
1030706d61b2SJohan Hovold 
1031706d61b2SJohan Hovold 	del_timer_sync(&glue->timer);
1032706d61b2SJohan Hovold 
1033f042e9cbSSebastian Andrzej Siewior 	mbase = musb->ctrl_base;
1034086b2882SBin Liu 	glue->context.control = musb_readl(mbase, wrp->control);
1035086b2882SBin Liu 	glue->context.epintr = musb_readl(mbase, wrp->epintr_set);
1036086b2882SBin Liu 	glue->context.coreintr = musb_readl(mbase, wrp->coreintr_set);
1037086b2882SBin Liu 	glue->context.phy_utmi = musb_readl(mbase, wrp->phy_utmi);
1038086b2882SBin Liu 	glue->context.mode = musb_readl(mbase, wrp->mode);
1039086b2882SBin Liu 	glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode);
1040086b2882SBin Liu 	glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode);
1041869c5978SDaniel Mack 
104225534828SAlexandre Bailon 	dsps_dma_controller_suspend(glue);
104325534828SAlexandre Bailon 
1044869c5978SDaniel Mack 	return 0;
1045869c5978SDaniel Mack }
1046869c5978SDaniel Mack 
1047869c5978SDaniel Mack static int dsps_resume(struct device *dev)
1048869c5978SDaniel Mack {
1049869c5978SDaniel Mack 	struct dsps_glue *glue = dev_get_drvdata(dev);
1050869c5978SDaniel Mack 	const struct dsps_musb_wrapper *wrp = glue->wrp;
1051869c5978SDaniel Mack 	struct musb *musb = platform_get_drvdata(glue->musb);
1052f042e9cbSSebastian Andrzej Siewior 	void __iomem *mbase;
1053869c5978SDaniel Mack 
1054f042e9cbSSebastian Andrzej Siewior 	if (!musb)
1055f042e9cbSSebastian Andrzej Siewior 		return 0;
1056f042e9cbSSebastian Andrzej Siewior 
105725534828SAlexandre Bailon 	dsps_dma_controller_resume(glue);
105825534828SAlexandre Bailon 
1059f042e9cbSSebastian Andrzej Siewior 	mbase = musb->ctrl_base;
1060086b2882SBin Liu 	musb_writel(mbase, wrp->control, glue->context.control);
1061086b2882SBin Liu 	musb_writel(mbase, wrp->epintr_set, glue->context.epintr);
1062086b2882SBin Liu 	musb_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
1063086b2882SBin Liu 	musb_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi);
1064086b2882SBin Liu 	musb_writel(mbase, wrp->mode, glue->context.mode);
1065086b2882SBin Liu 	musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
1066086b2882SBin Liu 	musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
1067e47d9254SAntoine Tenart 	if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
106853185b3aSSebastian Andrzej Siewior 	    musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
1069369469a9STony Lindgren 		dsps_mod_timer(glue, -1);
1070869c5978SDaniel Mack 
1071706d61b2SJohan Hovold 	pm_runtime_put(dev);
1072706d61b2SJohan Hovold 
1073869c5978SDaniel Mack 	return 0;
1074869c5978SDaniel Mack }
1075869c5978SDaniel Mack #endif
1076869c5978SDaniel Mack 
1077869c5978SDaniel Mack static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
1078869c5978SDaniel Mack 
10799ecb8875SAjay Kumar Gupta static struct platform_driver dsps_usbss_driver = {
10809ecb8875SAjay Kumar Gupta 	.probe		= dsps_probe,
10817690417dSBill Pemberton 	.remove         = dsps_remove,
10829ecb8875SAjay Kumar Gupta 	.driver         = {
10839ecb8875SAjay Kumar Gupta 		.name   = "musb-dsps",
1084869c5978SDaniel Mack 		.pm	= &dsps_pm_ops,
1085b432cb83SSachin Kamat 		.of_match_table	= musb_dsps_of_match,
10869ecb8875SAjay Kumar Gupta 	},
10879ecb8875SAjay Kumar Gupta };
10889ecb8875SAjay Kumar Gupta 
10899ecb8875SAjay Kumar Gupta MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
10909ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
10919ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
10929ecb8875SAjay Kumar Gupta MODULE_LICENSE("GPL v2");
10939ecb8875SAjay Kumar Gupta 
109497238b35SSebastian Andrzej Siewior module_platform_driver(dsps_usbss_driver);
1095