aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/blackfin.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/blackfin.c')
-rw-r--r--drivers/usb/musb/blackfin.c181
1 files changed, 159 insertions, 22 deletions
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index fcb5206a65bd..eeba228eb2af 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -15,12 +15,20 @@
15#include <linux/list.h> 15#include <linux/list.h>
16#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/platform_device.h>
19#include <linux/dma-mapping.h>
18 20
19#include <asm/cacheflush.h> 21#include <asm/cacheflush.h>
20 22
21#include "musb_core.h" 23#include "musb_core.h"
22#include "blackfin.h" 24#include "blackfin.h"
23 25
26struct bfin_glue {
27 struct device *dev;
28 struct platform_device *musb;
29};
30#define glue_to_musb(g) platform_get_drvdata(g->musb)
31
24/* 32/*
25 * Load an endpoint's FIFO 33 * Load an endpoint's FIFO
26 */ 34 */
@@ -278,7 +286,7 @@ static void musb_conn_timer_handler(unsigned long _musb)
278 DBG(4, "state is %s\n", otg_state_string(musb)); 286 DBG(4, "state is %s\n", otg_state_string(musb));
279} 287}
280 288
281void musb_platform_enable(struct musb *musb) 289static void bfin_musb_enable(struct musb *musb)
282{ 290{
283 if (!is_otg_enabled(musb) && is_host_enabled(musb)) { 291 if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
284 mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); 292 mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
@@ -286,11 +294,11 @@ void musb_platform_enable(struct musb *musb)
286 } 294 }
287} 295}
288 296
289void musb_platform_disable(struct musb *musb) 297static void bfin_musb_disable(struct musb *musb)
290{ 298{
291} 299}
292 300
293static void bfin_set_vbus(struct musb *musb, int is_on) 301static void bfin_musb_set_vbus(struct musb *musb, int is_on)
294{ 302{
295 int value = musb->config->gpio_vrsel_active; 303 int value = musb->config->gpio_vrsel_active;
296 if (!is_on) 304 if (!is_on)
@@ -303,28 +311,28 @@ static void bfin_set_vbus(struct musb *musb, int is_on)
303 musb_readb(musb->mregs, MUSB_DEVCTL)); 311 musb_readb(musb->mregs, MUSB_DEVCTL));
304} 312}
305 313
306static int bfin_set_power(struct otg_transceiver *x, unsigned mA) 314static int bfin_musb_set_power(struct otg_transceiver *x, unsigned mA)
307{ 315{
308 return 0; 316 return 0;
309} 317}
310 318
311void musb_platform_try_idle(struct musb *musb, unsigned long timeout) 319static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout)
312{ 320{
313 if (!is_otg_enabled(musb) && is_host_enabled(musb)) 321 if (!is_otg_enabled(musb) && is_host_enabled(musb))
314 mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); 322 mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
315} 323}
316 324
317int musb_platform_get_vbus_status(struct musb *musb) 325static int bfin_musb_get_vbus_status(struct musb *musb)
318{ 326{
319 return 0; 327 return 0;
320} 328}
321 329
322int musb_platform_set_mode(struct musb *musb, u8 musb_mode) 330static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
323{ 331{
324 return -EIO; 332 return -EIO;
325} 333}
326 334
327static void musb_platform_reg_init(struct musb *musb) 335static void bfin_musb_reg_init(struct musb *musb)
328{ 336{
329 if (ANOMALY_05000346) { 337 if (ANOMALY_05000346) {
330 bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); 338 bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
@@ -362,7 +370,7 @@ static void musb_platform_reg_init(struct musb *musb)
362 SSYNC(); 370 SSYNC();
363} 371}
364 372
365int __init musb_platform_init(struct musb *musb, void *board_data) 373static int bfin_musb_init(struct musb *musb)
366{ 374{
367 375
368 /* 376 /*
@@ -386,25 +394,124 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
386 return -ENODEV; 394 return -ENODEV;
387 } 395 }
388 396
389 musb_platform_reg_init(musb); 397 bfin_musb_reg_init(musb);
390 398
391 if (is_host_enabled(musb)) { 399 if (is_host_enabled(musb)) {
392 musb->board_set_vbus = bfin_set_vbus;
393 setup_timer(&musb_conn_timer, 400 setup_timer(&musb_conn_timer,
394 musb_conn_timer_handler, (unsigned long) musb); 401 musb_conn_timer_handler, (unsigned long) musb);
395 } 402 }
396 if (is_peripheral_enabled(musb)) 403 if (is_peripheral_enabled(musb))
397 musb->xceiv->set_power = bfin_set_power; 404 musb->xceiv->set_power = bfin_musb_set_power;
398 405
399 musb->isr = blackfin_interrupt; 406 musb->isr = blackfin_interrupt;
400 407
401 return 0; 408 return 0;
402} 409}
403 410
411static int bfin_musb_exit(struct musb *musb)
412{
413 gpio_free(musb->config->gpio_vrsel);
414
415 otg_put_transceiver(musb->xceiv);
416 usb_nop_xceiv_unregister();
417 return 0;
418}
419
420static const struct musb_platform_ops bfin_ops = {
421 .init = bfin_musb_init,
422 .exit = bfin_musb_exit,
423
424 .enable = bfin_musb_enable,
425 .disable = bfin_musb_disable,
426
427 .set_mode = bfin_musb_set_mode,
428 .try_idle = bfin_musb_try_idle,
429
430 .vbus_status = bfin_musb_vbus_status,
431 .set_vbus = bfin_musb_set_vbus,
432};
433
434static u64 bfin_dmamask = DMA_BIT_MASK(32);
435
436static int __init bfin_probe(struct platform_device *pdev)
437{
438 struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
439 struct platform_device *musb;
440 struct bfin_glue *glue;
441
442 int ret = -ENOMEM;
443
444 glue = kzalloc(sizeof(*glue), GFP_KERNEL);
445 if (!glue) {
446 dev_err(&pdev->dev, "failed to allocate glue context\n");
447 goto err0;
448 }
449
450 musb = platform_device_alloc("musb-hdrc", -1);
451 if (!musb) {
452 dev_err(&pdev->dev, "failed to allocate musb device\n");
453 goto err1;
454 }
455
456 musb->dev.parent = &pdev->dev;
457 musb->dev.dma_mask = &bfin_dmamask;
458 musb->dev.coherent_dma_mask = bfin_dmamask;
459
460 glue->dev = &pdev->dev;
461 glue->musb = musb;
462
463 pdata->platform_ops = &bfin_ops;
464
465 platform_set_drvdata(pdev, glue);
466
467 ret = platform_device_add_resources(musb, pdev->resource,
468 pdev->num_resources);
469 if (ret) {
470 dev_err(&pdev->dev, "failed to add resources\n");
471 goto err2;
472 }
473
474 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
475 if (ret) {
476 dev_err(&pdev->dev, "failed to add platform_data\n");
477 goto err2;
478 }
479
480 ret = platform_device_add(musb);
481 if (ret) {
482 dev_err(&pdev->dev, "failed to register musb device\n");
483 goto err2;
484 }
485
486 return 0;
487
488err2:
489 platform_device_put(musb);
490
491err1:
492 kfree(glue);
493
494err0:
495 return ret;
496}
497
498static int __exit bfin_remove(struct platform_device *pdev)
499{
500 struct bfin_glue *glue = platform_get_drvdata(pdev);
501
502 platform_device_del(glue->musb);
503 platform_device_put(glue->musb);
504 kfree(glue);
505
506 return 0;
507}
508
404#ifdef CONFIG_PM 509#ifdef CONFIG_PM
405void musb_platform_save_context(struct musb *musb, 510static int bfin_suspend(struct device *dev)
406 struct musb_context_registers *musb_context)
407{ 511{
512 struct bfin_glue *glue = dev_get_drvdata(dev);
513 struct musb *musb = glue_to_musb(glue);
514
408 if (is_host_active(musb)) 515 if (is_host_active(musb))
409 /* 516 /*
410 * During hibernate gpio_vrsel will change from high to low 517 * During hibernate gpio_vrsel will change from high to low
@@ -413,20 +520,50 @@ void musb_platform_save_context(struct musb *musb,
413 * wakeup event. 520 * wakeup event.
414 */ 521 */
415 gpio_set_value(musb->config->gpio_vrsel, 0); 522 gpio_set_value(musb->config->gpio_vrsel, 0);
523
524 return 0;
416} 525}
417 526
418void musb_platform_restore_context(struct musb *musb, 527static int bfin_resume(struct device *dev)
419 struct musb_context_registers *musb_context)
420{ 528{
421 musb_platform_reg_init(musb); 529 struct bfin_glue *glue = dev_get_drvdata(dev);
530 struct musb *musb = glue_to_musb(glue);
531
532 bfin_musb_reg_init(musb);
533
534 return 0;
422} 535}
536
537static struct dev_pm_ops bfin_pm_ops = {
538 .suspend = bfin_suspend,
539 .resume = bfin_resume,
540};
541
542#define DEV_PM_OPS &bfin_pm_op,
543#else
544#define DEV_PM_OPS NULL
423#endif 545#endif
424 546
425int musb_platform_exit(struct musb *musb) 547static struct platform_driver bfin_driver = {
548 .remove = __exit_p(bfin_remove),
549 .driver = {
550 .name = "musb-bfin",
551 .pm = DEV_PM_OPS,
552 },
553};
554
555MODULE_DESCRIPTION("Blackfin MUSB Glue Layer");
556MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>");
557MODULE_LICENSE("GPL v2");
558
559static int __init bfin_init(void)
426{ 560{
427 gpio_free(musb->config->gpio_vrsel); 561 return platform_driver_probe(&bfin_driver, bfin_probe);
562}
563subsys_initcall(bfin_init);
428 564
429 otg_put_transceiver(musb->xceiv); 565static void __exit bfin_exit(void)
430 usb_nop_xceiv_unregister(); 566{
431 return 0; 567 platform_driver_unregister(&bfin_driver);
432} 568}
569module_exit(bfin_exit);