xref: /openbmc/linux/drivers/usb/musb/ux500.c (revision 80005402)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
24bc36fd3SMian Yousaf Kaukab /*
34bc36fd3SMian Yousaf Kaukab  * Copyright (C) 2010 ST-Ericsson AB
44bc36fd3SMian Yousaf Kaukab  * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
54bc36fd3SMian Yousaf Kaukab  *
64bc36fd3SMian Yousaf Kaukab  * Based on omap2430.c
74bc36fd3SMian Yousaf Kaukab  */
84bc36fd3SMian Yousaf Kaukab 
94bc36fd3SMian Yousaf Kaukab #include <linux/module.h>
104bc36fd3SMian Yousaf Kaukab #include <linux/kernel.h>
114bc36fd3SMian Yousaf Kaukab #include <linux/clk.h>
12ded017eeSKishon Vijay Abraham I #include <linux/err.h>
134bc36fd3SMian Yousaf Kaukab #include <linux/io.h>
14313bdb11SLee Jones #include <linux/of.h>
154bc36fd3SMian Yousaf Kaukab #include <linux/platform_device.h>
16af6882beSFabio Baltieri #include <linux/usb/musb-ux500.h>
174bc36fd3SMian Yousaf Kaukab 
184bc36fd3SMian Yousaf Kaukab #include "musb_core.h"
194bc36fd3SMian Yousaf Kaukab 
201e572aa5SBhumika Goyal static const struct musb_hdrc_config ux500_musb_hdrc_config = {
21a20b1b79SLee Jones 	.multipoint	= true,
22a20b1b79SLee Jones 	.dyn_fifo	= true,
23a20b1b79SLee Jones 	.num_eps	= 16,
24a20b1b79SLee Jones 	.ram_bits	= 16,
25a20b1b79SLee Jones };
26a20b1b79SLee Jones 
274bc36fd3SMian Yousaf Kaukab struct ux500_glue {
284bc36fd3SMian Yousaf Kaukab 	struct device		*dev;
294bc36fd3SMian Yousaf Kaukab 	struct platform_device	*musb;
304bc36fd3SMian Yousaf Kaukab 	struct clk		*clk;
314bc36fd3SMian Yousaf Kaukab };
324bc36fd3SMian Yousaf Kaukab #define glue_to_musb(g)	platform_get_drvdata(g->musb)
334bc36fd3SMian Yousaf Kaukab 
ux500_musb_set_vbus(struct musb * musb,int is_on)34996a9d26SFabio Baltieri static void ux500_musb_set_vbus(struct musb *musb, int is_on)
35996a9d26SFabio Baltieri {
36996a9d26SFabio Baltieri 	u8            devctl;
37996a9d26SFabio Baltieri 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
38996a9d26SFabio Baltieri 	/* HDRC controls CPEN, but beware current surges during device
39996a9d26SFabio Baltieri 	 * connect.  They can trigger transient overcurrent conditions
40996a9d26SFabio Baltieri 	 * that must be ignored.
41996a9d26SFabio Baltieri 	 */
42996a9d26SFabio Baltieri 
43996a9d26SFabio Baltieri 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
44996a9d26SFabio Baltieri 
45996a9d26SFabio Baltieri 	if (is_on) {
46e47d9254SAntoine Tenart 		if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
47996a9d26SFabio Baltieri 			/* start the session */
48996a9d26SFabio Baltieri 			devctl |= MUSB_DEVCTL_SESSION;
49996a9d26SFabio Baltieri 			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
50996a9d26SFabio Baltieri 			/*
51996a9d26SFabio Baltieri 			 * Wait for the musb to set as A device to enable the
52996a9d26SFabio Baltieri 			 * VBUS
53996a9d26SFabio Baltieri 			 */
54996a9d26SFabio Baltieri 			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
55996a9d26SFabio Baltieri 
56996a9d26SFabio Baltieri 				if (time_after(jiffies, timeout)) {
57996a9d26SFabio Baltieri 					dev_err(musb->controller,
58996a9d26SFabio Baltieri 					"configured as A device timeout");
59996a9d26SFabio Baltieri 					break;
60996a9d26SFabio Baltieri 				}
61996a9d26SFabio Baltieri 			}
62996a9d26SFabio Baltieri 
63996a9d26SFabio Baltieri 		} else {
64996a9d26SFabio Baltieri 			musb->is_active = 1;
65e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
66996a9d26SFabio Baltieri 			devctl |= MUSB_DEVCTL_SESSION;
67996a9d26SFabio Baltieri 			MUSB_HST_MODE(musb);
68996a9d26SFabio Baltieri 		}
69996a9d26SFabio Baltieri 	} else {
70996a9d26SFabio Baltieri 		musb->is_active = 0;
71996a9d26SFabio Baltieri 
72996a9d26SFabio Baltieri 		/* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
73996a9d26SFabio Baltieri 		 * right to B_IDLE...
74996a9d26SFabio Baltieri 		 */
75996a9d26SFabio Baltieri 		devctl &= ~MUSB_DEVCTL_SESSION;
76996a9d26SFabio Baltieri 		MUSB_DEV_MODE(musb);
77996a9d26SFabio Baltieri 	}
78996a9d26SFabio Baltieri 	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
79996a9d26SFabio Baltieri 
80996a9d26SFabio Baltieri 	/*
81996a9d26SFabio Baltieri 	 * Devctl values will be updated after vbus goes below
82996a9d26SFabio Baltieri 	 * session_valid. The time taken depends on the capacitance
83996a9d26SFabio Baltieri 	 * on VBUS line. The max discharge time can be upto 1 sec
84996a9d26SFabio Baltieri 	 * as per the spec. Typically on our platform, it is 200ms
85996a9d26SFabio Baltieri 	 */
86996a9d26SFabio Baltieri 	if (!is_on)
87996a9d26SFabio Baltieri 		mdelay(200);
88996a9d26SFabio Baltieri 
89996a9d26SFabio Baltieri 	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
90e47d9254SAntoine Tenart 		usb_otg_state_string(musb->xceiv->otg->state),
91996a9d26SFabio Baltieri 		musb_readb(musb->mregs, MUSB_DEVCTL));
92996a9d26SFabio Baltieri }
93996a9d26SFabio Baltieri 
musb_otg_notifications(struct notifier_block * nb,unsigned long event,void * unused)940135522cSFabio Baltieri static int musb_otg_notifications(struct notifier_block *nb,
950135522cSFabio Baltieri 		unsigned long event, void *unused)
960135522cSFabio Baltieri {
970135522cSFabio Baltieri 	struct musb *musb = container_of(nb, struct musb, nb);
980135522cSFabio Baltieri 
990135522cSFabio Baltieri 	dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
100e47d9254SAntoine Tenart 			event, usb_otg_state_string(musb->xceiv->otg->state));
1010135522cSFabio Baltieri 
1020135522cSFabio Baltieri 	switch (event) {
103af6882beSFabio Baltieri 	case UX500_MUSB_ID:
1040135522cSFabio Baltieri 		dev_dbg(musb->controller, "ID GND\n");
1050135522cSFabio Baltieri 		ux500_musb_set_vbus(musb, 1);
1060135522cSFabio Baltieri 		break;
107af6882beSFabio Baltieri 	case UX500_MUSB_VBUS:
1080135522cSFabio Baltieri 		dev_dbg(musb->controller, "VBUS Connect\n");
1090135522cSFabio Baltieri 		break;
110af6882beSFabio Baltieri 	case UX500_MUSB_NONE:
1110135522cSFabio Baltieri 		dev_dbg(musb->controller, "VBUS Disconnect\n");
1120135522cSFabio Baltieri 		if (is_host_active(musb))
1130135522cSFabio Baltieri 			ux500_musb_set_vbus(musb, 0);
1140135522cSFabio Baltieri 		else
115e47d9254SAntoine Tenart 			musb->xceiv->otg->state = OTG_STATE_B_IDLE;
1160135522cSFabio Baltieri 		break;
1170135522cSFabio Baltieri 	default:
1180135522cSFabio Baltieri 		dev_dbg(musb->controller, "ID float\n");
1190135522cSFabio Baltieri 		return NOTIFY_DONE;
1200135522cSFabio Baltieri 	}
1210135522cSFabio Baltieri 	return NOTIFY_OK;
1220135522cSFabio Baltieri }
1230135522cSFabio Baltieri 
ux500_musb_interrupt(int irq,void * __hci)124baef653aSPhilippe De Swert static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
125baef653aSPhilippe De Swert {
126baef653aSPhilippe De Swert 	unsigned long   flags;
127baef653aSPhilippe De Swert 	irqreturn_t     retval = IRQ_NONE;
128baef653aSPhilippe De Swert 	struct musb     *musb = __hci;
129baef653aSPhilippe De Swert 
130baef653aSPhilippe De Swert 	spin_lock_irqsave(&musb->lock, flags);
131baef653aSPhilippe De Swert 
132baef653aSPhilippe De Swert 	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
133baef653aSPhilippe De Swert 	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
134baef653aSPhilippe De Swert 	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
135baef653aSPhilippe De Swert 
136baef653aSPhilippe De Swert 	if (musb->int_usb || musb->int_tx || musb->int_rx)
137baef653aSPhilippe De Swert 		retval = musb_interrupt(musb);
138baef653aSPhilippe De Swert 
139baef653aSPhilippe De Swert 	spin_unlock_irqrestore(&musb->lock, flags);
140baef653aSPhilippe De Swert 
141baef653aSPhilippe De Swert 	return retval;
142baef653aSPhilippe De Swert }
143baef653aSPhilippe De Swert 
ux500_musb_init(struct musb * musb)1444bc36fd3SMian Yousaf Kaukab static int ux500_musb_init(struct musb *musb)
1454bc36fd3SMian Yousaf Kaukab {
1460135522cSFabio Baltieri 	int status;
1470135522cSFabio Baltieri 
148662dca54SKishon Vijay Abraham I 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
149ded017eeSKishon Vijay Abraham I 	if (IS_ERR_OR_NULL(musb->xceiv)) {
1504bc36fd3SMian Yousaf Kaukab 		pr_err("HS USB OTG: no transceiver configured\n");
15125736e0cSMing Lei 		return -EPROBE_DEFER;
1524bc36fd3SMian Yousaf Kaukab 	}
1534bc36fd3SMian Yousaf Kaukab 
1540135522cSFabio Baltieri 	musb->nb.notifier_call = musb_otg_notifications;
1550135522cSFabio Baltieri 	status = usb_register_notifier(musb->xceiv, &musb->nb);
1560135522cSFabio Baltieri 	if (status < 0) {
1570135522cSFabio Baltieri 		dev_dbg(musb->controller, "notification register failed\n");
1580135522cSFabio Baltieri 		return status;
1590135522cSFabio Baltieri 	}
1600135522cSFabio Baltieri 
161baef653aSPhilippe De Swert 	musb->isr = ux500_musb_interrupt;
162baef653aSPhilippe De Swert 
1634bc36fd3SMian Yousaf Kaukab 	return 0;
1644bc36fd3SMian Yousaf Kaukab }
1654bc36fd3SMian Yousaf Kaukab 
ux500_musb_exit(struct musb * musb)1664bc36fd3SMian Yousaf Kaukab static int ux500_musb_exit(struct musb *musb)
1674bc36fd3SMian Yousaf Kaukab {
1680135522cSFabio Baltieri 	usb_unregister_notifier(musb->xceiv, &musb->nb);
1690135522cSFabio Baltieri 
170721002ecSKishon Vijay Abraham I 	usb_put_phy(musb->xceiv);
1714bc36fd3SMian Yousaf Kaukab 
1724bc36fd3SMian Yousaf Kaukab 	return 0;
1734bc36fd3SMian Yousaf Kaukab }
1744bc36fd3SMian Yousaf Kaukab 
1754bc36fd3SMian Yousaf Kaukab static const struct musb_platform_ops ux500_ops = {
176f8e9f34fSTony Lindgren 	.quirks		= MUSB_DMA_UX500 | MUSB_INDEXED_EP,
1777f6283edSTony Lindgren #ifdef CONFIG_USB_UX500_DMA
1787f6283edSTony Lindgren 	.dma_init	= ux500_dma_controller_create,
1797f6283edSTony Lindgren 	.dma_exit	= ux500_dma_controller_destroy,
1807f6283edSTony Lindgren #endif
1814bc36fd3SMian Yousaf Kaukab 	.init		= ux500_musb_init,
1824bc36fd3SMian Yousaf Kaukab 	.exit		= ux500_musb_exit,
1838a77f05aSTony Lindgren 	.fifo_mode	= 5,
184996a9d26SFabio Baltieri 
185996a9d26SFabio Baltieri 	.set_vbus	= ux500_musb_set_vbus,
1864bc36fd3SMian Yousaf Kaukab };
1874bc36fd3SMian Yousaf Kaukab 
188313bdb11SLee Jones static struct musb_hdrc_platform_data *
ux500_of_probe(struct platform_device * pdev,struct device_node * np)189313bdb11SLee Jones ux500_of_probe(struct platform_device *pdev, struct device_node *np)
190313bdb11SLee Jones {
191313bdb11SLee Jones 	struct musb_hdrc_platform_data *pdata;
192313bdb11SLee Jones 	const char *mode;
193313bdb11SLee Jones 	int strlen;
194313bdb11SLee Jones 
195313bdb11SLee Jones 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
196313bdb11SLee Jones 	if (!pdata)
197313bdb11SLee Jones 		return NULL;
198313bdb11SLee Jones 
199313bdb11SLee Jones 	mode = of_get_property(np, "dr_mode", &strlen);
200313bdb11SLee Jones 	if (!mode) {
201313bdb11SLee Jones 		dev_err(&pdev->dev, "No 'dr_mode' property found\n");
202313bdb11SLee Jones 		return NULL;
203313bdb11SLee Jones 	}
204313bdb11SLee Jones 
205313bdb11SLee Jones 	if (strlen > 0) {
206313bdb11SLee Jones 		if (!strcmp(mode, "host"))
207313bdb11SLee Jones 			pdata->mode = MUSB_HOST;
208313bdb11SLee Jones 		if (!strcmp(mode, "otg"))
209313bdb11SLee Jones 			pdata->mode = MUSB_OTG;
210313bdb11SLee Jones 		if (!strcmp(mode, "peripheral"))
211313bdb11SLee Jones 			pdata->mode = MUSB_PERIPHERAL;
212313bdb11SLee Jones 	}
213313bdb11SLee Jones 
214313bdb11SLee Jones 	return pdata;
215313bdb11SLee Jones }
216313bdb11SLee Jones 
ux500_probe(struct platform_device * pdev)21741ac7b3aSBill Pemberton static int ux500_probe(struct platform_device *pdev)
2184bc36fd3SMian Yousaf Kaukab {
219c1a7d67cSJingoo Han 	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
220313bdb11SLee Jones 	struct device_node		*np = pdev->dev.of_node;
2214bc36fd3SMian Yousaf Kaukab 	struct platform_device		*musb;
2224bc36fd3SMian Yousaf Kaukab 	struct ux500_glue		*glue;
2234bc36fd3SMian Yousaf Kaukab 	struct clk			*clk;
2244bc36fd3SMian Yousaf Kaukab 	int				ret = -ENOMEM;
2254bc36fd3SMian Yousaf Kaukab 
226313bdb11SLee Jones 	if (!pdata) {
227313bdb11SLee Jones 		if (np) {
228313bdb11SLee Jones 			pdata = ux500_of_probe(pdev, np);
229313bdb11SLee Jones 			if (!pdata)
230313bdb11SLee Jones 				goto err0;
231313bdb11SLee Jones 
232313bdb11SLee Jones 			pdev->dev.platform_data = pdata;
233313bdb11SLee Jones 		} else {
234313bdb11SLee Jones 			dev_err(&pdev->dev, "no pdata or device tree found\n");
235313bdb11SLee Jones 			goto err0;
236313bdb11SLee Jones 		}
237313bdb11SLee Jones 	}
238313bdb11SLee Jones 
239d7dc5bdeSHimangi Saraogi 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
24024c611b9SPeter Chen 	if (!glue)
2414bc36fd3SMian Yousaf Kaukab 		goto err0;
2424bc36fd3SMian Yousaf Kaukab 
2432f771164SSebastian Andrzej Siewior 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
2444bc36fd3SMian Yousaf Kaukab 	if (!musb) {
2454bc36fd3SMian Yousaf Kaukab 		dev_err(&pdev->dev, "failed to allocate musb device\n");
246d7dc5bdeSHimangi Saraogi 		goto err0;
2474bc36fd3SMian Yousaf Kaukab 	}
2484bc36fd3SMian Yousaf Kaukab 
249d7dc5bdeSHimangi Saraogi 	clk = devm_clk_get(&pdev->dev, NULL);
2504bc36fd3SMian Yousaf Kaukab 	if (IS_ERR(clk)) {
2514bc36fd3SMian Yousaf Kaukab 		dev_err(&pdev->dev, "failed to get clock\n");
2524bc36fd3SMian Yousaf Kaukab 		ret = PTR_ERR(clk);
253d7dc5bdeSHimangi Saraogi 		goto err1;
2544bc36fd3SMian Yousaf Kaukab 	}
2554bc36fd3SMian Yousaf Kaukab 
25699d17cfaSFabio Baltieri 	ret = clk_prepare_enable(clk);
2574bc36fd3SMian Yousaf Kaukab 	if (ret) {
2584bc36fd3SMian Yousaf Kaukab 		dev_err(&pdev->dev, "failed to enable clock\n");
259d7dc5bdeSHimangi Saraogi 		goto err1;
2604bc36fd3SMian Yousaf Kaukab 	}
2614bc36fd3SMian Yousaf Kaukab 
2624bc36fd3SMian Yousaf Kaukab 	musb->dev.parent		= &pdev->dev;
2631e6eebb4SLee Jones 	musb->dev.dma_mask		= &pdev->dev.coherent_dma_mask;
26487266064SMian Yousaf Kaukab 	musb->dev.coherent_dma_mask	= pdev->dev.coherent_dma_mask;
265cf081d00SRob Herring 	device_set_of_node_from_dev(&musb->dev, &pdev->dev);
2664bc36fd3SMian Yousaf Kaukab 
2674bc36fd3SMian Yousaf Kaukab 	glue->dev			= &pdev->dev;
2684bc36fd3SMian Yousaf Kaukab 	glue->musb			= musb;
2694bc36fd3SMian Yousaf Kaukab 	glue->clk			= clk;
2704bc36fd3SMian Yousaf Kaukab 
2714bc36fd3SMian Yousaf Kaukab 	pdata->platform_ops		= &ux500_ops;
272a20b1b79SLee Jones 	pdata->config 			= &ux500_musb_hdrc_config;
2734bc36fd3SMian Yousaf Kaukab 
2744bc36fd3SMian Yousaf Kaukab 	platform_set_drvdata(pdev, glue);
2754bc36fd3SMian Yousaf Kaukab 
2769879c81bSRob Herring 	ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
2774bc36fd3SMian Yousaf Kaukab 	if (ret) {
2784bc36fd3SMian Yousaf Kaukab 		dev_err(&pdev->dev, "failed to add resources\n");
279d7dc5bdeSHimangi Saraogi 		goto err2;
2804bc36fd3SMian Yousaf Kaukab 	}
2814bc36fd3SMian Yousaf Kaukab 
2824bc36fd3SMian Yousaf Kaukab 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
2834bc36fd3SMian Yousaf Kaukab 	if (ret) {
2844bc36fd3SMian Yousaf Kaukab 		dev_err(&pdev->dev, "failed to add platform_data\n");
285d7dc5bdeSHimangi Saraogi 		goto err2;
2864bc36fd3SMian Yousaf Kaukab 	}
2874bc36fd3SMian Yousaf Kaukab 
2884bc36fd3SMian Yousaf Kaukab 	ret = platform_device_add(musb);
2894bc36fd3SMian Yousaf Kaukab 	if (ret) {
2904bc36fd3SMian Yousaf Kaukab 		dev_err(&pdev->dev, "failed to register musb device\n");
291d7dc5bdeSHimangi Saraogi 		goto err2;
2924bc36fd3SMian Yousaf Kaukab 	}
2934bc36fd3SMian Yousaf Kaukab 
2944bc36fd3SMian Yousaf Kaukab 	return 0;
2954bc36fd3SMian Yousaf Kaukab 
296d7dc5bdeSHimangi Saraogi err2:
29799d17cfaSFabio Baltieri 	clk_disable_unprepare(clk);
2984bc36fd3SMian Yousaf Kaukab 
2994bc36fd3SMian Yousaf Kaukab err1:
300d7dc5bdeSHimangi Saraogi 	platform_device_put(musb);
3014bc36fd3SMian Yousaf Kaukab 
3024bc36fd3SMian Yousaf Kaukab err0:
3034bc36fd3SMian Yousaf Kaukab 	return ret;
3044bc36fd3SMian Yousaf Kaukab }
3054bc36fd3SMian Yousaf Kaukab 
ux500_remove(struct platform_device * pdev)306*80005402SUwe Kleine-König static void ux500_remove(struct platform_device *pdev)
3074bc36fd3SMian Yousaf Kaukab {
3084bc36fd3SMian Yousaf Kaukab 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
3094bc36fd3SMian Yousaf Kaukab 
3104b0de6f3SWei Yongjun 	platform_device_unregister(glue->musb);
31199d17cfaSFabio Baltieri 	clk_disable_unprepare(glue->clk);
3124bc36fd3SMian Yousaf Kaukab }
3134bc36fd3SMian Yousaf Kaukab 
31430d09223SFelipe Balbi #ifdef CONFIG_PM_SLEEP
ux500_suspend(struct device * dev)3154bc36fd3SMian Yousaf Kaukab static int ux500_suspend(struct device *dev)
3164bc36fd3SMian Yousaf Kaukab {
3174bc36fd3SMian Yousaf Kaukab 	struct ux500_glue	*glue = dev_get_drvdata(dev);
3184bc36fd3SMian Yousaf Kaukab 	struct musb		*musb = glue_to_musb(glue);
3194bc36fd3SMian Yousaf Kaukab 
32079c5623fSUlf Hansson 	if (musb)
321b96d3b08SHeikki Krogerus 		usb_phy_set_suspend(musb->xceiv, 1);
32279c5623fSUlf Hansson 
32399d17cfaSFabio Baltieri 	clk_disable_unprepare(glue->clk);
3244bc36fd3SMian Yousaf Kaukab 
3254bc36fd3SMian Yousaf Kaukab 	return 0;
3264bc36fd3SMian Yousaf Kaukab }
3274bc36fd3SMian Yousaf Kaukab 
ux500_resume(struct device * dev)3284bc36fd3SMian Yousaf Kaukab static int ux500_resume(struct device *dev)
3294bc36fd3SMian Yousaf Kaukab {
3304bc36fd3SMian Yousaf Kaukab 	struct ux500_glue	*glue = dev_get_drvdata(dev);
3314bc36fd3SMian Yousaf Kaukab 	struct musb		*musb = glue_to_musb(glue);
3324bc36fd3SMian Yousaf Kaukab 	int			ret;
3334bc36fd3SMian Yousaf Kaukab 
33499d17cfaSFabio Baltieri 	ret = clk_prepare_enable(glue->clk);
3354bc36fd3SMian Yousaf Kaukab 	if (ret) {
3364bc36fd3SMian Yousaf Kaukab 		dev_err(dev, "failed to enable clock\n");
3374bc36fd3SMian Yousaf Kaukab 		return ret;
3384bc36fd3SMian Yousaf Kaukab 	}
3394bc36fd3SMian Yousaf Kaukab 
34079c5623fSUlf Hansson 	if (musb)
341b96d3b08SHeikki Krogerus 		usb_phy_set_suspend(musb->xceiv, 0);
3424bc36fd3SMian Yousaf Kaukab 
3434bc36fd3SMian Yousaf Kaukab 	return 0;
3444bc36fd3SMian Yousaf Kaukab }
3454bc36fd3SMian Yousaf Kaukab #endif
3464bc36fd3SMian Yousaf Kaukab 
347a89adb09SDaniel Mack static SIMPLE_DEV_PM_OPS(ux500_pm_ops, ux500_suspend, ux500_resume);
348a89adb09SDaniel Mack 
349313bdb11SLee Jones static const struct of_device_id ux500_match[] = {
350313bdb11SLee Jones         { .compatible = "stericsson,db8500-musb", },
351313bdb11SLee Jones         {}
352313bdb11SLee Jones };
353313bdb11SLee Jones 
354523d5dafSLuis de Bethencourt MODULE_DEVICE_TABLE(of, ux500_match);
355523d5dafSLuis de Bethencourt 
3564bc36fd3SMian Yousaf Kaukab static struct platform_driver ux500_driver = {
357e9e8c85eSFelipe Balbi 	.probe		= ux500_probe,
358*80005402SUwe Kleine-König 	.remove_new	= ux500_remove,
3594bc36fd3SMian Yousaf Kaukab 	.driver		= {
3604bc36fd3SMian Yousaf Kaukab 		.name	= "musb-ux500",
361a89adb09SDaniel Mack 		.pm	= &ux500_pm_ops,
362313bdb11SLee Jones 		.of_match_table = ux500_match,
3634bc36fd3SMian Yousaf Kaukab 	},
3644bc36fd3SMian Yousaf Kaukab };
3654bc36fd3SMian Yousaf Kaukab 
3664bc36fd3SMian Yousaf Kaukab MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
3674bc36fd3SMian Yousaf Kaukab MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
3684bc36fd3SMian Yousaf Kaukab MODULE_LICENSE("GPL v2");
3690e7090a6SSrinivas Kandagatla module_platform_driver(ux500_driver);
370