diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 18:27:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 18:27:22 -0500 |
commit | bab588fcfb6335c767d811a8955979f5440328e0 (patch) | |
tree | 2a862ddf47a82be885a8e7945a17cc3ff7a658b9 /drivers/usb/host | |
parent | 3298a3511f1e73255a8dc023efd909e569eea037 (diff) | |
parent | 9cb0d1babfcb1b4ac248c09425f7d5de1e771133 (diff) |
Merge tag 'soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC-specific updates from Arnd Bergmann:
"This is a larger set of new functionality for the existing SoC
families, including:
- vt8500 gains support for new CPU cores, notably the Cortex-A9 based
wm8850
- prima2 gains support for the "marco" SoC family, its SMP based
cousin
- tegra gains support for the new Tegra4 (Tegra114) family
- socfpga now supports a newer version of the hardware including SMP
- i.mx31 and bcm2835 are now using DT probing for their clocks
- lots of updates for sh-mobile
- OMAP updates for clocks, power management and USB
- i.mx6q and tegra now support cpuidle
- kirkwood now supports PCIe hot plugging
- tegra clock support is updated
- tegra USB PHY probing gets implemented diffently"
* tag 'soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (148 commits)
ARM: prima2: remove duplicate v7_invalidate_l1
ARM: shmobile: r8a7779: Correct TMU clock support again
ARM: prima2: fix __init section for cpu hotplug
ARM: OMAP: Consolidate OMAP USB-HS platform data (part 3/3)
ARM: OMAP: Consolidate OMAP USB-HS platform data (part 1/3)
arm: socfpga: Add SMP support for actual socfpga harware
arm: Add v7_invalidate_l1 to cache-v7.S
arm: socfpga: Add entries to enable make dtbs socfpga
arm: socfpga: Add new device tree source for actual socfpga HW
ARM: tegra: sort Kconfig selects for Tegra114
ARM: tegra: enable ARCH_REQUIRE_GPIOLIB for Tegra114
ARM: tegra: Fix build error w/ ARCH_TEGRA_114_SOC w/o ARCH_TEGRA_3x_SOC
ARM: tegra: Fix build error for gic update
ARM: tegra: remove empty tegra_smp_init_cpus()
ARM: shmobile: Register ARM architected timer
ARM: MARCO: fix the build issue due to gic-vic-to-irqchip move
ARM: shmobile: r8a7779: Correct TMU clock support
ARM: mxs_defconfig: Select CONFIG_DEVTMPFS_MOUNT
ARM: mxs: decrease mxs_clockevent_device.min_delta_ns to 2 clock cycles
ARM: mxs: use apbx bus clock to drive the timers on timrotv2
...
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 97 |
1 files changed, 65 insertions, 32 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index acf17556bd87..568aecc7075b 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs | 2 | * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright (C) 2010 Google, Inc. |
5 | * Copyright (C) 2009 NVIDIA Corporation | 5 | * Copyright (C) 2009 - 2013 NVIDIA Corporation |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
@@ -26,23 +26,28 @@ | |||
26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
27 | #include <linux/of_gpio.h> | 27 | #include <linux/of_gpio.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | 29 | #include <linux/usb/ehci_def.h> | |
30 | #include <linux/usb/tegra_usb_phy.h> | 30 | #include <linux/usb/tegra_usb_phy.h> |
31 | 31 | ||
32 | #define TEGRA_USB_BASE 0xC5000000 | 32 | #define TEGRA_USB_BASE 0xC5000000 |
33 | #define TEGRA_USB2_BASE 0xC5004000 | 33 | #define TEGRA_USB2_BASE 0xC5004000 |
34 | #define TEGRA_USB3_BASE 0xC5008000 | 34 | #define TEGRA_USB3_BASE 0xC5008000 |
35 | 35 | ||
36 | /* PORTSC registers */ | ||
37 | #define TEGRA_USB_PORTSC1 0x184 | ||
38 | #define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) | ||
39 | #define TEGRA_USB_PORTSC1_PHCD (1 << 23) | ||
40 | |||
36 | #define TEGRA_USB_DMA_ALIGN 32 | 41 | #define TEGRA_USB_DMA_ALIGN 32 |
37 | 42 | ||
38 | struct tegra_ehci_hcd { | 43 | struct tegra_ehci_hcd { |
39 | struct ehci_hcd *ehci; | 44 | struct ehci_hcd *ehci; |
40 | struct tegra_usb_phy *phy; | 45 | struct tegra_usb_phy *phy; |
41 | struct clk *clk; | 46 | struct clk *clk; |
42 | struct clk *emc_clk; | ||
43 | struct usb_phy *transceiver; | 47 | struct usb_phy *transceiver; |
44 | int host_resumed; | 48 | int host_resumed; |
45 | int port_resuming; | 49 | int port_resuming; |
50 | bool needs_double_reset; | ||
46 | enum tegra_usb_phy_port_speed port_speed; | 51 | enum tegra_usb_phy_port_speed port_speed; |
47 | }; | 52 | }; |
48 | 53 | ||
@@ -50,9 +55,8 @@ static void tegra_ehci_power_up(struct usb_hcd *hcd) | |||
50 | { | 55 | { |
51 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 56 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); |
52 | 57 | ||
53 | clk_prepare_enable(tegra->emc_clk); | ||
54 | clk_prepare_enable(tegra->clk); | 58 | clk_prepare_enable(tegra->clk); |
55 | usb_phy_set_suspend(&tegra->phy->u_phy, 0); | 59 | usb_phy_set_suspend(hcd->phy, 0); |
56 | tegra->host_resumed = 1; | 60 | tegra->host_resumed = 1; |
57 | } | 61 | } |
58 | 62 | ||
@@ -61,9 +65,8 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd) | |||
61 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 65 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); |
62 | 66 | ||
63 | tegra->host_resumed = 0; | 67 | tegra->host_resumed = 0; |
64 | usb_phy_set_suspend(&tegra->phy->u_phy, 1); | 68 | usb_phy_set_suspend(hcd->phy, 1); |
65 | clk_disable_unprepare(tegra->clk); | 69 | clk_disable_unprepare(tegra->clk); |
66 | clk_disable_unprepare(tegra->emc_clk); | ||
67 | } | 70 | } |
68 | 71 | ||
69 | static int tegra_ehci_internal_port_reset( | 72 | static int tegra_ehci_internal_port_reset( |
@@ -156,7 +159,7 @@ static int tegra_ehci_hub_control( | |||
156 | if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { | 159 | if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { |
157 | /* Resume completed, re-enable disconnect detection */ | 160 | /* Resume completed, re-enable disconnect detection */ |
158 | tegra->port_resuming = 0; | 161 | tegra->port_resuming = 0; |
159 | tegra_usb_phy_postresume(tegra->phy); | 162 | tegra_usb_phy_postresume(hcd->phy); |
160 | } | 163 | } |
161 | } | 164 | } |
162 | 165 | ||
@@ -184,7 +187,7 @@ static int tegra_ehci_hub_control( | |||
184 | } | 187 | } |
185 | 188 | ||
186 | /* For USB1 port we need to issue Port Reset twice internally */ | 189 | /* For USB1 port we need to issue Port Reset twice internally */ |
187 | if (tegra->phy->instance == 0 && | 190 | if (tegra->needs_double_reset && |
188 | (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { | 191 | (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { |
189 | spin_unlock_irqrestore(&ehci->lock, flags); | 192 | spin_unlock_irqrestore(&ehci->lock, flags); |
190 | return tegra_ehci_internal_port_reset(ehci, status_reg); | 193 | return tegra_ehci_internal_port_reset(ehci, status_reg); |
@@ -209,7 +212,7 @@ static int tegra_ehci_hub_control( | |||
209 | goto done; | 212 | goto done; |
210 | 213 | ||
211 | /* Disable disconnect detection during port resume */ | 214 | /* Disable disconnect detection during port resume */ |
212 | tegra_usb_phy_preresume(tegra->phy); | 215 | tegra_usb_phy_preresume(hcd->phy); |
213 | 216 | ||
214 | ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); | 217 | ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); |
215 | 218 | ||
@@ -473,7 +476,7 @@ static int controller_resume(struct device *dev) | |||
473 | } | 476 | } |
474 | 477 | ||
475 | /* Force the phy to keep data lines in suspend state */ | 478 | /* Force the phy to keep data lines in suspend state */ |
476 | tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); | 479 | tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed); |
477 | 480 | ||
478 | /* Enable host mode */ | 481 | /* Enable host mode */ |
479 | tdi_reset(ehci); | 482 | tdi_reset(ehci); |
@@ -540,17 +543,17 @@ static int controller_resume(struct device *dev) | |||
540 | } | 543 | } |
541 | } | 544 | } |
542 | 545 | ||
543 | tegra_ehci_phy_restore_end(tegra->phy); | 546 | tegra_ehci_phy_restore_end(hcd->phy); |
544 | goto done; | 547 | goto done; |
545 | 548 | ||
546 | restart: | 549 | restart: |
547 | if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) | 550 | if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) |
548 | tegra_ehci_phy_restore_end(tegra->phy); | 551 | tegra_ehci_phy_restore_end(hcd->phy); |
549 | 552 | ||
550 | tegra_ehci_restart(hcd); | 553 | tegra_ehci_restart(hcd); |
551 | 554 | ||
552 | done: | 555 | done: |
553 | tegra_usb_phy_preresume(tegra->phy); | 556 | tegra_usb_phy_preresume(hcd->phy); |
554 | tegra->port_resuming = 1; | 557 | tegra->port_resuming = 1; |
555 | return 0; | 558 | return 0; |
556 | } | 559 | } |
@@ -604,6 +607,37 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = { | |||
604 | 607 | ||
605 | #endif | 608 | #endif |
606 | 609 | ||
610 | /* Bits of PORTSC1, which will get cleared by writing 1 into them */ | ||
611 | #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
612 | |||
613 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) | ||
614 | { | ||
615 | unsigned long val; | ||
616 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | ||
617 | void __iomem *base = hcd->regs; | ||
618 | |||
619 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | ||
620 | val &= ~TEGRA_USB_PORTSC1_PTS(3); | ||
621 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); | ||
622 | writel(val, base + TEGRA_USB_PORTSC1); | ||
623 | } | ||
624 | EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); | ||
625 | |||
626 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) | ||
627 | { | ||
628 | unsigned long val; | ||
629 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | ||
630 | void __iomem *base = hcd->regs; | ||
631 | |||
632 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | ||
633 | if (enable) | ||
634 | val |= TEGRA_USB_PORTSC1_PHCD; | ||
635 | else | ||
636 | val &= ~TEGRA_USB_PORTSC1_PHCD; | ||
637 | writel(val, base + TEGRA_USB_PORTSC1); | ||
638 | } | ||
639 | EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); | ||
640 | |||
607 | static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); | 641 | static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); |
608 | 642 | ||
609 | static int tegra_ehci_probe(struct platform_device *pdev) | 643 | static int tegra_ehci_probe(struct platform_device *pdev) |
@@ -615,6 +649,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
615 | int err = 0; | 649 | int err = 0; |
616 | int irq; | 650 | int irq; |
617 | int instance = pdev->id; | 651 | int instance = pdev->id; |
652 | struct usb_phy *u_phy; | ||
618 | 653 | ||
619 | pdata = pdev->dev.platform_data; | 654 | pdata = pdev->dev.platform_data; |
620 | if (!pdata) { | 655 | if (!pdata) { |
@@ -656,15 +691,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
656 | if (err) | 691 | if (err) |
657 | goto fail_clk; | 692 | goto fail_clk; |
658 | 693 | ||
659 | tegra->emc_clk = devm_clk_get(&pdev->dev, "emc"); | 694 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, |
660 | if (IS_ERR(tegra->emc_clk)) { | 695 | "nvidia,needs-double-reset"); |
661 | dev_err(&pdev->dev, "Can't get emc clock\n"); | ||
662 | err = PTR_ERR(tegra->emc_clk); | ||
663 | goto fail_emc_clk; | ||
664 | } | ||
665 | |||
666 | clk_prepare_enable(tegra->emc_clk); | ||
667 | clk_set_rate(tegra->emc_clk, 400000000); | ||
668 | 696 | ||
669 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 697 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
670 | if (!res) { | 698 | if (!res) { |
@@ -712,9 +740,19 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
712 | goto fail_io; | 740 | goto fail_io; |
713 | } | 741 | } |
714 | 742 | ||
715 | usb_phy_init(&tegra->phy->u_phy); | 743 | hcd->phy = u_phy = &tegra->phy->u_phy; |
744 | usb_phy_init(hcd->phy); | ||
745 | |||
746 | u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), | ||
747 | GFP_KERNEL); | ||
748 | if (!u_phy->otg) { | ||
749 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); | ||
750 | err = -ENOMEM; | ||
751 | goto fail_io; | ||
752 | } | ||
753 | u_phy->otg->host = hcd_to_bus(hcd); | ||
716 | 754 | ||
717 | err = usb_phy_set_suspend(&tegra->phy->u_phy, 0); | 755 | err = usb_phy_set_suspend(hcd->phy, 0); |
718 | if (err) { | 756 | if (err) { |
719 | dev_err(&pdev->dev, "Failed to power on the phy\n"); | 757 | dev_err(&pdev->dev, "Failed to power on the phy\n"); |
720 | goto fail; | 758 | goto fail; |
@@ -760,10 +798,8 @@ fail: | |||
760 | if (!IS_ERR_OR_NULL(tegra->transceiver)) | 798 | if (!IS_ERR_OR_NULL(tegra->transceiver)) |
761 | otg_set_host(tegra->transceiver->otg, NULL); | 799 | otg_set_host(tegra->transceiver->otg, NULL); |
762 | #endif | 800 | #endif |
763 | usb_phy_shutdown(&tegra->phy->u_phy); | 801 | usb_phy_shutdown(hcd->phy); |
764 | fail_io: | 802 | fail_io: |
765 | clk_disable_unprepare(tegra->emc_clk); | ||
766 | fail_emc_clk: | ||
767 | clk_disable_unprepare(tegra->clk); | 803 | clk_disable_unprepare(tegra->clk); |
768 | fail_clk: | 804 | fail_clk: |
769 | usb_put_hcd(hcd); | 805 | usb_put_hcd(hcd); |
@@ -784,15 +820,12 @@ static int tegra_ehci_remove(struct platform_device *pdev) | |||
784 | otg_set_host(tegra->transceiver->otg, NULL); | 820 | otg_set_host(tegra->transceiver->otg, NULL); |
785 | #endif | 821 | #endif |
786 | 822 | ||
823 | usb_phy_shutdown(hcd->phy); | ||
787 | usb_remove_hcd(hcd); | 824 | usb_remove_hcd(hcd); |
788 | usb_put_hcd(hcd); | 825 | usb_put_hcd(hcd); |
789 | 826 | ||
790 | usb_phy_shutdown(&tegra->phy->u_phy); | ||
791 | |||
792 | clk_disable_unprepare(tegra->clk); | 827 | clk_disable_unprepare(tegra->clk); |
793 | 828 | ||
794 | clk_disable_unprepare(tegra->emc_clk); | ||
795 | |||
796 | return 0; | 829 | return 0; |
797 | } | 830 | } |
798 | 831 | ||