aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/blackfin.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2010-12-16 13:05:06 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-16 13:05:06 -0500
commit36facadd9ea98f8415d0dbb63e0763b7ee9d3911 (patch)
tree99dea00b332ed852f2b0a4923b581dd723f03634 /drivers/usb/musb/blackfin.c
parent2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff)
parent0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff)
Merge branch 'usb-next' into musb-merge
* usb-next: (132 commits) USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path USB: uas: Ensure we only bind to a UAS interface USB: uas: Rename sense pipe and sense urb to status pipe and status urb USB: uas: Use kzalloc instead of kmalloc USB: uas: Fix up the Sense IU usb: musb: core: kill unneeded #include's DA8xx: assign name to MUSB IRQ resource usb: gadget: g_ncm added usb: gadget: f_ncm.c added usb: gadget: u_ether: prepare for NCM usb: pch_udc: Fix setup transfers with data out usb: pch_udc: Fix compile error, warnings and checkpatch warnings usb: add ab8500 usb transceiver driver USB: gadget: Implement runtime PM for MSM bus glue driver USB: gadget: Implement runtime PM for ci13xxx gadget USB: gadget: Add USB controller driver for MSM SoC USB: gadget: Introduce ci13xxx_udc_driver struct USB: gadget: Initialize ci13xxx gadget device's coherent DMA mask USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc USB: gadget: Separate out PCI bus code from ci13xxx_udc ...
Diffstat (limited to 'drivers/usb/musb/blackfin.c')
-rw-r--r--drivers/usb/musb/blackfin.c229
1 files changed, 196 insertions, 33 deletions
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 930a2611fe3e..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,51 +311,29 @@ 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
327int __init musb_platform_init(struct musb *musb, void *board_data) 335static void bfin_musb_reg_init(struct musb *musb)
328{ 336{
329
330 /*
331 * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE
332 * and OTG HOST modes, while rev 1.1 and greater require PE7 to
333 * be low for DEVICE mode and high for HOST mode. We set it high
334 * here because we are in host mode
335 */
336
337 if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) {
338 printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d \n",
339 musb->config->gpio_vrsel);
340 return -ENODEV;
341 }
342 gpio_direction_output(musb->config->gpio_vrsel, 0);
343
344 usb_nop_xceiv_register();
345 musb->xceiv = otg_get_transceiver();
346 if (!musb->xceiv) {
347 gpio_free(musb->config->gpio_vrsel);
348 return -ENODEV;
349 }
350
351 if (ANOMALY_05000346) { 337 if (ANOMALY_05000346) {
352 bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); 338 bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
353 SSYNC(); 339 SSYNC();
@@ -382,21 +368,47 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
382 EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | 368 EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA |
383 EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); 369 EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA);
384 SSYNC(); 370 SSYNC();
371}
372
373static int bfin_musb_init(struct musb *musb)
374{
375
376 /*
377 * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE
378 * and OTG HOST modes, while rev 1.1 and greater require PE7 to
379 * be low for DEVICE mode and high for HOST mode. We set it high
380 * here because we are in host mode
381 */
382
383 if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) {
384 printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d\n",
385 musb->config->gpio_vrsel);
386 return -ENODEV;
387 }
388 gpio_direction_output(musb->config->gpio_vrsel, 0);
389
390 usb_nop_xceiv_register();
391 musb->xceiv = otg_get_transceiver();
392 if (!musb->xceiv) {
393 gpio_free(musb->config->gpio_vrsel);
394 return -ENODEV;
395 }
396
397 bfin_musb_reg_init(musb);
385 398
386 if (is_host_enabled(musb)) { 399 if (is_host_enabled(musb)) {
387 musb->board_set_vbus = bfin_set_vbus;
388 setup_timer(&musb_conn_timer, 400 setup_timer(&musb_conn_timer,
389 musb_conn_timer_handler, (unsigned long) musb); 401 musb_conn_timer_handler, (unsigned long) musb);
390 } 402 }
391 if (is_peripheral_enabled(musb)) 403 if (is_peripheral_enabled(musb))
392 musb->xceiv->set_power = bfin_set_power; 404 musb->xceiv->set_power = bfin_musb_set_power;
393 405
394 musb->isr = blackfin_interrupt; 406 musb->isr = blackfin_interrupt;
395 407
396 return 0; 408 return 0;
397} 409}
398 410
399int musb_platform_exit(struct musb *musb) 411static int bfin_musb_exit(struct musb *musb)
400{ 412{
401 gpio_free(musb->config->gpio_vrsel); 413 gpio_free(musb->config->gpio_vrsel);
402 414
@@ -404,3 +416,154 @@ int musb_platform_exit(struct musb *musb)
404 usb_nop_xceiv_unregister(); 416 usb_nop_xceiv_unregister();
405 return 0; 417 return 0;
406} 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
509#ifdef CONFIG_PM
510static int bfin_suspend(struct device *dev)
511{
512 struct bfin_glue *glue = dev_get_drvdata(dev);
513 struct musb *musb = glue_to_musb(glue);
514
515 if (is_host_active(musb))
516 /*
517 * During hibernate gpio_vrsel will change from high to low
518 * low which will generate wakeup event resume the system
519 * immediately. Set it to 0 before hibernate to avoid this
520 * wakeup event.
521 */
522 gpio_set_value(musb->config->gpio_vrsel, 0);
523
524 return 0;
525}
526
527static int bfin_resume(struct device *dev)
528{
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;
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
545#endif
546
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)
560{
561 return platform_driver_probe(&bfin_driver, bfin_probe);
562}
563subsys_initcall(bfin_init);
564
565static void __exit bfin_exit(void)
566{
567 platform_driver_unregister(&bfin_driver);
568}
569module_exit(bfin_exit);