xref: /linux/drivers/usb/musb/musb_dsps.c (revision 9ecb887522a0483fdde8db7ec41d72b8235f2fe8)
1*9ecb8875SAjay Kumar Gupta /*
2*9ecb8875SAjay Kumar Gupta  * Texas Instruments DSPS platforms "glue layer"
3*9ecb8875SAjay Kumar Gupta  *
4*9ecb8875SAjay Kumar Gupta  * Copyright (C) 2012, by Texas Instruments
5*9ecb8875SAjay Kumar Gupta  *
6*9ecb8875SAjay Kumar Gupta  * Based on the am35x "glue layer" code.
7*9ecb8875SAjay Kumar Gupta  *
8*9ecb8875SAjay Kumar Gupta  * This file is part of the Inventra Controller Driver for Linux.
9*9ecb8875SAjay Kumar Gupta  *
10*9ecb8875SAjay Kumar Gupta  * The Inventra Controller Driver for Linux is free software; you
11*9ecb8875SAjay Kumar Gupta  * can redistribute it and/or modify it under the terms of the GNU
12*9ecb8875SAjay Kumar Gupta  * General Public License version 2 as published by the Free Software
13*9ecb8875SAjay Kumar Gupta  * Foundation.
14*9ecb8875SAjay Kumar Gupta  *
15*9ecb8875SAjay Kumar Gupta  * The Inventra Controller Driver for Linux is distributed in
16*9ecb8875SAjay Kumar Gupta  * the hope that it will be useful, but WITHOUT ANY WARRANTY;
17*9ecb8875SAjay Kumar Gupta  * without even the implied warranty of MERCHANTABILITY or
18*9ecb8875SAjay Kumar Gupta  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19*9ecb8875SAjay Kumar Gupta  * License for more details.
20*9ecb8875SAjay Kumar Gupta  *
21*9ecb8875SAjay Kumar Gupta  * You should have received a copy of the GNU General Public License
22*9ecb8875SAjay Kumar Gupta  * along with The Inventra Controller Driver for Linux ; if not,
23*9ecb8875SAjay Kumar Gupta  * write to the Free Software Foundation, Inc., 59 Temple Place,
24*9ecb8875SAjay Kumar Gupta  * Suite 330, Boston, MA  02111-1307  USA
25*9ecb8875SAjay Kumar Gupta  *
26*9ecb8875SAjay Kumar Gupta  * musb_dsps.c will be a common file for all the TI DSPS platforms
27*9ecb8875SAjay Kumar Gupta  * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
28*9ecb8875SAjay Kumar Gupta  * For now only ti81x is using this and in future davinci.c, am35x.c
29*9ecb8875SAjay Kumar Gupta  * da8xx.c would be merged to this file after testing.
30*9ecb8875SAjay Kumar Gupta  */
31*9ecb8875SAjay Kumar Gupta 
32*9ecb8875SAjay Kumar Gupta #include <linux/init.h>
33*9ecb8875SAjay Kumar Gupta #include <linux/io.h>
34*9ecb8875SAjay Kumar Gupta #include <linux/platform_device.h>
35*9ecb8875SAjay Kumar Gupta #include <linux/dma-mapping.h>
36*9ecb8875SAjay Kumar Gupta #include <linux/pm_runtime.h>
37*9ecb8875SAjay Kumar Gupta #include <linux/module.h>
38*9ecb8875SAjay Kumar Gupta 
39*9ecb8875SAjay Kumar Gupta #include <linux/of.h>
40*9ecb8875SAjay Kumar Gupta #include <linux/of_device.h>
41*9ecb8875SAjay Kumar Gupta #include <linux/of_address.h>
42*9ecb8875SAjay Kumar Gupta 
43*9ecb8875SAjay Kumar Gupta #include <plat/usb.h>
44*9ecb8875SAjay Kumar Gupta 
45*9ecb8875SAjay Kumar Gupta #include "musb_core.h"
46*9ecb8875SAjay Kumar Gupta 
47*9ecb8875SAjay Kumar Gupta /**
48*9ecb8875SAjay Kumar Gupta  * avoid using musb_readx()/musb_writex() as glue layer should not be
49*9ecb8875SAjay Kumar Gupta  * dependent on musb core layer symbols.
50*9ecb8875SAjay Kumar Gupta  */
51*9ecb8875SAjay Kumar Gupta static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
52*9ecb8875SAjay Kumar Gupta 	{ return __raw_readb(addr + offset); }
53*9ecb8875SAjay Kumar Gupta 
54*9ecb8875SAjay Kumar Gupta static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
55*9ecb8875SAjay Kumar Gupta 	{ return __raw_readl(addr + offset); }
56*9ecb8875SAjay Kumar Gupta 
57*9ecb8875SAjay Kumar Gupta static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
58*9ecb8875SAjay Kumar Gupta 	{ __raw_writeb(data, addr + offset); }
59*9ecb8875SAjay Kumar Gupta 
60*9ecb8875SAjay Kumar Gupta static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
61*9ecb8875SAjay Kumar Gupta 	{ __raw_writel(data, addr + offset); }
62*9ecb8875SAjay Kumar Gupta 
63*9ecb8875SAjay Kumar Gupta /**
64*9ecb8875SAjay Kumar Gupta  * DSPS musb wrapper register offset.
65*9ecb8875SAjay Kumar Gupta  * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
66*9ecb8875SAjay Kumar Gupta  * musb ips.
67*9ecb8875SAjay Kumar Gupta  */
68*9ecb8875SAjay Kumar Gupta struct dsps_musb_wrapper {
69*9ecb8875SAjay Kumar Gupta 	u16	revision;
70*9ecb8875SAjay Kumar Gupta 	u16	control;
71*9ecb8875SAjay Kumar Gupta 	u16	status;
72*9ecb8875SAjay Kumar Gupta 	u16	eoi;
73*9ecb8875SAjay Kumar Gupta 	u16	epintr_set;
74*9ecb8875SAjay Kumar Gupta 	u16	epintr_clear;
75*9ecb8875SAjay Kumar Gupta 	u16	epintr_status;
76*9ecb8875SAjay Kumar Gupta 	u16	coreintr_set;
77*9ecb8875SAjay Kumar Gupta 	u16	coreintr_clear;
78*9ecb8875SAjay Kumar Gupta 	u16	coreintr_status;
79*9ecb8875SAjay Kumar Gupta 	u16	phy_utmi;
80*9ecb8875SAjay Kumar Gupta 	u16	mode;
81*9ecb8875SAjay Kumar Gupta 
82*9ecb8875SAjay Kumar Gupta 	/* bit positions for control */
83*9ecb8875SAjay Kumar Gupta 	unsigned	reset:5;
84*9ecb8875SAjay Kumar Gupta 
85*9ecb8875SAjay Kumar Gupta 	/* bit positions for interrupt */
86*9ecb8875SAjay Kumar Gupta 	unsigned	usb_shift:5;
87*9ecb8875SAjay Kumar Gupta 	u32		usb_mask;
88*9ecb8875SAjay Kumar Gupta 	u32		usb_bitmap;
89*9ecb8875SAjay Kumar Gupta 	unsigned	drvvbus:5;
90*9ecb8875SAjay Kumar Gupta 
91*9ecb8875SAjay Kumar Gupta 	unsigned	txep_shift:5;
92*9ecb8875SAjay Kumar Gupta 	u32		txep_mask;
93*9ecb8875SAjay Kumar Gupta 	u32		txep_bitmap;
94*9ecb8875SAjay Kumar Gupta 
95*9ecb8875SAjay Kumar Gupta 	unsigned	rxep_shift:5;
96*9ecb8875SAjay Kumar Gupta 	u32		rxep_mask;
97*9ecb8875SAjay Kumar Gupta 	u32		rxep_bitmap;
98*9ecb8875SAjay Kumar Gupta 
99*9ecb8875SAjay Kumar Gupta 	/* bit positions for phy_utmi */
100*9ecb8875SAjay Kumar Gupta 	unsigned	otg_disable:5;
101*9ecb8875SAjay Kumar Gupta 
102*9ecb8875SAjay Kumar Gupta 	/* bit positions for mode */
103*9ecb8875SAjay Kumar Gupta 	unsigned	iddig:5;
104*9ecb8875SAjay Kumar Gupta 	/* miscellaneous stuff */
105*9ecb8875SAjay Kumar Gupta 	u32		musb_core_offset;
106*9ecb8875SAjay Kumar Gupta 	u8		poll_seconds;
107*9ecb8875SAjay Kumar Gupta };
108*9ecb8875SAjay Kumar Gupta 
109*9ecb8875SAjay Kumar Gupta /**
110*9ecb8875SAjay Kumar Gupta  * DSPS glue structure.
111*9ecb8875SAjay Kumar Gupta  */
112*9ecb8875SAjay Kumar Gupta struct dsps_glue {
113*9ecb8875SAjay Kumar Gupta 	struct device *dev;
114*9ecb8875SAjay Kumar Gupta 	struct platform_device *musb;	/* child musb pdev */
115*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
116*9ecb8875SAjay Kumar Gupta 	struct timer_list timer;	/* otg_workaround timer */
117*9ecb8875SAjay Kumar Gupta };
118*9ecb8875SAjay Kumar Gupta 
119*9ecb8875SAjay Kumar Gupta /**
120*9ecb8875SAjay Kumar Gupta  * dsps_musb_enable - enable interrupts
121*9ecb8875SAjay Kumar Gupta  */
122*9ecb8875SAjay Kumar Gupta static void dsps_musb_enable(struct musb *musb)
123*9ecb8875SAjay Kumar Gupta {
124*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
125*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
126*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
127*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
128*9ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
129*9ecb8875SAjay Kumar Gupta 	u32 epmask, coremask;
130*9ecb8875SAjay Kumar Gupta 
131*9ecb8875SAjay Kumar Gupta 	/* Workaround: setup IRQs through both register sets. */
132*9ecb8875SAjay Kumar Gupta 	epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
133*9ecb8875SAjay Kumar Gupta 	       ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
134*9ecb8875SAjay Kumar Gupta 	coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
135*9ecb8875SAjay Kumar Gupta 
136*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->epintr_set, epmask);
137*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->coreintr_set, coremask);
138*9ecb8875SAjay Kumar Gupta 	/* Force the DRVVBUS IRQ so we can start polling for ID change. */
139*9ecb8875SAjay Kumar Gupta 	if (is_otg_enabled(musb))
140*9ecb8875SAjay Kumar Gupta 		dsps_writel(reg_base, wrp->coreintr_set,
141*9ecb8875SAjay Kumar Gupta 			    (1 << wrp->drvvbus) << wrp->usb_shift);
142*9ecb8875SAjay Kumar Gupta }
143*9ecb8875SAjay Kumar Gupta 
144*9ecb8875SAjay Kumar Gupta /**
145*9ecb8875SAjay Kumar Gupta  * dsps_musb_disable - disable HDRC and flush interrupts
146*9ecb8875SAjay Kumar Gupta  */
147*9ecb8875SAjay Kumar Gupta static void dsps_musb_disable(struct musb *musb)
148*9ecb8875SAjay Kumar Gupta {
149*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
150*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
151*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
152*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
153*9ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
154*9ecb8875SAjay Kumar Gupta 
155*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
156*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->epintr_clear,
157*9ecb8875SAjay Kumar Gupta 			 wrp->txep_bitmap | wrp->rxep_bitmap);
158*9ecb8875SAjay Kumar Gupta 	dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
159*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->eoi, 0);
160*9ecb8875SAjay Kumar Gupta }
161*9ecb8875SAjay Kumar Gupta 
162*9ecb8875SAjay Kumar Gupta static void otg_timer(unsigned long _musb)
163*9ecb8875SAjay Kumar Gupta {
164*9ecb8875SAjay Kumar Gupta 	struct musb *musb = (void *)_musb;
165*9ecb8875SAjay Kumar Gupta 	void __iomem *mregs = musb->mregs;
166*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
167*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
168*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
169*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
170*9ecb8875SAjay Kumar Gupta 	u8 devctl;
171*9ecb8875SAjay Kumar Gupta 	unsigned long flags;
172*9ecb8875SAjay Kumar Gupta 
173*9ecb8875SAjay Kumar Gupta 	/*
174*9ecb8875SAjay Kumar Gupta 	 * We poll because DSPS IP's won't expose several OTG-critical
175*9ecb8875SAjay Kumar Gupta 	 * status change events (from the transceiver) otherwise.
176*9ecb8875SAjay Kumar Gupta 	 */
177*9ecb8875SAjay Kumar Gupta 	devctl = dsps_readb(mregs, MUSB_DEVCTL);
178*9ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
179*9ecb8875SAjay Kumar Gupta 				otg_state_string(musb->xceiv->state));
180*9ecb8875SAjay Kumar Gupta 
181*9ecb8875SAjay Kumar Gupta 	spin_lock_irqsave(&musb->lock, flags);
182*9ecb8875SAjay Kumar Gupta 	switch (musb->xceiv->state) {
183*9ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_BCON:
184*9ecb8875SAjay Kumar Gupta 		devctl &= ~MUSB_DEVCTL_SESSION;
185*9ecb8875SAjay Kumar Gupta 		dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
186*9ecb8875SAjay Kumar Gupta 
187*9ecb8875SAjay Kumar Gupta 		devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
188*9ecb8875SAjay Kumar Gupta 		if (devctl & MUSB_DEVCTL_BDEVICE) {
189*9ecb8875SAjay Kumar Gupta 			musb->xceiv->state = OTG_STATE_B_IDLE;
190*9ecb8875SAjay Kumar Gupta 			MUSB_DEV_MODE(musb);
191*9ecb8875SAjay Kumar Gupta 		} else {
192*9ecb8875SAjay Kumar Gupta 			musb->xceiv->state = OTG_STATE_A_IDLE;
193*9ecb8875SAjay Kumar Gupta 			MUSB_HST_MODE(musb);
194*9ecb8875SAjay Kumar Gupta 		}
195*9ecb8875SAjay Kumar Gupta 		break;
196*9ecb8875SAjay Kumar Gupta 	case OTG_STATE_A_WAIT_VFALL:
197*9ecb8875SAjay Kumar Gupta 		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
198*9ecb8875SAjay Kumar Gupta 		dsps_writel(musb->ctrl_base, wrp->coreintr_set,
199*9ecb8875SAjay Kumar Gupta 			    MUSB_INTR_VBUSERROR << wrp->usb_shift);
200*9ecb8875SAjay Kumar Gupta 		break;
201*9ecb8875SAjay Kumar Gupta 	case OTG_STATE_B_IDLE:
202*9ecb8875SAjay Kumar Gupta 		if (!is_peripheral_enabled(musb))
203*9ecb8875SAjay Kumar Gupta 			break;
204*9ecb8875SAjay Kumar Gupta 
205*9ecb8875SAjay Kumar Gupta 		devctl = dsps_readb(mregs, MUSB_DEVCTL);
206*9ecb8875SAjay Kumar Gupta 		if (devctl & MUSB_DEVCTL_BDEVICE)
207*9ecb8875SAjay Kumar Gupta 			mod_timer(&glue->timer,
208*9ecb8875SAjay Kumar Gupta 					jiffies + wrp->poll_seconds * HZ);
209*9ecb8875SAjay Kumar Gupta 		else
210*9ecb8875SAjay Kumar Gupta 			musb->xceiv->state = OTG_STATE_A_IDLE;
211*9ecb8875SAjay Kumar Gupta 		break;
212*9ecb8875SAjay Kumar Gupta 	default:
213*9ecb8875SAjay Kumar Gupta 		break;
214*9ecb8875SAjay Kumar Gupta 	}
215*9ecb8875SAjay Kumar Gupta 	spin_unlock_irqrestore(&musb->lock, flags);
216*9ecb8875SAjay Kumar Gupta }
217*9ecb8875SAjay Kumar Gupta 
218*9ecb8875SAjay Kumar Gupta static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
219*9ecb8875SAjay Kumar Gupta {
220*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
221*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
222*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
223*9ecb8875SAjay Kumar Gupta 	static unsigned long last_timer;
224*9ecb8875SAjay Kumar Gupta 
225*9ecb8875SAjay Kumar Gupta 	if (!is_otg_enabled(musb))
226*9ecb8875SAjay Kumar Gupta 		return;
227*9ecb8875SAjay Kumar Gupta 
228*9ecb8875SAjay Kumar Gupta 	if (timeout == 0)
229*9ecb8875SAjay Kumar Gupta 		timeout = jiffies + msecs_to_jiffies(3);
230*9ecb8875SAjay Kumar Gupta 
231*9ecb8875SAjay Kumar Gupta 	/* Never idle if active, or when VBUS timeout is not set as host */
232*9ecb8875SAjay Kumar Gupta 	if (musb->is_active || (musb->a_wait_bcon == 0 &&
233*9ecb8875SAjay Kumar Gupta 				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
234*9ecb8875SAjay Kumar Gupta 		dev_dbg(musb->controller, "%s active, deleting timer\n",
235*9ecb8875SAjay Kumar Gupta 				otg_state_string(musb->xceiv->state));
236*9ecb8875SAjay Kumar Gupta 		del_timer(&glue->timer);
237*9ecb8875SAjay Kumar Gupta 		last_timer = jiffies;
238*9ecb8875SAjay Kumar Gupta 		return;
239*9ecb8875SAjay Kumar Gupta 	}
240*9ecb8875SAjay Kumar Gupta 
241*9ecb8875SAjay Kumar Gupta 	if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) {
242*9ecb8875SAjay Kumar Gupta 		dev_dbg(musb->controller,
243*9ecb8875SAjay Kumar Gupta 			"Longer idle timer already pending, ignoring...\n");
244*9ecb8875SAjay Kumar Gupta 		return;
245*9ecb8875SAjay Kumar Gupta 	}
246*9ecb8875SAjay Kumar Gupta 	last_timer = timeout;
247*9ecb8875SAjay Kumar Gupta 
248*9ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
249*9ecb8875SAjay Kumar Gupta 		otg_state_string(musb->xceiv->state),
250*9ecb8875SAjay Kumar Gupta 			jiffies_to_msecs(timeout - jiffies));
251*9ecb8875SAjay Kumar Gupta 	mod_timer(&glue->timer, timeout);
252*9ecb8875SAjay Kumar Gupta }
253*9ecb8875SAjay Kumar Gupta 
254*9ecb8875SAjay Kumar Gupta static irqreturn_t dsps_interrupt(int irq, void *hci)
255*9ecb8875SAjay Kumar Gupta {
256*9ecb8875SAjay Kumar Gupta 	struct musb  *musb = hci;
257*9ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
258*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
259*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
260*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
261*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
262*9ecb8875SAjay Kumar Gupta 	unsigned long flags;
263*9ecb8875SAjay Kumar Gupta 	irqreturn_t ret = IRQ_NONE;
264*9ecb8875SAjay Kumar Gupta 	u32 epintr, usbintr;
265*9ecb8875SAjay Kumar Gupta 
266*9ecb8875SAjay Kumar Gupta 	spin_lock_irqsave(&musb->lock, flags);
267*9ecb8875SAjay Kumar Gupta 
268*9ecb8875SAjay Kumar Gupta 	/* Get endpoint interrupts */
269*9ecb8875SAjay Kumar Gupta 	epintr = dsps_readl(reg_base, wrp->epintr_status);
270*9ecb8875SAjay Kumar Gupta 	musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
271*9ecb8875SAjay Kumar Gupta 	musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
272*9ecb8875SAjay Kumar Gupta 
273*9ecb8875SAjay Kumar Gupta 	if (epintr)
274*9ecb8875SAjay Kumar Gupta 		dsps_writel(reg_base, wrp->epintr_status, epintr);
275*9ecb8875SAjay Kumar Gupta 
276*9ecb8875SAjay Kumar Gupta 	/* Get usb core interrupts */
277*9ecb8875SAjay Kumar Gupta 	usbintr = dsps_readl(reg_base, wrp->coreintr_status);
278*9ecb8875SAjay Kumar Gupta 	if (!usbintr && !epintr)
279*9ecb8875SAjay Kumar Gupta 		goto eoi;
280*9ecb8875SAjay Kumar Gupta 
281*9ecb8875SAjay Kumar Gupta 	musb->int_usb =	(usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
282*9ecb8875SAjay Kumar Gupta 	if (usbintr)
283*9ecb8875SAjay Kumar Gupta 		dsps_writel(reg_base, wrp->coreintr_status, usbintr);
284*9ecb8875SAjay Kumar Gupta 
285*9ecb8875SAjay Kumar Gupta 	dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
286*9ecb8875SAjay Kumar Gupta 			usbintr, epintr);
287*9ecb8875SAjay Kumar Gupta 	/*
288*9ecb8875SAjay Kumar Gupta 	 * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
289*9ecb8875SAjay Kumar Gupta 	 * DSPS IP's missing ID change IRQ.  We need an ID change IRQ to
290*9ecb8875SAjay Kumar Gupta 	 * switch appropriately between halves of the OTG state machine.
291*9ecb8875SAjay Kumar Gupta 	 * Managing DEVCTL.SESSION per Mentor docs requires that we know its
292*9ecb8875SAjay Kumar Gupta 	 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
293*9ecb8875SAjay Kumar Gupta 	 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
294*9ecb8875SAjay Kumar Gupta 	 */
295*9ecb8875SAjay Kumar Gupta 	if ((usbintr & MUSB_INTR_BABBLE) && is_host_enabled(musb))
296*9ecb8875SAjay Kumar Gupta 		pr_info("CAUTION: musb: Babble Interrupt Occured\n");
297*9ecb8875SAjay Kumar Gupta 
298*9ecb8875SAjay Kumar Gupta 	if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
299*9ecb8875SAjay Kumar Gupta 		int drvvbus = dsps_readl(reg_base, wrp->status);
300*9ecb8875SAjay Kumar Gupta 		void __iomem *mregs = musb->mregs;
301*9ecb8875SAjay Kumar Gupta 		u8 devctl = dsps_readb(mregs, MUSB_DEVCTL);
302*9ecb8875SAjay Kumar Gupta 		int err;
303*9ecb8875SAjay Kumar Gupta 
304*9ecb8875SAjay Kumar Gupta 		err = is_host_enabled(musb) && (musb->int_usb &
305*9ecb8875SAjay Kumar Gupta 						MUSB_INTR_VBUSERROR);
306*9ecb8875SAjay Kumar Gupta 		if (err) {
307*9ecb8875SAjay Kumar Gupta 			/*
308*9ecb8875SAjay Kumar Gupta 			 * The Mentor core doesn't debounce VBUS as needed
309*9ecb8875SAjay Kumar Gupta 			 * to cope with device connect current spikes. This
310*9ecb8875SAjay Kumar Gupta 			 * means it's not uncommon for bus-powered devices
311*9ecb8875SAjay Kumar Gupta 			 * to get VBUS errors during enumeration.
312*9ecb8875SAjay Kumar Gupta 			 *
313*9ecb8875SAjay Kumar Gupta 			 * This is a workaround, but newer RTL from Mentor
314*9ecb8875SAjay Kumar Gupta 			 * seems to allow a better one: "re"-starting sessions
315*9ecb8875SAjay Kumar Gupta 			 * without waiting for VBUS to stop registering in
316*9ecb8875SAjay Kumar Gupta 			 * devctl.
317*9ecb8875SAjay Kumar Gupta 			 */
318*9ecb8875SAjay Kumar Gupta 			musb->int_usb &= ~MUSB_INTR_VBUSERROR;
319*9ecb8875SAjay Kumar Gupta 			musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
320*9ecb8875SAjay Kumar Gupta 			mod_timer(&glue->timer,
321*9ecb8875SAjay Kumar Gupta 					jiffies + wrp->poll_seconds * HZ);
322*9ecb8875SAjay Kumar Gupta 			WARNING("VBUS error workaround (delay coming)\n");
323*9ecb8875SAjay Kumar Gupta 		} else if (is_host_enabled(musb) && drvvbus) {
324*9ecb8875SAjay Kumar Gupta 			musb->is_active = 1;
325*9ecb8875SAjay Kumar Gupta 			MUSB_HST_MODE(musb);
326*9ecb8875SAjay Kumar Gupta 			musb->xceiv->otg->default_a = 1;
327*9ecb8875SAjay Kumar Gupta 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
328*9ecb8875SAjay Kumar Gupta 			del_timer(&glue->timer);
329*9ecb8875SAjay Kumar Gupta 		} else {
330*9ecb8875SAjay Kumar Gupta 			musb->is_active = 0;
331*9ecb8875SAjay Kumar Gupta 			MUSB_DEV_MODE(musb);
332*9ecb8875SAjay Kumar Gupta 			musb->xceiv->otg->default_a = 0;
333*9ecb8875SAjay Kumar Gupta 			musb->xceiv->state = OTG_STATE_B_IDLE;
334*9ecb8875SAjay Kumar Gupta 		}
335*9ecb8875SAjay Kumar Gupta 
336*9ecb8875SAjay Kumar Gupta 		/* NOTE: this must complete power-on within 100 ms. */
337*9ecb8875SAjay Kumar Gupta 		dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
338*9ecb8875SAjay Kumar Gupta 				drvvbus ? "on" : "off",
339*9ecb8875SAjay Kumar Gupta 				otg_state_string(musb->xceiv->state),
340*9ecb8875SAjay Kumar Gupta 				err ? " ERROR" : "",
341*9ecb8875SAjay Kumar Gupta 				devctl);
342*9ecb8875SAjay Kumar Gupta 		ret = IRQ_HANDLED;
343*9ecb8875SAjay Kumar Gupta 	}
344*9ecb8875SAjay Kumar Gupta 
345*9ecb8875SAjay Kumar Gupta 	if (musb->int_tx || musb->int_rx || musb->int_usb)
346*9ecb8875SAjay Kumar Gupta 		ret |= musb_interrupt(musb);
347*9ecb8875SAjay Kumar Gupta 
348*9ecb8875SAjay Kumar Gupta  eoi:
349*9ecb8875SAjay Kumar Gupta 	/* EOI needs to be written for the IRQ to be re-asserted. */
350*9ecb8875SAjay Kumar Gupta 	if (ret == IRQ_HANDLED || epintr || usbintr)
351*9ecb8875SAjay Kumar Gupta 		dsps_writel(reg_base, wrp->eoi, 1);
352*9ecb8875SAjay Kumar Gupta 
353*9ecb8875SAjay Kumar Gupta 	/* Poll for ID change */
354*9ecb8875SAjay Kumar Gupta 	if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
355*9ecb8875SAjay Kumar Gupta 		mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
356*9ecb8875SAjay Kumar Gupta 
357*9ecb8875SAjay Kumar Gupta 	spin_unlock_irqrestore(&musb->lock, flags);
358*9ecb8875SAjay Kumar Gupta 
359*9ecb8875SAjay Kumar Gupta 	return ret;
360*9ecb8875SAjay Kumar Gupta }
361*9ecb8875SAjay Kumar Gupta 
362*9ecb8875SAjay Kumar Gupta static int dsps_musb_init(struct musb *musb)
363*9ecb8875SAjay Kumar Gupta {
364*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
365*9ecb8875SAjay Kumar Gupta 	struct musb_hdrc_platform_data *plat = dev->platform_data;
366*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
367*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
368*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp = glue->wrp;
369*9ecb8875SAjay Kumar Gupta 	struct omap_musb_board_data *data = plat->board_data;
370*9ecb8875SAjay Kumar Gupta 	void __iomem *reg_base = musb->ctrl_base;
371*9ecb8875SAjay Kumar Gupta 	u32 rev, val;
372*9ecb8875SAjay Kumar Gupta 	int status;
373*9ecb8875SAjay Kumar Gupta 
374*9ecb8875SAjay Kumar Gupta 	/* mentor core register starts at offset of 0x400 from musb base */
375*9ecb8875SAjay Kumar Gupta 	musb->mregs += wrp->musb_core_offset;
376*9ecb8875SAjay Kumar Gupta 
377*9ecb8875SAjay Kumar Gupta 	/* NOP driver needs change if supporting dual instance */
378*9ecb8875SAjay Kumar Gupta 	usb_nop_xceiv_register();
379*9ecb8875SAjay Kumar Gupta 	musb->xceiv = usb_get_transceiver();
380*9ecb8875SAjay Kumar Gupta 	if (!musb->xceiv)
381*9ecb8875SAjay Kumar Gupta 		return -ENODEV;
382*9ecb8875SAjay Kumar Gupta 
383*9ecb8875SAjay Kumar Gupta 	/* Returns zero if e.g. not clocked */
384*9ecb8875SAjay Kumar Gupta 	rev = dsps_readl(reg_base, wrp->revision);
385*9ecb8875SAjay Kumar Gupta 	if (!rev) {
386*9ecb8875SAjay Kumar Gupta 		status = -ENODEV;
387*9ecb8875SAjay Kumar Gupta 		goto err0;
388*9ecb8875SAjay Kumar Gupta 	}
389*9ecb8875SAjay Kumar Gupta 
390*9ecb8875SAjay Kumar Gupta 	if (is_host_enabled(musb))
391*9ecb8875SAjay Kumar Gupta 		setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
392*9ecb8875SAjay Kumar Gupta 
393*9ecb8875SAjay Kumar Gupta 	/* Reset the musb */
394*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
395*9ecb8875SAjay Kumar Gupta 
396*9ecb8875SAjay Kumar Gupta 	/* Start the on-chip PHY and its PLL. */
397*9ecb8875SAjay Kumar Gupta 	if (data->set_phy_power)
398*9ecb8875SAjay Kumar Gupta 		data->set_phy_power(1);
399*9ecb8875SAjay Kumar Gupta 
400*9ecb8875SAjay Kumar Gupta 	musb->isr = dsps_interrupt;
401*9ecb8875SAjay Kumar Gupta 
402*9ecb8875SAjay Kumar Gupta 	/* reset the otgdisable bit, needed for host mode to work */
403*9ecb8875SAjay Kumar Gupta 	val = dsps_readl(reg_base, wrp->phy_utmi);
404*9ecb8875SAjay Kumar Gupta 	val &= ~(1 << wrp->otg_disable);
405*9ecb8875SAjay Kumar Gupta 	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
406*9ecb8875SAjay Kumar Gupta 
407*9ecb8875SAjay Kumar Gupta 	/* clear level interrupt */
408*9ecb8875SAjay Kumar Gupta 	dsps_writel(reg_base, wrp->eoi, 0);
409*9ecb8875SAjay Kumar Gupta 
410*9ecb8875SAjay Kumar Gupta 	return 0;
411*9ecb8875SAjay Kumar Gupta err0:
412*9ecb8875SAjay Kumar Gupta 	usb_put_transceiver(musb->xceiv);
413*9ecb8875SAjay Kumar Gupta 	usb_nop_xceiv_unregister();
414*9ecb8875SAjay Kumar Gupta 	return status;
415*9ecb8875SAjay Kumar Gupta }
416*9ecb8875SAjay Kumar Gupta 
417*9ecb8875SAjay Kumar Gupta static int dsps_musb_exit(struct musb *musb)
418*9ecb8875SAjay Kumar Gupta {
419*9ecb8875SAjay Kumar Gupta 	struct device *dev = musb->controller;
420*9ecb8875SAjay Kumar Gupta 	struct musb_hdrc_platform_data *plat = dev->platform_data;
421*9ecb8875SAjay Kumar Gupta 	struct omap_musb_board_data *data = plat->board_data;
422*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev->parent);
423*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
424*9ecb8875SAjay Kumar Gupta 
425*9ecb8875SAjay Kumar Gupta 	if (is_host_enabled(musb))
426*9ecb8875SAjay Kumar Gupta 		del_timer_sync(&glue->timer);
427*9ecb8875SAjay Kumar Gupta 
428*9ecb8875SAjay Kumar Gupta 	/* Shutdown the on-chip PHY and its PLL. */
429*9ecb8875SAjay Kumar Gupta 	if (data->set_phy_power)
430*9ecb8875SAjay Kumar Gupta 		data->set_phy_power(0);
431*9ecb8875SAjay Kumar Gupta 
432*9ecb8875SAjay Kumar Gupta 	/* NOP driver needs change if supporting dual instance */
433*9ecb8875SAjay Kumar Gupta 	usb_put_transceiver(musb->xceiv);
434*9ecb8875SAjay Kumar Gupta 	usb_nop_xceiv_unregister();
435*9ecb8875SAjay Kumar Gupta 
436*9ecb8875SAjay Kumar Gupta 	return 0;
437*9ecb8875SAjay Kumar Gupta }
438*9ecb8875SAjay Kumar Gupta 
439*9ecb8875SAjay Kumar Gupta static struct musb_platform_ops dsps_ops = {
440*9ecb8875SAjay Kumar Gupta 	.init		= dsps_musb_init,
441*9ecb8875SAjay Kumar Gupta 	.exit		= dsps_musb_exit,
442*9ecb8875SAjay Kumar Gupta 
443*9ecb8875SAjay Kumar Gupta 	.enable		= dsps_musb_enable,
444*9ecb8875SAjay Kumar Gupta 	.disable	= dsps_musb_disable,
445*9ecb8875SAjay Kumar Gupta 
446*9ecb8875SAjay Kumar Gupta 	.try_idle	= dsps_musb_try_idle,
447*9ecb8875SAjay Kumar Gupta };
448*9ecb8875SAjay Kumar Gupta 
449*9ecb8875SAjay Kumar Gupta static u64 musb_dmamask = DMA_BIT_MASK(32);
450*9ecb8875SAjay Kumar Gupta 
451*9ecb8875SAjay Kumar Gupta static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
452*9ecb8875SAjay Kumar Gupta {
453*9ecb8875SAjay Kumar Gupta 	struct device *dev = glue->dev;
454*9ecb8875SAjay Kumar Gupta 	struct platform_device *pdev = to_platform_device(dev);
455*9ecb8875SAjay Kumar Gupta 	struct musb_hdrc_platform_data  *pdata = dev->platform_data;
456*9ecb8875SAjay Kumar Gupta 	struct platform_device	*musb;
457*9ecb8875SAjay Kumar Gupta 	struct resource *res;
458*9ecb8875SAjay Kumar Gupta 	struct resource	resources[2];
459*9ecb8875SAjay Kumar Gupta 	char res_name[10];
460*9ecb8875SAjay Kumar Gupta 	int ret;
461*9ecb8875SAjay Kumar Gupta 
462*9ecb8875SAjay Kumar Gupta 	/* get memory resource */
463*9ecb8875SAjay Kumar Gupta 	sprintf(res_name, "musb%d", id);
464*9ecb8875SAjay Kumar Gupta 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
465*9ecb8875SAjay Kumar Gupta 	if (!res) {
466*9ecb8875SAjay Kumar Gupta 		dev_err(dev, "%s get mem resource failed\n", res_name);
467*9ecb8875SAjay Kumar Gupta 		ret = -ENODEV;
468*9ecb8875SAjay Kumar Gupta 		goto err0;
469*9ecb8875SAjay Kumar Gupta 	}
470*9ecb8875SAjay Kumar Gupta 	res->parent = NULL;
471*9ecb8875SAjay Kumar Gupta 	resources[0] = *res;
472*9ecb8875SAjay Kumar Gupta 
473*9ecb8875SAjay Kumar Gupta 	/* get irq resource */
474*9ecb8875SAjay Kumar Gupta 	sprintf(res_name, "musb%d-irq", id);
475*9ecb8875SAjay Kumar Gupta 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
476*9ecb8875SAjay Kumar Gupta 	if (!res) {
477*9ecb8875SAjay Kumar Gupta 		dev_err(dev, "%s get irq resource failed\n", res_name);
478*9ecb8875SAjay Kumar Gupta 		ret = -ENODEV;
479*9ecb8875SAjay Kumar Gupta 		goto err0;
480*9ecb8875SAjay Kumar Gupta 	}
481*9ecb8875SAjay Kumar Gupta 	strcpy((u8 *)res->name, "mc");
482*9ecb8875SAjay Kumar Gupta 	res->parent = NULL;
483*9ecb8875SAjay Kumar Gupta 	resources[1] = *res;
484*9ecb8875SAjay Kumar Gupta 
485*9ecb8875SAjay Kumar Gupta 	/* allocate the child platform device */
486*9ecb8875SAjay Kumar Gupta 	musb = platform_device_alloc("musb-hdrc", -1);
487*9ecb8875SAjay Kumar Gupta 	if (!musb) {
488*9ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to allocate musb device\n");
489*9ecb8875SAjay Kumar Gupta 		ret = -ENOMEM;
490*9ecb8875SAjay Kumar Gupta 		goto err0;
491*9ecb8875SAjay Kumar Gupta 	}
492*9ecb8875SAjay Kumar Gupta 
493*9ecb8875SAjay Kumar Gupta 	musb->dev.parent		= dev;
494*9ecb8875SAjay Kumar Gupta 	musb->dev.dma_mask		= &musb_dmamask;
495*9ecb8875SAjay Kumar Gupta 	musb->dev.coherent_dma_mask	= musb_dmamask;
496*9ecb8875SAjay Kumar Gupta 
497*9ecb8875SAjay Kumar Gupta 	glue->musb			= musb;
498*9ecb8875SAjay Kumar Gupta 
499*9ecb8875SAjay Kumar Gupta 	pdata->platform_ops		= &dsps_ops;
500*9ecb8875SAjay Kumar Gupta 
501*9ecb8875SAjay Kumar Gupta 	ret = platform_device_add_resources(musb, resources, 2);
502*9ecb8875SAjay Kumar Gupta 	if (ret) {
503*9ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add resources\n");
504*9ecb8875SAjay Kumar Gupta 		goto err1;
505*9ecb8875SAjay Kumar Gupta 	}
506*9ecb8875SAjay Kumar Gupta 
507*9ecb8875SAjay Kumar Gupta 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
508*9ecb8875SAjay Kumar Gupta 	if (ret) {
509*9ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to add platform_data\n");
510*9ecb8875SAjay Kumar Gupta 		goto err1;
511*9ecb8875SAjay Kumar Gupta 	}
512*9ecb8875SAjay Kumar Gupta 
513*9ecb8875SAjay Kumar Gupta 	ret = platform_device_add(musb);
514*9ecb8875SAjay Kumar Gupta 	if (ret) {
515*9ecb8875SAjay Kumar Gupta 		dev_err(dev, "failed to register musb device\n");
516*9ecb8875SAjay Kumar Gupta 		goto err1;
517*9ecb8875SAjay Kumar Gupta 	}
518*9ecb8875SAjay Kumar Gupta 
519*9ecb8875SAjay Kumar Gupta 	return 0;
520*9ecb8875SAjay Kumar Gupta 
521*9ecb8875SAjay Kumar Gupta err1:
522*9ecb8875SAjay Kumar Gupta 	platform_device_put(musb);
523*9ecb8875SAjay Kumar Gupta err0:
524*9ecb8875SAjay Kumar Gupta 	return ret;
525*9ecb8875SAjay Kumar Gupta }
526*9ecb8875SAjay Kumar Gupta 
527*9ecb8875SAjay Kumar Gupta static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue)
528*9ecb8875SAjay Kumar Gupta {
529*9ecb8875SAjay Kumar Gupta 	platform_device_del(glue->musb);
530*9ecb8875SAjay Kumar Gupta 	platform_device_put(glue->musb);
531*9ecb8875SAjay Kumar Gupta }
532*9ecb8875SAjay Kumar Gupta 
533*9ecb8875SAjay Kumar Gupta static int __devinit dsps_probe(struct platform_device *pdev)
534*9ecb8875SAjay Kumar Gupta {
535*9ecb8875SAjay Kumar Gupta 	const struct platform_device_id *id = platform_get_device_id(pdev);
536*9ecb8875SAjay Kumar Gupta 	const struct dsps_musb_wrapper *wrp =
537*9ecb8875SAjay Kumar Gupta 				(struct dsps_musb_wrapper *)id->driver_data;
538*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue;
539*9ecb8875SAjay Kumar Gupta 	struct resource *iomem;
540*9ecb8875SAjay Kumar Gupta 	int ret;
541*9ecb8875SAjay Kumar Gupta 
542*9ecb8875SAjay Kumar Gupta 	/* allocate glue */
543*9ecb8875SAjay Kumar Gupta 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
544*9ecb8875SAjay Kumar Gupta 	if (!glue) {
545*9ecb8875SAjay Kumar Gupta 		dev_err(&pdev->dev, "unable to allocate glue memory\n");
546*9ecb8875SAjay Kumar Gupta 		ret = -ENOMEM;
547*9ecb8875SAjay Kumar Gupta 		goto err0;
548*9ecb8875SAjay Kumar Gupta 	}
549*9ecb8875SAjay Kumar Gupta 
550*9ecb8875SAjay Kumar Gupta 	/* get memory resource */
551*9ecb8875SAjay Kumar Gupta 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
552*9ecb8875SAjay Kumar Gupta 	if (!iomem) {
553*9ecb8875SAjay Kumar Gupta 		dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
554*9ecb8875SAjay Kumar Gupta 		ret = -ENODEV;
555*9ecb8875SAjay Kumar Gupta 		goto err1;
556*9ecb8875SAjay Kumar Gupta 	}
557*9ecb8875SAjay Kumar Gupta 
558*9ecb8875SAjay Kumar Gupta 	glue->dev = &pdev->dev;
559*9ecb8875SAjay Kumar Gupta 
560*9ecb8875SAjay Kumar Gupta 	glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
561*9ecb8875SAjay Kumar Gupta 	if (!glue->wrp) {
562*9ecb8875SAjay Kumar Gupta 		dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n");
563*9ecb8875SAjay Kumar Gupta 		ret = -ENOMEM;
564*9ecb8875SAjay Kumar Gupta 		goto err1;
565*9ecb8875SAjay Kumar Gupta 	}
566*9ecb8875SAjay Kumar Gupta 	platform_set_drvdata(pdev, glue);
567*9ecb8875SAjay Kumar Gupta 
568*9ecb8875SAjay Kumar Gupta 	/* create the child platform device for first instances of musb */
569*9ecb8875SAjay Kumar Gupta 	ret = dsps_create_musb_pdev(glue, 0);
570*9ecb8875SAjay Kumar Gupta 	if (ret != 0) {
571*9ecb8875SAjay Kumar Gupta 		dev_err(&pdev->dev, "failed to create child pdev\n");
572*9ecb8875SAjay Kumar Gupta 		goto err2;
573*9ecb8875SAjay Kumar Gupta 	}
574*9ecb8875SAjay Kumar Gupta 
575*9ecb8875SAjay Kumar Gupta 	/* enable the usbss clocks */
576*9ecb8875SAjay Kumar Gupta 	pm_runtime_enable(&pdev->dev);
577*9ecb8875SAjay Kumar Gupta 
578*9ecb8875SAjay Kumar Gupta 	ret = pm_runtime_get_sync(&pdev->dev);
579*9ecb8875SAjay Kumar Gupta 	if (ret < 0) {
580*9ecb8875SAjay Kumar Gupta 		dev_err(&pdev->dev, "pm_runtime_get_sync FAILED");
581*9ecb8875SAjay Kumar Gupta 		goto err3;
582*9ecb8875SAjay Kumar Gupta 	}
583*9ecb8875SAjay Kumar Gupta 
584*9ecb8875SAjay Kumar Gupta 	return 0;
585*9ecb8875SAjay Kumar Gupta 
586*9ecb8875SAjay Kumar Gupta err3:
587*9ecb8875SAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
588*9ecb8875SAjay Kumar Gupta err2:
589*9ecb8875SAjay Kumar Gupta 	kfree(glue->wrp);
590*9ecb8875SAjay Kumar Gupta err1:
591*9ecb8875SAjay Kumar Gupta 	kfree(glue);
592*9ecb8875SAjay Kumar Gupta err0:
593*9ecb8875SAjay Kumar Gupta 	return ret;
594*9ecb8875SAjay Kumar Gupta }
595*9ecb8875SAjay Kumar Gupta static int __devexit dsps_remove(struct platform_device *pdev)
596*9ecb8875SAjay Kumar Gupta {
597*9ecb8875SAjay Kumar Gupta 	struct dsps_glue *glue = platform_get_drvdata(pdev);
598*9ecb8875SAjay Kumar Gupta 
599*9ecb8875SAjay Kumar Gupta 	/* delete the child platform device */
600*9ecb8875SAjay Kumar Gupta 	dsps_delete_musb_pdev(glue);
601*9ecb8875SAjay Kumar Gupta 
602*9ecb8875SAjay Kumar Gupta 	/* disable usbss clocks */
603*9ecb8875SAjay Kumar Gupta 	pm_runtime_put(&pdev->dev);
604*9ecb8875SAjay Kumar Gupta 	pm_runtime_disable(&pdev->dev);
605*9ecb8875SAjay Kumar Gupta 	kfree(glue->wrp);
606*9ecb8875SAjay Kumar Gupta 	kfree(glue);
607*9ecb8875SAjay Kumar Gupta 	return 0;
608*9ecb8875SAjay Kumar Gupta }
609*9ecb8875SAjay Kumar Gupta 
610*9ecb8875SAjay Kumar Gupta #ifdef CONFIG_PM_SLEEP
611*9ecb8875SAjay Kumar Gupta static int dsps_suspend(struct device *dev)
612*9ecb8875SAjay Kumar Gupta {
613*9ecb8875SAjay Kumar Gupta 	struct musb_hdrc_platform_data *plat = dev->platform_data;
614*9ecb8875SAjay Kumar Gupta 	struct omap_musb_board_data *data = plat->board_data;
615*9ecb8875SAjay Kumar Gupta 
616*9ecb8875SAjay Kumar Gupta 	/* Shutdown the on-chip PHY and its PLL. */
617*9ecb8875SAjay Kumar Gupta 	if (data->set_phy_power)
618*9ecb8875SAjay Kumar Gupta 		data->set_phy_power(0);
619*9ecb8875SAjay Kumar Gupta 
620*9ecb8875SAjay Kumar Gupta 	return 0;
621*9ecb8875SAjay Kumar Gupta }
622*9ecb8875SAjay Kumar Gupta 
623*9ecb8875SAjay Kumar Gupta static int dsps_resume(struct device *dev)
624*9ecb8875SAjay Kumar Gupta {
625*9ecb8875SAjay Kumar Gupta 	struct musb_hdrc_platform_data *plat = dev->platform_data;
626*9ecb8875SAjay Kumar Gupta 	struct omap_musb_board_data *data = plat->board_data;
627*9ecb8875SAjay Kumar Gupta 
628*9ecb8875SAjay Kumar Gupta 	/* Start the on-chip PHY and its PLL. */
629*9ecb8875SAjay Kumar Gupta 	if (data->set_phy_power)
630*9ecb8875SAjay Kumar Gupta 		data->set_phy_power(1);
631*9ecb8875SAjay Kumar Gupta 
632*9ecb8875SAjay Kumar Gupta 	return 0;
633*9ecb8875SAjay Kumar Gupta }
634*9ecb8875SAjay Kumar Gupta #endif
635*9ecb8875SAjay Kumar Gupta 
636*9ecb8875SAjay Kumar Gupta static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
637*9ecb8875SAjay Kumar Gupta 
638*9ecb8875SAjay Kumar Gupta static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
639*9ecb8875SAjay Kumar Gupta 	.revision		= 0x00,
640*9ecb8875SAjay Kumar Gupta 	.control		= 0x14,
641*9ecb8875SAjay Kumar Gupta 	.status			= 0x18,
642*9ecb8875SAjay Kumar Gupta 	.eoi			= 0x24,
643*9ecb8875SAjay Kumar Gupta 	.epintr_set		= 0x38,
644*9ecb8875SAjay Kumar Gupta 	.epintr_clear		= 0x40,
645*9ecb8875SAjay Kumar Gupta 	.epintr_status		= 0x30,
646*9ecb8875SAjay Kumar Gupta 	.coreintr_set		= 0x3c,
647*9ecb8875SAjay Kumar Gupta 	.coreintr_clear		= 0x44,
648*9ecb8875SAjay Kumar Gupta 	.coreintr_status	= 0x34,
649*9ecb8875SAjay Kumar Gupta 	.phy_utmi		= 0xe0,
650*9ecb8875SAjay Kumar Gupta 	.mode			= 0xe8,
651*9ecb8875SAjay Kumar Gupta 	.reset			= 0,
652*9ecb8875SAjay Kumar Gupta 	.otg_disable		= 21,
653*9ecb8875SAjay Kumar Gupta 	.iddig			= 8,
654*9ecb8875SAjay Kumar Gupta 	.usb_shift		= 0,
655*9ecb8875SAjay Kumar Gupta 	.usb_mask		= 0x1ff,
656*9ecb8875SAjay Kumar Gupta 	.usb_bitmap		= (0x1ff << 0),
657*9ecb8875SAjay Kumar Gupta 	.drvvbus		= 8,
658*9ecb8875SAjay Kumar Gupta 	.txep_shift		= 0,
659*9ecb8875SAjay Kumar Gupta 	.txep_mask		= 0xffff,
660*9ecb8875SAjay Kumar Gupta 	.txep_bitmap		= (0xffff << 0),
661*9ecb8875SAjay Kumar Gupta 	.rxep_shift		= 16,
662*9ecb8875SAjay Kumar Gupta 	.rxep_mask		= 0xfffe,
663*9ecb8875SAjay Kumar Gupta 	.rxep_bitmap		= (0xfffe << 16),
664*9ecb8875SAjay Kumar Gupta 	.musb_core_offset	= 0x400,
665*9ecb8875SAjay Kumar Gupta 	.poll_seconds		= 2,
666*9ecb8875SAjay Kumar Gupta };
667*9ecb8875SAjay Kumar Gupta 
668*9ecb8875SAjay Kumar Gupta static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
669*9ecb8875SAjay Kumar Gupta 	{
670*9ecb8875SAjay Kumar Gupta 		.name	= "musb-ti81xx",
671*9ecb8875SAjay Kumar Gupta 		.driver_data	= (kernel_ulong_t) &ti81xx_driver_data,
672*9ecb8875SAjay Kumar Gupta 	},
673*9ecb8875SAjay Kumar Gupta 	{  },	/* Terminating Entry */
674*9ecb8875SAjay Kumar Gupta };
675*9ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
676*9ecb8875SAjay Kumar Gupta 
677*9ecb8875SAjay Kumar Gupta static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
678*9ecb8875SAjay Kumar Gupta 	{ .compatible = "musb-ti81xx", },
679*9ecb8875SAjay Kumar Gupta 	{ .compatible = "ti,ti81xx-musb", },
680*9ecb8875SAjay Kumar Gupta 	{ .compatible = "ti,am335x-musb", },
681*9ecb8875SAjay Kumar Gupta 	{  },
682*9ecb8875SAjay Kumar Gupta };
683*9ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
684*9ecb8875SAjay Kumar Gupta 
685*9ecb8875SAjay Kumar Gupta static struct platform_driver dsps_usbss_driver = {
686*9ecb8875SAjay Kumar Gupta 	.probe		= dsps_probe,
687*9ecb8875SAjay Kumar Gupta 	.remove         = __devexit_p(dsps_remove),
688*9ecb8875SAjay Kumar Gupta 	.driver         = {
689*9ecb8875SAjay Kumar Gupta 		.name   = "musb-dsps",
690*9ecb8875SAjay Kumar Gupta 		.pm	= &dsps_pm_ops,
691*9ecb8875SAjay Kumar Gupta 		.of_match_table	= musb_dsps_of_match,
692*9ecb8875SAjay Kumar Gupta 	},
693*9ecb8875SAjay Kumar Gupta 	.id_table	= musb_dsps_id_table,
694*9ecb8875SAjay Kumar Gupta };
695*9ecb8875SAjay Kumar Gupta 
696*9ecb8875SAjay Kumar Gupta MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
697*9ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
698*9ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
699*9ecb8875SAjay Kumar Gupta MODULE_LICENSE("GPL v2");
700*9ecb8875SAjay Kumar Gupta 
701*9ecb8875SAjay Kumar Gupta static int __init dsps_init(void)
702*9ecb8875SAjay Kumar Gupta {
703*9ecb8875SAjay Kumar Gupta 	return platform_driver_register(&dsps_usbss_driver);
704*9ecb8875SAjay Kumar Gupta }
705*9ecb8875SAjay Kumar Gupta subsys_initcall(dsps_init);
706*9ecb8875SAjay Kumar Gupta 
707*9ecb8875SAjay Kumar Gupta static void __exit dsps_exit(void)
708*9ecb8875SAjay Kumar Gupta {
709*9ecb8875SAjay Kumar Gupta 	platform_driver_unregister(&dsps_usbss_driver);
710*9ecb8875SAjay Kumar Gupta }
711*9ecb8875SAjay Kumar Gupta module_exit(dsps_exit);
712