diff options
author | Olof Johansson <olof@lixom.net> | 2011-11-04 05:12:40 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2011-12-07 23:47:48 -0500 |
commit | 4a53f4e692c5df8a4bf9bf059b8007d575b0204a (patch) | |
tree | a8ed23bee2f1c0233566105c77f0d084ecfc59e9 /drivers/usb | |
parent | c27317c0ed114152d02b2ed40056f232e5732b9d (diff) |
USB: ehci-tegra: add probing through device tree
Rely on platform_data being passed through auxdata for now; more elaborate
bindings for phy config and tunings to be added.
v2: moved vbus-gpio check to the helper function, added check for !of_node,
added usb2 clock to board-dt table.
Signed-off-by: Olof Johansson <olof@lixom.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
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 | }; |