• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 ST-Ericsson AB
3  * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
4  *
5  * Based on omap2430.c
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/clk.h>
26 #include <linux/err.h>
27 #include <linux/io.h>
28 #include <linux/platform_device.h>
29 #include <linux/usb/musb-ux500.h>
30 
31 #include "musb_core.h"
32 
33 struct ux500_glue {
34 	struct device		*dev;
35 	struct platform_device	*musb;
36 	struct clk		*clk;
37 };
38 #define glue_to_musb(g)	platform_get_drvdata(g->musb)
39 
ux500_musb_set_vbus(struct musb * musb,int is_on)40 static void ux500_musb_set_vbus(struct musb *musb, int is_on)
41 {
42 	u8            devctl;
43 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
44 	/* HDRC controls CPEN, but beware current surges during device
45 	 * connect.  They can trigger transient overcurrent conditions
46 	 * that must be ignored.
47 	 */
48 
49 	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
50 
51 	if (is_on) {
52 		if (musb->xceiv->state == OTG_STATE_A_IDLE) {
53 			/* start the session */
54 			devctl |= MUSB_DEVCTL_SESSION;
55 			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
56 			/*
57 			 * Wait for the musb to set as A device to enable the
58 			 * VBUS
59 			 */
60 			while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
61 
62 				if (time_after(jiffies, timeout)) {
63 					dev_err(musb->controller,
64 					"configured as A device timeout");
65 					break;
66 				}
67 			}
68 
69 		} else {
70 			musb->is_active = 1;
71 			musb->xceiv->otg->default_a = 1;
72 			musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
73 			devctl |= MUSB_DEVCTL_SESSION;
74 			MUSB_HST_MODE(musb);
75 		}
76 	} else {
77 		musb->is_active = 0;
78 
79 		/* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
80 		 * right to B_IDLE...
81 		 */
82 		musb->xceiv->otg->default_a = 0;
83 		devctl &= ~MUSB_DEVCTL_SESSION;
84 		MUSB_DEV_MODE(musb);
85 	}
86 	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
87 
88 	/*
89 	 * Devctl values will be updated after vbus goes below
90 	 * session_valid. The time taken depends on the capacitance
91 	 * on VBUS line. The max discharge time can be upto 1 sec
92 	 * as per the spec. Typically on our platform, it is 200ms
93 	 */
94 	if (!is_on)
95 		mdelay(200);
96 
97 	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
98 		usb_otg_state_string(musb->xceiv->state),
99 		musb_readb(musb->mregs, MUSB_DEVCTL));
100 }
101 
musb_otg_notifications(struct notifier_block * nb,unsigned long event,void * unused)102 static int musb_otg_notifications(struct notifier_block *nb,
103 		unsigned long event, void *unused)
104 {
105 	struct musb *musb = container_of(nb, struct musb, nb);
106 
107 	dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
108 			event, usb_otg_state_string(musb->xceiv->state));
109 
110 	switch (event) {
111 	case UX500_MUSB_ID:
112 		dev_dbg(musb->controller, "ID GND\n");
113 		ux500_musb_set_vbus(musb, 1);
114 		break;
115 	case UX500_MUSB_VBUS:
116 		dev_dbg(musb->controller, "VBUS Connect\n");
117 		break;
118 	case UX500_MUSB_NONE:
119 		dev_dbg(musb->controller, "VBUS Disconnect\n");
120 		if (is_host_active(musb))
121 			ux500_musb_set_vbus(musb, 0);
122 		else
123 			musb->xceiv->state = OTG_STATE_B_IDLE;
124 		break;
125 	default:
126 		dev_dbg(musb->controller, "ID float\n");
127 		return NOTIFY_DONE;
128 	}
129 	return NOTIFY_OK;
130 }
131 
ux500_musb_interrupt(int irq,void * __hci)132 static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
133 {
134 	unsigned long   flags;
135 	irqreturn_t     retval = IRQ_NONE;
136 	struct musb     *musb = __hci;
137 
138 	spin_lock_irqsave(&musb->lock, flags);
139 
140 	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
141 	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
142 	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
143 
144 	if (musb->int_usb || musb->int_tx || musb->int_rx)
145 		retval = musb_interrupt(musb);
146 
147 	spin_unlock_irqrestore(&musb->lock, flags);
148 
149 	return retval;
150 }
151 
ux500_musb_init(struct musb * musb)152 static int ux500_musb_init(struct musb *musb)
153 {
154 	int status;
155 
156 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
157 	if (IS_ERR_OR_NULL(musb->xceiv)) {
158 		pr_err("HS USB OTG: no transceiver configured\n");
159 		return -EPROBE_DEFER;
160 	}
161 
162 	musb->nb.notifier_call = musb_otg_notifications;
163 	status = usb_register_notifier(musb->xceiv, &musb->nb);
164 	if (status < 0) {
165 		dev_dbg(musb->controller, "notification register failed\n");
166 		return status;
167 	}
168 
169 	musb->isr = ux500_musb_interrupt;
170 
171 	return 0;
172 }
173 
ux500_musb_exit(struct musb * musb)174 static int ux500_musb_exit(struct musb *musb)
175 {
176 	usb_unregister_notifier(musb->xceiv, &musb->nb);
177 
178 	usb_put_phy(musb->xceiv);
179 
180 	return 0;
181 }
182 
183 static const struct musb_platform_ops ux500_ops = {
184 	.init		= ux500_musb_init,
185 	.exit		= ux500_musb_exit,
186 
187 	.set_vbus	= ux500_musb_set_vbus,
188 };
189 
ux500_probe(struct platform_device * pdev)190 static int ux500_probe(struct platform_device *pdev)
191 {
192 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
193 	struct platform_device		*musb;
194 	struct ux500_glue		*glue;
195 	struct clk			*clk;
196 	int				ret = -ENOMEM;
197 
198 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
199 	if (!glue) {
200 		dev_err(&pdev->dev, "failed to allocate glue context\n");
201 		goto err0;
202 	}
203 
204 	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
205 	if (!musb) {
206 		dev_err(&pdev->dev, "failed to allocate musb device\n");
207 		goto err1;
208 	}
209 
210 	clk = clk_get(&pdev->dev, "usb");
211 	if (IS_ERR(clk)) {
212 		dev_err(&pdev->dev, "failed to get clock\n");
213 		ret = PTR_ERR(clk);
214 		goto err3;
215 	}
216 
217 	ret = clk_prepare_enable(clk);
218 	if (ret) {
219 		dev_err(&pdev->dev, "failed to enable clock\n");
220 		goto err4;
221 	}
222 
223 	musb->dev.parent		= &pdev->dev;
224 	musb->dev.dma_mask		= pdev->dev.dma_mask;
225 	musb->dev.coherent_dma_mask	= pdev->dev.coherent_dma_mask;
226 
227 	glue->dev			= &pdev->dev;
228 	glue->musb			= musb;
229 	glue->clk			= clk;
230 
231 	pdata->platform_ops		= &ux500_ops;
232 
233 	platform_set_drvdata(pdev, glue);
234 
235 	ret = platform_device_add_resources(musb, pdev->resource,
236 			pdev->num_resources);
237 	if (ret) {
238 		dev_err(&pdev->dev, "failed to add resources\n");
239 		goto err5;
240 	}
241 
242 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
243 	if (ret) {
244 		dev_err(&pdev->dev, "failed to add platform_data\n");
245 		goto err5;
246 	}
247 
248 	ret = platform_device_add(musb);
249 	if (ret) {
250 		dev_err(&pdev->dev, "failed to register musb device\n");
251 		goto err5;
252 	}
253 
254 	return 0;
255 
256 err5:
257 	clk_disable_unprepare(clk);
258 
259 err4:
260 	clk_put(clk);
261 
262 err3:
263 	platform_device_put(musb);
264 
265 err1:
266 	kfree(glue);
267 
268 err0:
269 	return ret;
270 }
271 
ux500_remove(struct platform_device * pdev)272 static int ux500_remove(struct platform_device *pdev)
273 {
274 	struct ux500_glue	*glue = platform_get_drvdata(pdev);
275 
276 	platform_device_unregister(glue->musb);
277 	clk_disable_unprepare(glue->clk);
278 	clk_put(glue->clk);
279 	kfree(glue);
280 
281 	return 0;
282 }
283 
284 #ifdef CONFIG_PM
ux500_suspend(struct device * dev)285 static int ux500_suspend(struct device *dev)
286 {
287 	struct ux500_glue	*glue = dev_get_drvdata(dev);
288 	struct musb		*musb = glue_to_musb(glue);
289 
290 	usb_phy_set_suspend(musb->xceiv, 1);
291 	clk_disable_unprepare(glue->clk);
292 
293 	return 0;
294 }
295 
ux500_resume(struct device * dev)296 static int ux500_resume(struct device *dev)
297 {
298 	struct ux500_glue	*glue = dev_get_drvdata(dev);
299 	struct musb		*musb = glue_to_musb(glue);
300 	int			ret;
301 
302 	ret = clk_prepare_enable(glue->clk);
303 	if (ret) {
304 		dev_err(dev, "failed to enable clock\n");
305 		return ret;
306 	}
307 
308 	usb_phy_set_suspend(musb->xceiv, 0);
309 
310 	return 0;
311 }
312 
313 static const struct dev_pm_ops ux500_pm_ops = {
314 	.suspend	= ux500_suspend,
315 	.resume		= ux500_resume,
316 };
317 
318 #define DEV_PM_OPS	(&ux500_pm_ops)
319 #else
320 #define DEV_PM_OPS	NULL
321 #endif
322 
323 static struct platform_driver ux500_driver = {
324 	.probe		= ux500_probe,
325 	.remove		= ux500_remove,
326 	.driver		= {
327 		.name	= "musb-ux500",
328 		.pm	= DEV_PM_OPS,
329 	},
330 };
331 
332 MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
333 MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
334 MODULE_LICENSE("GPL v2");
335 module_platform_driver(ux500_driver);
336