diff options
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/host/ehci-tegra.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index db9d1b4bfbdc..dbc7fe8ca9e7 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c | |||
| @@ -21,7 +21,12 @@ | |||
| 21 | #include <linux/platform_data/tegra_usb.h> | 21 | #include <linux/platform_data/tegra_usb.h> |
| 22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
| 23 | #include <linux/usb/otg.h> | 23 | #include <linux/usb/otg.h> |
| 24 | #include <linux/gpio.h> | ||
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/of_gpio.h> | ||
| 27 | |||
| 24 | #include <mach/usb_phy.h> | 28 | #include <mach/usb_phy.h> |
| 29 | #include <mach/iomap.h> | ||
| 25 | 30 | ||
| 26 | #define TEGRA_USB_DMA_ALIGN 32 | 31 | #define TEGRA_USB_DMA_ALIGN 32 |
| 27 | 32 | ||
| @@ -574,6 +579,35 @@ static const struct hc_driver tegra_ehci_hc_driver = { | |||
| 574 | .port_handed_over = ehci_port_handed_over, | 579 | .port_handed_over = ehci_port_handed_over, |
| 575 | }; | 580 | }; |
| 576 | 581 | ||
| 582 | static int setup_vbus_gpio(struct platform_device *pdev) | ||
| 583 | { | ||
| 584 | int err = 0; | ||
| 585 | int gpio; | ||
| 586 | |||
| 587 | if (!pdev->dev.of_node) | ||
| 588 | return 0; | ||
| 589 | |||
| 590 | gpio = of_get_named_gpio(pdev->dev.of_node, "nvidia,vbus-gpio", 0); | ||
| 591 | if (!gpio_is_valid(gpio)) | ||
| 592 | return 0; | ||
| 593 | |||
| 594 | err = gpio_request(gpio, "vbus_gpio"); | ||
| 595 | if (err) { | ||
| 596 | dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); | ||
| 597 | return err; | ||
| 598 | } | ||
| 599 | err = gpio_direction_output(gpio, 1); | ||
| 600 | if (err) { | ||
| 601 | dev_err(&pdev->dev, "can't enable vbus\n"); | ||
| 602 | return err; | ||
| 603 | } | ||
| 604 | gpio_set_value(gpio, 1); | ||
| 605 | |||
| 606 | return err; | ||
| 607 | } | ||
| 608 | |||
| 609 | static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); | ||
| 610 | |||
| 577 | static int tegra_ehci_probe(struct platform_device *pdev) | 611 | static int tegra_ehci_probe(struct platform_device *pdev) |
| 578 | { | 612 | { |
| 579 | struct resource *res; | 613 | struct resource *res; |
| @@ -590,6 +624,15 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
| 590 | return -EINVAL; | 624 | return -EINVAL; |
| 591 | } | 625 | } |
| 592 | 626 | ||
| 627 | /* Right now device-tree probed devices don't get dma_mask set. | ||
| 628 | * Since shared usb code relies on it, set it here for now. | ||
| 629 | * Once we have dma capability bindings this can go away. | ||
| 630 | */ | ||
| 631 | if (!pdev->dev.dma_mask) | ||
| 632 | pdev->dev.dma_mask = &tegra_ehci_dma_mask; | ||
| 633 | |||
| 634 | setup_vbus_gpio(pdev); | ||
| 635 | |||
| 593 | tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL); | 636 | tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL); |
| 594 | if (!tegra) | 637 | if (!tegra) |
| 595 | return -ENOMEM; | 638 | return -ENOMEM; |
| @@ -640,6 +683,28 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
| 640 | goto fail_io; | 683 | goto fail_io; |
| 641 | } | 684 | } |
| 642 | 685 | ||
| 686 | /* This is pretty ugly and needs to be fixed when we do only | ||
| 687 | * device-tree probing. Old code relies on the platform_device | ||
| 688 | * numbering that we lack for device-tree-instantiated devices. | ||
| 689 | */ | ||
| 690 | if (instance < 0) { | ||
| 691 | switch (res->start) { | ||
| 692 | case TEGRA_USB_BASE: | ||
| 693 | instance = 0; | ||
| 694 | break; | ||
| 695 | case TEGRA_USB2_BASE: | ||
| 696 | instance = 1; | ||
| 697 | break; | ||
| 698 | case TEGRA_USB3_BASE: | ||
| 699 | instance = 2; | ||
| 700 | break; | ||
| 701 | default: | ||
| 702 | err = -ENODEV; | ||
| 703 | dev_err(&pdev->dev, "unknown usb instance\n"); | ||
| 704 | goto fail_phy; | ||
| 705 | } | ||
| 706 | } | ||
| 707 | |||
| 643 | tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config, | 708 | tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config, |
| 644 | TEGRA_USB_PHY_MODE_HOST); | 709 | TEGRA_USB_PHY_MODE_HOST); |
| 645 | if (IS_ERR(tegra->phy)) { | 710 | if (IS_ERR(tegra->phy)) { |
| @@ -773,6 +838,11 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev) | |||
| 773 | hcd->driver->shutdown(hcd); | 838 | hcd->driver->shutdown(hcd); |
| 774 | } | 839 | } |
| 775 | 840 | ||
| 841 | static struct of_device_id tegra_ehci_of_match[] __devinitdata = { | ||
| 842 | { .compatible = "nvidia,tegra20-ehci", }, | ||
| 843 | { }, | ||
| 844 | }; | ||
| 845 | |||
| 776 | static struct platform_driver tegra_ehci_driver = { | 846 | static struct platform_driver tegra_ehci_driver = { |
| 777 | .probe = tegra_ehci_probe, | 847 | .probe = tegra_ehci_probe, |
| 778 | .remove = tegra_ehci_remove, | 848 | .remove = tegra_ehci_remove, |
| @@ -783,5 +853,6 @@ static struct platform_driver tegra_ehci_driver = { | |||
| 783 | .shutdown = tegra_ehci_hcd_shutdown, | 853 | .shutdown = tegra_ehci_hcd_shutdown, |
| 784 | .driver = { | 854 | .driver = { |
| 785 | .name = "tegra-ehci", | 855 | .name = "tegra-ehci", |
| 856 | .of_match_table = tegra_ehci_of_match, | ||
| 786 | } | 857 | } |
| 787 | }; | 858 | }; |
