xref: /linux/drivers/usb/renesas_usbhs/common.c (revision 12871a0bd67dd4db4418e1daafcd46e9d329ef10)
1 /*
2  * Renesas USB driver
3  *
4  * Copyright (C) 2011 Renesas Solutions Corp.
5  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15  *
16  */
17 #include <linux/io.h>
18 #include <linux/module.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/slab.h>
21 #include <linux/sysfs.h>
22 #include "./common.h"
23 
24 #define USBHSF_RUNTIME_PWCTRL	(1 << 0)
25 
26 /* status */
27 #define usbhsc_flags_init(p)   do {(p)->flags = 0; } while (0)
28 #define usbhsc_flags_set(p, b) ((p)->flags |=  (b))
29 #define usbhsc_flags_clr(p, b) ((p)->flags &= ~(b))
30 #define usbhsc_flags_has(p, b) ((p)->flags &   (b))
31 
32 /*
33  * platform call back
34  *
35  * renesas usb support platform callback function.
36  * Below macro call it.
37  * if platform doesn't have callback, it return 0 (no error)
38  */
39 #define usbhs_platform_call(priv, func, args...)\
40 	(!(priv) ? -ENODEV :			\
41 	 !((priv)->pfunc->func) ? 0 :		\
42 	 (priv)->pfunc->func(args))
43 
44 /*
45  *		common functions
46  */
47 u16 usbhs_read(struct usbhs_priv *priv, u32 reg)
48 {
49 	return ioread16(priv->base + reg);
50 }
51 
52 void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data)
53 {
54 	iowrite16(data, priv->base + reg);
55 }
56 
57 void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data)
58 {
59 	u16 val = usbhs_read(priv, reg);
60 
61 	val &= ~mask;
62 	val |= data & mask;
63 
64 	usbhs_write(priv, reg, val);
65 }
66 
67 struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev)
68 {
69 	return dev_get_drvdata(&pdev->dev);
70 }
71 
72 /*
73  *		syscfg functions
74  */
75 void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable)
76 {
77 	usbhs_bset(priv, SYSCFG, SCKE, enable ? SCKE : 0);
78 }
79 
80 void usbhs_sys_hispeed_ctrl(struct usbhs_priv *priv, int enable)
81 {
82 	usbhs_bset(priv, SYSCFG, HSE, enable ? HSE : 0);
83 }
84 
85 void usbhs_sys_usb_ctrl(struct usbhs_priv *priv, int enable)
86 {
87 	usbhs_bset(priv, SYSCFG, USBE, enable ? USBE : 0);
88 }
89 
90 void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
91 {
92 	u16 mask = DCFM | DRPD | DPRPU;
93 	u16 val  = DCFM | DRPD;
94 
95 	/*
96 	 * if enable
97 	 *
98 	 * - select Host mode
99 	 * - D+ Line/D- Line Pull-down
100 	 */
101 	usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
102 }
103 
104 void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
105 {
106 	u16 mask = DCFM | DRPD | DPRPU;
107 	u16 val  = DPRPU;
108 
109 	/*
110 	 * if enable
111 	 *
112 	 * - select Function mode
113 	 * - D+ Line Pull-up
114 	 */
115 	usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
116 }
117 
118 /*
119  *		frame functions
120  */
121 int usbhs_frame_get_num(struct usbhs_priv *priv)
122 {
123 	return usbhs_read(priv, FRMNUM) & FRNM_MASK;
124 }
125 
126 /*
127  *		local functions
128  */
129 static void usbhsc_bus_ctrl(struct usbhs_priv *priv, int enable)
130 {
131 	int wait = usbhs_get_dparam(priv, buswait_bwait);
132 	u16 data = 0;
133 
134 	if (enable) {
135 		/* set bus wait if platform have */
136 		if (wait)
137 			usbhs_bset(priv, BUSWAIT, 0x000F, wait);
138 	}
139 	usbhs_write(priv, DVSTCTR, data);
140 }
141 
142 /*
143  *		platform default param
144  */
145 static u32 usbhsc_default_pipe_type[] = {
146 		USB_ENDPOINT_XFER_CONTROL,
147 		USB_ENDPOINT_XFER_ISOC,
148 		USB_ENDPOINT_XFER_ISOC,
149 		USB_ENDPOINT_XFER_BULK,
150 		USB_ENDPOINT_XFER_BULK,
151 		USB_ENDPOINT_XFER_BULK,
152 		USB_ENDPOINT_XFER_INT,
153 		USB_ENDPOINT_XFER_INT,
154 		USB_ENDPOINT_XFER_INT,
155 		USB_ENDPOINT_XFER_INT,
156 };
157 
158 /*
159  *		power control
160  */
161 static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
162 {
163 	struct device *dev = usbhs_priv_to_dev(priv);
164 
165 	if (enable) {
166 		/* enable PM */
167 		pm_runtime_get_sync(dev);
168 
169 		/* USB on */
170 		usbhs_sys_clock_ctrl(priv, enable);
171 		usbhsc_bus_ctrl(priv, enable);
172 	} else {
173 		/* USB off */
174 		usbhsc_bus_ctrl(priv, enable);
175 		usbhs_sys_clock_ctrl(priv, enable);
176 
177 		/* disable PM */
178 		pm_runtime_put_sync(dev);
179 	}
180 }
181 
182 /*
183  *		notify hotplug
184  */
185 static void usbhsc_notify_hotplug(struct work_struct *work)
186 {
187 	struct usbhs_priv *priv = container_of(work,
188 					       struct usbhs_priv,
189 					       notify_hotplug_work.work);
190 	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
191 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
192 	int id;
193 	int enable;
194 	int ret;
195 
196 	/*
197 	 * get vbus status from platform
198 	 */
199 	enable = usbhs_platform_call(priv, get_vbus, pdev);
200 
201 	/*
202 	 * get id from platform
203 	 */
204 	id = usbhs_platform_call(priv, get_id, pdev);
205 
206 	if (enable && !mod) {
207 		ret = usbhs_mod_change(priv, id);
208 		if (ret < 0)
209 			return;
210 
211 		dev_dbg(&pdev->dev, "%s enable\n", __func__);
212 
213 		/* power on */
214 		if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
215 			usbhsc_power_ctrl(priv, enable);
216 
217 		/* module start */
218 		usbhs_mod_call(priv, start, priv);
219 
220 	} else if (!enable && mod) {
221 		dev_dbg(&pdev->dev, "%s disable\n", __func__);
222 
223 		/* module stop */
224 		usbhs_mod_call(priv, stop, priv);
225 
226 		/* power off */
227 		if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
228 			usbhsc_power_ctrl(priv, enable);
229 
230 		usbhs_mod_change(priv, -1);
231 
232 		/* reset phy for next connection */
233 		usbhs_platform_call(priv, phy_reset, pdev);
234 	}
235 }
236 
237 int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
238 {
239 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
240 	int delay = usbhs_get_dparam(priv, detection_delay);
241 
242 	/*
243 	 * This functions will be called in interrupt.
244 	 * To make sure safety context,
245 	 * use workqueue for usbhs_notify_hotplug
246 	 */
247 	schedule_delayed_work(&priv->notify_hotplug_work, delay);
248 	return 0;
249 }
250 
251 /*
252  *		platform functions
253  */
254 static int __devinit usbhs_probe(struct platform_device *pdev)
255 {
256 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
257 	struct renesas_usbhs_driver_callback *dfunc;
258 	struct usbhs_priv *priv;
259 	struct resource *res;
260 	unsigned int irq;
261 	int ret;
262 
263 	/* check platform information */
264 	if (!info ||
265 	    !info->platform_callback.get_id) {
266 		dev_err(&pdev->dev, "no platform information\n");
267 		return -EINVAL;
268 	}
269 
270 	/* platform data */
271 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
272 	irq = platform_get_irq(pdev, 0);
273 	if (!res || (int)irq <= 0) {
274 		dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
275 		return -ENODEV;
276 	}
277 
278 	/* usb private data */
279 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
280 	if (!priv) {
281 		dev_err(&pdev->dev, "Could not allocate priv\n");
282 		return -ENOMEM;
283 	}
284 
285 	priv->base = ioremap_nocache(res->start, resource_size(res));
286 	if (!priv->base) {
287 		dev_err(&pdev->dev, "ioremap error.\n");
288 		ret = -ENOMEM;
289 		goto probe_end_kfree;
290 	}
291 
292 	/*
293 	 * care platform info
294 	 */
295 	priv->pfunc	= &info->platform_callback;
296 	priv->dparam	= &info->driver_param;
297 
298 	/* set driver callback functions for platform */
299 	dfunc			= &info->driver_callback;
300 	dfunc->notify_hotplug	= usbhsc_drvcllbck_notify_hotplug;
301 
302 	/* set default param if platform doesn't have */
303 	if (!priv->dparam->pipe_type) {
304 		priv->dparam->pipe_type = usbhsc_default_pipe_type;
305 		priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
306 	}
307 
308 	/* FIXME */
309 	/* runtime power control ? */
310 	if (priv->pfunc->get_vbus)
311 		usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL);
312 
313 	/*
314 	 * priv settings
315 	 */
316 	priv->irq	= irq;
317 	priv->pdev	= pdev;
318 	INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
319 	spin_lock_init(usbhs_priv_to_lock(priv));
320 
321 	/* call pipe and module init */
322 	ret = usbhs_pipe_probe(priv);
323 	if (ret < 0)
324 		goto probe_end_iounmap;
325 
326 	ret = usbhs_mod_probe(priv);
327 	if (ret < 0)
328 		goto probe_end_pipe_exit;
329 
330 	/* dev_set_drvdata should be called after usbhs_mod_init */
331 	dev_set_drvdata(&pdev->dev, priv);
332 
333 	/*
334 	 * deviece reset here because
335 	 * USB device might be used in boot loader.
336 	 */
337 	usbhs_sys_clock_ctrl(priv, 0);
338 
339 	/*
340 	 * platform call
341 	 *
342 	 * USB phy setup might depend on CPU/Board.
343 	 * If platform has its callback functions,
344 	 * call it here.
345 	 */
346 	ret = usbhs_platform_call(priv, hardware_init, pdev);
347 	if (ret < 0) {
348 		dev_err(&pdev->dev, "platform prove failed.\n");
349 		goto probe_end_mod_exit;
350 	}
351 
352 	/* reset phy for connection */
353 	usbhs_platform_call(priv, phy_reset, pdev);
354 
355 	/* power control */
356 	pm_runtime_enable(&pdev->dev);
357 	if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
358 		usbhsc_power_ctrl(priv, 1);
359 		usbhs_mod_autonomy_mode(priv);
360 	}
361 
362 	/*
363 	 * manual call notify_hotplug for cold plug
364 	 */
365 	ret = usbhsc_drvcllbck_notify_hotplug(pdev);
366 	if (ret < 0)
367 		goto probe_end_call_remove;
368 
369 	dev_info(&pdev->dev, "probed\n");
370 
371 	return ret;
372 
373 probe_end_call_remove:
374 	usbhs_platform_call(priv, hardware_exit, pdev);
375 probe_end_mod_exit:
376 	usbhs_mod_remove(priv);
377 probe_end_pipe_exit:
378 	usbhs_pipe_remove(priv);
379 probe_end_iounmap:
380 	iounmap(priv->base);
381 probe_end_kfree:
382 	kfree(priv);
383 
384 	dev_info(&pdev->dev, "probe failed\n");
385 
386 	return ret;
387 }
388 
389 static int __devexit usbhs_remove(struct platform_device *pdev)
390 {
391 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
392 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
393 	struct renesas_usbhs_driver_callback *dfunc = &info->driver_callback;
394 
395 	dev_dbg(&pdev->dev, "usb remove\n");
396 
397 	dfunc->notify_hotplug = NULL;
398 
399 	/* power off */
400 	if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
401 		usbhsc_power_ctrl(priv, 0);
402 
403 	pm_runtime_disable(&pdev->dev);
404 
405 	usbhs_platform_call(priv, hardware_exit, pdev);
406 	usbhs_mod_remove(priv);
407 	usbhs_pipe_remove(priv);
408 	iounmap(priv->base);
409 	kfree(priv);
410 
411 	return 0;
412 }
413 
414 static struct platform_driver renesas_usbhs_driver = {
415 	.driver		= {
416 		.name	= "renesas_usbhs",
417 	},
418 	.probe		= usbhs_probe,
419 	.remove		= __devexit_p(usbhs_remove),
420 };
421 
422 static int __init usbhs_init(void)
423 {
424 	return platform_driver_register(&renesas_usbhs_driver);
425 }
426 
427 static void __exit usbhs_exit(void)
428 {
429 	platform_driver_unregister(&renesas_usbhs_driver);
430 }
431 
432 module_init(usbhs_init);
433 module_exit(usbhs_exit);
434 
435 MODULE_LICENSE("GPL");
436 MODULE_DESCRIPTION("Renesas USB driver");
437 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
438