aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/omap2430.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 18:35:41 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-05 18:35:41 -0400
commitff9cce82772a78983b529e044d85884d3ec95fda (patch)
tree6491adac0538739a415f7b776d1865ce7ae5d1f7 /drivers/usb/musb/omap2430.c
parent933141509cefd64102a943d61d154c5c53bad889 (diff)
parentf8ecf829481b2cc7301a811da9d2df53ef174977 (diff)
Merge tag 'xceiv-for-v3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
usb: phy: patches for v3.6 merge window We are starting to support multiple USB phys as we should thanks for Kishon's work. DeviceTree support for USB PHYs won't come until discussion with DeviceTree maintainer is finished. Together with that series, we have one fix for twl4030 which missed a IRQF_ONESHOT annotation when requesting a threaded IRQ without a top half handler, and removal of an unused variable compilation warning to isp1301_omap.
Diffstat (limited to 'drivers/usb/musb/omap2430.c')
-rw-r--r--drivers/usb/musb/omap2430.c124
1 files changed, 77 insertions, 47 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index c7785e81254c..5fdb9da8dd56 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,6 +34,7 @@
34#include <linux/dma-mapping.h> 34#include <linux/dma-mapping.h>
35#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
36#include <linux/err.h> 36#include <linux/err.h>
37#include <linux/usb/musb-omap.h>
37 38
38#include "musb_core.h" 39#include "musb_core.h"
39#include "omap2430.h" 40#include "omap2430.h"
@@ -41,9 +42,13 @@
41struct omap2430_glue { 42struct omap2430_glue {
42 struct device *dev; 43 struct device *dev;
43 struct platform_device *musb; 44 struct platform_device *musb;
45 enum omap_musb_vbus_id_status status;
46 struct work_struct omap_musb_mailbox_work;
44}; 47};
45#define glue_to_musb(g) platform_get_drvdata(g->musb) 48#define glue_to_musb(g) platform_get_drvdata(g->musb)
46 49
50struct omap2430_glue *_glue;
51
47static struct timer_list musb_idle_timer; 52static struct timer_list musb_idle_timer;
48 53
49static void musb_do_idle(unsigned long _musb) 54static void musb_do_idle(unsigned long _musb)
@@ -223,50 +228,63 @@ static inline void omap2430_low_level_init(struct musb *musb)
223 musb_writel(musb->mregs, OTG_FORCESTDBY, l); 228 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
224} 229}
225 230
226static int musb_otg_notifications(struct notifier_block *nb, 231void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
227 unsigned long event, void *unused)
228{ 232{
229 struct musb *musb = container_of(nb, struct musb, nb); 233 struct omap2430_glue *glue = _glue;
234 struct musb *musb = glue_to_musb(glue);
230 235
231 musb->xceiv_event = event; 236 glue->status = status;
232 schedule_work(&musb->otg_notifier_work); 237 if (!musb) {
238 dev_err(glue->dev, "musb core is not yet ready\n");
239 return;
240 }
233 241
234 return NOTIFY_OK; 242 schedule_work(&glue->omap_musb_mailbox_work);
235} 243}
244EXPORT_SYMBOL_GPL(omap_musb_mailbox);
236 245
237static void musb_otg_notifier_work(struct work_struct *data_notifier_work) 246static void omap_musb_set_mailbox(struct omap2430_glue *glue)
238{ 247{
239 struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work); 248 struct musb *musb = glue_to_musb(glue);
240 struct device *dev = musb->controller; 249 struct device *dev = musb->controller;
241 struct musb_hdrc_platform_data *pdata = dev->platform_data; 250 struct musb_hdrc_platform_data *pdata = dev->platform_data;
242 struct omap_musb_board_data *data = pdata->board_data; 251 struct omap_musb_board_data *data = pdata->board_data;
252 struct usb_otg *otg = musb->xceiv->otg;
243 253
244 switch (musb->xceiv_event) { 254 switch (glue->status) {
245 case USB_EVENT_ID: 255 case OMAP_MUSB_ID_GROUND:
246 dev_dbg(musb->controller, "ID GND\n"); 256 dev_dbg(dev, "ID GND\n");
247 257
258 otg->default_a = true;
259 musb->xceiv->state = OTG_STATE_A_IDLE;
260 musb->xceiv->last_event = USB_EVENT_ID;
248 if (!is_otg_enabled(musb) || musb->gadget_driver) { 261 if (!is_otg_enabled(musb) || musb->gadget_driver) {
249 pm_runtime_get_sync(musb->controller); 262 pm_runtime_get_sync(dev);
250 usb_phy_init(musb->xceiv); 263 usb_phy_init(musb->xceiv);
251 omap2430_musb_set_vbus(musb, 1); 264 omap2430_musb_set_vbus(musb, 1);
252 } 265 }
253 break; 266 break;
254 267
255 case USB_EVENT_VBUS: 268 case OMAP_MUSB_VBUS_VALID:
256 dev_dbg(musb->controller, "VBUS Connect\n"); 269 dev_dbg(dev, "VBUS Connect\n");
257 270
271 otg->default_a = false;
272 musb->xceiv->state = OTG_STATE_B_IDLE;
273 musb->xceiv->last_event = USB_EVENT_VBUS;
258 if (musb->gadget_driver) 274 if (musb->gadget_driver)
259 pm_runtime_get_sync(musb->controller); 275 pm_runtime_get_sync(dev);
260 usb_phy_init(musb->xceiv); 276 usb_phy_init(musb->xceiv);
261 break; 277 break;
262 278
263 case USB_EVENT_NONE: 279 case OMAP_MUSB_ID_FLOAT:
264 dev_dbg(musb->controller, "VBUS Disconnect\n"); 280 case OMAP_MUSB_VBUS_OFF:
281 dev_dbg(dev, "VBUS Disconnect\n");
265 282
283 musb->xceiv->last_event = USB_EVENT_NONE;
266 if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) 284 if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
267 if (musb->gadget_driver) { 285 if (musb->gadget_driver) {
268 pm_runtime_mark_last_busy(musb->controller); 286 pm_runtime_mark_last_busy(dev);
269 pm_runtime_put_autosuspend(musb->controller); 287 pm_runtime_put_autosuspend(dev);
270 } 288 }
271 289
272 if (data->interface_type == MUSB_INTERFACE_UTMI) { 290 if (data->interface_type == MUSB_INTERFACE_UTMI) {
@@ -276,15 +294,24 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
276 usb_phy_shutdown(musb->xceiv); 294 usb_phy_shutdown(musb->xceiv);
277 break; 295 break;
278 default: 296 default:
279 dev_dbg(musb->controller, "ID float\n"); 297 dev_dbg(dev, "ID float\n");
280 } 298 }
281} 299}
282 300
301
302static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
303{
304 struct omap2430_glue *glue = container_of(mailbox_work,
305 struct omap2430_glue, omap_musb_mailbox_work);
306 omap_musb_set_mailbox(glue);
307}
308
283static int omap2430_musb_init(struct musb *musb) 309static int omap2430_musb_init(struct musb *musb)
284{ 310{
285 u32 l; 311 u32 l;
286 int status = 0; 312 int status = 0;
287 struct device *dev = musb->controller; 313 struct device *dev = musb->controller;
314 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
288 struct musb_hdrc_platform_data *plat = dev->platform_data; 315 struct musb_hdrc_platform_data *plat = dev->platform_data;
289 struct omap_musb_board_data *data = plat->board_data; 316 struct omap_musb_board_data *data = plat->board_data;
290 317
@@ -292,14 +319,12 @@ static int omap2430_musb_init(struct musb *musb)
292 * up through ULPI. TWL4030-family PMICs include one, 319 * up through ULPI. TWL4030-family PMICs include one,
293 * which needs a driver, drivers aren't always needed. 320 * which needs a driver, drivers aren't always needed.
294 */ 321 */
295 musb->xceiv = usb_get_transceiver(); 322 musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
296 if (!musb->xceiv) { 323 if (IS_ERR_OR_NULL(musb->xceiv)) {
297 pr_err("HS USB OTG: no transceiver configured\n"); 324 pr_err("HS USB OTG: no transceiver configured\n");
298 return -ENODEV; 325 return -ENODEV;
299 } 326 }
300 327
301 INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
302
303 status = pm_runtime_get_sync(dev); 328 status = pm_runtime_get_sync(dev);
304 if (status < 0) { 329 if (status < 0) {
305 dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); 330 dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -326,14 +351,11 @@ static int omap2430_musb_init(struct musb *musb)
326 musb_readl(musb->mregs, OTG_INTERFSEL), 351 musb_readl(musb->mregs, OTG_INTERFSEL),
327 musb_readl(musb->mregs, OTG_SIMENABLE)); 352 musb_readl(musb->mregs, OTG_SIMENABLE));
328 353
329 musb->nb.notifier_call = musb_otg_notifications;
330 status = usb_register_notifier(musb->xceiv, &musb->nb);
331
332 if (status)
333 dev_dbg(musb->controller, "notification register failed\n");
334
335 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); 354 setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
336 355
356 if (glue->status != OMAP_MUSB_UNKNOWN)
357 omap_musb_set_mailbox(glue);
358
337 pm_runtime_put_noidle(musb->controller); 359 pm_runtime_put_noidle(musb->controller);
338 return 0; 360 return 0;
339 361
@@ -346,12 +368,13 @@ static void omap2430_musb_enable(struct musb *musb)
346 u8 devctl; 368 u8 devctl;
347 unsigned long timeout = jiffies + msecs_to_jiffies(1000); 369 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
348 struct device *dev = musb->controller; 370 struct device *dev = musb->controller;
371 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
349 struct musb_hdrc_platform_data *pdata = dev->platform_data; 372 struct musb_hdrc_platform_data *pdata = dev->platform_data;
350 struct omap_musb_board_data *data = pdata->board_data; 373 struct omap_musb_board_data *data = pdata->board_data;
351 374
352 switch (musb->xceiv->last_event) { 375 switch (glue->status) {
353 376
354 case USB_EVENT_ID: 377 case OMAP_MUSB_ID_GROUND:
355 usb_phy_init(musb->xceiv); 378 usb_phy_init(musb->xceiv);
356 if (data->interface_type != MUSB_INTERFACE_UTMI) 379 if (data->interface_type != MUSB_INTERFACE_UTMI)
357 break; 380 break;
@@ -370,7 +393,7 @@ static void omap2430_musb_enable(struct musb *musb)
370 } 393 }
371 break; 394 break;
372 395
373 case USB_EVENT_VBUS: 396 case OMAP_MUSB_VBUS_VALID:
374 usb_phy_init(musb->xceiv); 397 usb_phy_init(musb->xceiv);
375 break; 398 break;
376 399
@@ -381,17 +404,18 @@ static void omap2430_musb_enable(struct musb *musb)
381 404
382static void omap2430_musb_disable(struct musb *musb) 405static void omap2430_musb_disable(struct musb *musb)
383{ 406{
384 if (musb->xceiv->last_event) 407 struct device *dev = musb->controller;
408 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
409
410 if (glue->status != OMAP_MUSB_UNKNOWN)
385 usb_phy_shutdown(musb->xceiv); 411 usb_phy_shutdown(musb->xceiv);
386} 412}
387 413
388static int omap2430_musb_exit(struct musb *musb) 414static int omap2430_musb_exit(struct musb *musb)
389{ 415{
390 del_timer_sync(&musb_idle_timer); 416 del_timer_sync(&musb_idle_timer);
391 cancel_work_sync(&musb->otg_notifier_work);
392 417
393 omap2430_low_level_exit(musb); 418 omap2430_low_level_exit(musb);
394 usb_put_transceiver(musb->xceiv);
395 419
396 return 0; 420 return 0;
397} 421}
@@ -418,7 +442,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
418 struct omap2430_glue *glue; 442 struct omap2430_glue *glue;
419 int ret = -ENOMEM; 443 int ret = -ENOMEM;
420 444
421 glue = kzalloc(sizeof(*glue), GFP_KERNEL); 445 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
422 if (!glue) { 446 if (!glue) {
423 dev_err(&pdev->dev, "failed to allocate glue context\n"); 447 dev_err(&pdev->dev, "failed to allocate glue context\n");
424 goto err0; 448 goto err0;
@@ -427,7 +451,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
427 musb = platform_device_alloc("musb-hdrc", -1); 451 musb = platform_device_alloc("musb-hdrc", -1);
428 if (!musb) { 452 if (!musb) {
429 dev_err(&pdev->dev, "failed to allocate musb device\n"); 453 dev_err(&pdev->dev, "failed to allocate musb device\n");
430 goto err1; 454 goto err0;
431 } 455 }
432 456
433 musb->dev.parent = &pdev->dev; 457 musb->dev.parent = &pdev->dev;
@@ -436,22 +460,31 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
436 460
437 glue->dev = &pdev->dev; 461 glue->dev = &pdev->dev;
438 glue->musb = musb; 462 glue->musb = musb;
463 glue->status = OMAP_MUSB_UNKNOWN;
439 464
440 pdata->platform_ops = &omap2430_ops; 465 pdata->platform_ops = &omap2430_ops;
441 466
442 platform_set_drvdata(pdev, glue); 467 platform_set_drvdata(pdev, glue);
443 468
469 /*
470 * REVISIT if we ever have two instances of the wrapper, we will be
471 * in big trouble
472 */
473 _glue = glue;
474
475 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
476
444 ret = platform_device_add_resources(musb, pdev->resource, 477 ret = platform_device_add_resources(musb, pdev->resource,
445 pdev->num_resources); 478 pdev->num_resources);
446 if (ret) { 479 if (ret) {
447 dev_err(&pdev->dev, "failed to add resources\n"); 480 dev_err(&pdev->dev, "failed to add resources\n");
448 goto err2; 481 goto err1;
449 } 482 }
450 483
451 ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); 484 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
452 if (ret) { 485 if (ret) {
453 dev_err(&pdev->dev, "failed to add platform_data\n"); 486 dev_err(&pdev->dev, "failed to add platform_data\n");
454 goto err2; 487 goto err1;
455 } 488 }
456 489
457 pm_runtime_enable(&pdev->dev); 490 pm_runtime_enable(&pdev->dev);
@@ -459,16 +492,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
459 ret = platform_device_add(musb); 492 ret = platform_device_add(musb);
460 if (ret) { 493 if (ret) {
461 dev_err(&pdev->dev, "failed to register musb device\n"); 494 dev_err(&pdev->dev, "failed to register musb device\n");
462 goto err2; 495 goto err1;
463 } 496 }
464 497
465 return 0; 498 return 0;
466 499
467err2:
468 platform_device_put(musb);
469
470err1: 500err1:
471 kfree(glue); 501 platform_device_put(musb);
472 502
473err0: 503err0:
474 return ret; 504 return ret;
@@ -478,9 +508,9 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
478{ 508{
479 struct omap2430_glue *glue = platform_get_drvdata(pdev); 509 struct omap2430_glue *glue = platform_get_drvdata(pdev);
480 510
511 cancel_work_sync(&glue->omap_musb_mailbox_work);
481 platform_device_del(glue->musb); 512 platform_device_del(glue->musb);
482 platform_device_put(glue->musb); 513 platform_device_put(glue->musb);
483 kfree(glue);
484 514
485 return 0; 515 return 0;
486} 516}
@@ -546,7 +576,7 @@ static int __init omap2430_init(void)
546{ 576{
547 return platform_driver_register(&omap2430_driver); 577 return platform_driver_register(&omap2430_driver);
548} 578}
549module_init(omap2430_init); 579subsys_initcall(omap2430_init);
550 580
551static void __exit omap2430_exit(void) 581static void __exit omap2430_exit(void)
552{ 582{