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 | |
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')
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 97 | ||||
-rw-r--r-- | drivers/usb/phy/tegra_usb_phy.c | 132 |
2 files changed, 110 insertions, 119 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 | ||
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c index 9d13c81754e0..5487d38481af 100644 --- a/drivers/usb/phy/tegra_usb_phy.c +++ b/drivers/usb/phy/tegra_usb_phy.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
27 | #include <linux/of.h> | ||
27 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
28 | #include <linux/usb/otg.h> | 29 | #include <linux/usb/otg.h> |
29 | #include <linux/usb/ulpi.h> | 30 | #include <linux/usb/ulpi.h> |
@@ -35,19 +36,6 @@ | |||
35 | 36 | ||
36 | #define ULPI_VIEWPORT 0x170 | 37 | #define ULPI_VIEWPORT 0x170 |
37 | 38 | ||
38 | #define USB_PORTSC1 0x184 | ||
39 | #define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) | ||
40 | #define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26) | ||
41 | #define USB_PORTSC1_PHCD (1 << 23) | ||
42 | #define USB_PORTSC1_WKOC (1 << 22) | ||
43 | #define USB_PORTSC1_WKDS (1 << 21) | ||
44 | #define USB_PORTSC1_WKCN (1 << 20) | ||
45 | #define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) | ||
46 | #define USB_PORTSC1_PP (1 << 12) | ||
47 | #define USB_PORTSC1_SUSP (1 << 7) | ||
48 | #define USB_PORTSC1_PE (1 << 2) | ||
49 | #define USB_PORTSC1_CCS (1 << 0) | ||
50 | |||
51 | #define USB_SUSP_CTRL 0x400 | 39 | #define USB_SUSP_CTRL 0x400 |
52 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) | 40 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) |
53 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) | 41 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) |
@@ -208,11 +196,6 @@ static struct tegra_utmip_config utmip_default[] = { | |||
208 | }, | 196 | }, |
209 | }; | 197 | }; |
210 | 198 | ||
211 | static inline bool phy_is_ulpi(struct tegra_usb_phy *phy) | ||
212 | { | ||
213 | return (phy->instance == 1); | ||
214 | } | ||
215 | |||
216 | static int utmip_pad_open(struct tegra_usb_phy *phy) | 199 | static int utmip_pad_open(struct tegra_usb_phy *phy) |
217 | { | 200 | { |
218 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); | 201 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); |
@@ -221,7 +204,7 @@ static int utmip_pad_open(struct tegra_usb_phy *phy) | |||
221 | return PTR_ERR(phy->pad_clk); | 204 | return PTR_ERR(phy->pad_clk); |
222 | } | 205 | } |
223 | 206 | ||
224 | if (phy->instance == 0) { | 207 | if (phy->is_legacy_phy) { |
225 | phy->pad_regs = phy->regs; | 208 | phy->pad_regs = phy->regs; |
226 | } else { | 209 | } else { |
227 | phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); | 210 | phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); |
@@ -236,7 +219,7 @@ static int utmip_pad_open(struct tegra_usb_phy *phy) | |||
236 | 219 | ||
237 | static void utmip_pad_close(struct tegra_usb_phy *phy) | 220 | static void utmip_pad_close(struct tegra_usb_phy *phy) |
238 | { | 221 | { |
239 | if (phy->instance != 0) | 222 | if (!phy->is_legacy_phy) |
240 | iounmap(phy->pad_regs); | 223 | iounmap(phy->pad_regs); |
241 | clk_put(phy->pad_clk); | 224 | clk_put(phy->pad_clk); |
242 | } | 225 | } |
@@ -305,7 +288,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | |||
305 | unsigned long val; | 288 | unsigned long val; |
306 | void __iomem *base = phy->regs; | 289 | void __iomem *base = phy->regs; |
307 | 290 | ||
308 | if (phy->instance == 0) { | 291 | if (phy->is_legacy_phy) { |
309 | val = readl(base + USB_SUSP_CTRL); | 292 | val = readl(base + USB_SUSP_CTRL); |
310 | val |= USB_SUSP_SET; | 293 | val |= USB_SUSP_SET; |
311 | writel(val, base + USB_SUSP_CTRL); | 294 | writel(val, base + USB_SUSP_CTRL); |
@@ -315,13 +298,8 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | |||
315 | val = readl(base + USB_SUSP_CTRL); | 298 | val = readl(base + USB_SUSP_CTRL); |
316 | val &= ~USB_SUSP_SET; | 299 | val &= ~USB_SUSP_SET; |
317 | writel(val, base + USB_SUSP_CTRL); | 300 | writel(val, base + USB_SUSP_CTRL); |
318 | } | 301 | } else |
319 | 302 | tegra_ehci_set_phcd(&phy->u_phy, true); | |
320 | if (phy->instance == 2) { | ||
321 | val = readl(base + USB_PORTSC1); | ||
322 | val |= USB_PORTSC1_PHCD; | ||
323 | writel(val, base + USB_PORTSC1); | ||
324 | } | ||
325 | 303 | ||
326 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) | 304 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) |
327 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | 305 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); |
@@ -332,7 +310,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | |||
332 | unsigned long val; | 310 | unsigned long val; |
333 | void __iomem *base = phy->regs; | 311 | void __iomem *base = phy->regs; |
334 | 312 | ||
335 | if (phy->instance == 0) { | 313 | if (phy->is_legacy_phy) { |
336 | val = readl(base + USB_SUSP_CTRL); | 314 | val = readl(base + USB_SUSP_CTRL); |
337 | val |= USB_SUSP_CLR; | 315 | val |= USB_SUSP_CLR; |
338 | writel(val, base + USB_SUSP_CTRL); | 316 | writel(val, base + USB_SUSP_CTRL); |
@@ -342,13 +320,8 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | |||
342 | val = readl(base + USB_SUSP_CTRL); | 320 | val = readl(base + USB_SUSP_CTRL); |
343 | val &= ~USB_SUSP_CLR; | 321 | val &= ~USB_SUSP_CLR; |
344 | writel(val, base + USB_SUSP_CTRL); | 322 | writel(val, base + USB_SUSP_CTRL); |
345 | } | 323 | } else |
346 | 324 | tegra_ehci_set_phcd(&phy->u_phy, false); | |
347 | if (phy->instance == 2) { | ||
348 | val = readl(base + USB_PORTSC1); | ||
349 | val &= ~USB_PORTSC1_PHCD; | ||
350 | writel(val, base + USB_PORTSC1); | ||
351 | } | ||
352 | 325 | ||
353 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, | 326 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, |
354 | USB_PHY_CLK_VALID)) | 327 | USB_PHY_CLK_VALID)) |
@@ -365,7 +338,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) | |||
365 | val |= UTMIP_RESET; | 338 | val |= UTMIP_RESET; |
366 | writel(val, base + USB_SUSP_CTRL); | 339 | writel(val, base + USB_SUSP_CTRL); |
367 | 340 | ||
368 | if (phy->instance == 0) { | 341 | if (phy->is_legacy_phy) { |
369 | val = readl(base + USB1_LEGACY_CTRL); | 342 | val = readl(base + USB1_LEGACY_CTRL); |
370 | val |= USB1_NO_LEGACY_MODE; | 343 | val |= USB1_NO_LEGACY_MODE; |
371 | writel(val, base + USB1_LEGACY_CTRL); | 344 | writel(val, base + USB1_LEGACY_CTRL); |
@@ -440,16 +413,14 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) | |||
440 | val |= UTMIP_BIAS_PDTRK_COUNT(0x5); | 413 | val |= UTMIP_BIAS_PDTRK_COUNT(0x5); |
441 | writel(val, base + UTMIP_BIAS_CFG1); | 414 | writel(val, base + UTMIP_BIAS_CFG1); |
442 | 415 | ||
443 | if (phy->instance == 0) { | 416 | if (phy->is_legacy_phy) { |
444 | val = readl(base + UTMIP_SPARE_CFG0); | 417 | val = readl(base + UTMIP_SPARE_CFG0); |
445 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) | 418 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) |
446 | val &= ~FUSE_SETUP_SEL; | 419 | val &= ~FUSE_SETUP_SEL; |
447 | else | 420 | else |
448 | val |= FUSE_SETUP_SEL; | 421 | val |= FUSE_SETUP_SEL; |
449 | writel(val, base + UTMIP_SPARE_CFG0); | 422 | writel(val, base + UTMIP_SPARE_CFG0); |
450 | } | 423 | } else { |
451 | |||
452 | if (phy->instance == 2) { | ||
453 | val = readl(base + USB_SUSP_CTRL); | 424 | val = readl(base + USB_SUSP_CTRL); |
454 | val |= UTMIP_PHY_ENABLE; | 425 | val |= UTMIP_PHY_ENABLE; |
455 | writel(val, base + USB_SUSP_CTRL); | 426 | writel(val, base + USB_SUSP_CTRL); |
@@ -459,7 +430,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) | |||
459 | val &= ~UTMIP_RESET; | 430 | val &= ~UTMIP_RESET; |
460 | writel(val, base + USB_SUSP_CTRL); | 431 | writel(val, base + USB_SUSP_CTRL); |
461 | 432 | ||
462 | if (phy->instance == 0) { | 433 | if (phy->is_legacy_phy) { |
463 | val = readl(base + USB1_LEGACY_CTRL); | 434 | val = readl(base + USB1_LEGACY_CTRL); |
464 | val &= ~USB1_VBUS_SENSE_CTL_MASK; | 435 | val &= ~USB1_VBUS_SENSE_CTL_MASK; |
465 | val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; | 436 | val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; |
@@ -472,11 +443,8 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) | |||
472 | 443 | ||
473 | utmi_phy_clk_enable(phy); | 444 | utmi_phy_clk_enable(phy); |
474 | 445 | ||
475 | if (phy->instance == 2) { | 446 | if (!phy->is_legacy_phy) |
476 | val = readl(base + USB_PORTSC1); | 447 | tegra_ehci_set_pts(&phy->u_phy, 0); |
477 | val &= ~USB_PORTSC1_PTS(~0); | ||
478 | writel(val, base + USB_PORTSC1); | ||
479 | } | ||
480 | 448 | ||
481 | return 0; | 449 | return 0; |
482 | } | 450 | } |
@@ -621,10 +589,6 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
621 | return ret; | 589 | return ret; |
622 | } | 590 | } |
623 | 591 | ||
624 | val = readl(base + USB_PORTSC1); | ||
625 | val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; | ||
626 | writel(val, base + USB_PORTSC1); | ||
627 | |||
628 | val = readl(base + USB_SUSP_CTRL); | 592 | val = readl(base + USB_SUSP_CTRL); |
629 | val |= USB_SUSP_CLR; | 593 | val |= USB_SUSP_CLR; |
630 | writel(val, base + USB_SUSP_CTRL); | 594 | writel(val, base + USB_SUSP_CTRL); |
@@ -639,17 +603,8 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
639 | 603 | ||
640 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) | 604 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) |
641 | { | 605 | { |
642 | unsigned long val; | ||
643 | void __iomem *base = phy->regs; | ||
644 | struct tegra_ulpi_config *config = phy->config; | 606 | struct tegra_ulpi_config *config = phy->config; |
645 | 607 | ||
646 | /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB | ||
647 | * Controller to immediately bring the ULPI PHY out of low power | ||
648 | */ | ||
649 | val = readl(base + USB_PORTSC1); | ||
650 | val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN); | ||
651 | writel(val, base + USB_PORTSC1); | ||
652 | |||
653 | clk_disable(phy->clk); | 608 | clk_disable(phy->clk); |
654 | return gpio_direction_output(config->reset_gpio, 0); | 609 | return gpio_direction_output(config->reset_gpio, 0); |
655 | } | 610 | } |
@@ -660,7 +615,7 @@ static int tegra_phy_init(struct usb_phy *x) | |||
660 | struct tegra_ulpi_config *ulpi_config; | 615 | struct tegra_ulpi_config *ulpi_config; |
661 | int err; | 616 | int err; |
662 | 617 | ||
663 | if (phy_is_ulpi(phy)) { | 618 | if (phy->is_ulpi_phy) { |
664 | ulpi_config = phy->config; | 619 | ulpi_config = phy->config; |
665 | phy->clk = clk_get_sys(NULL, ulpi_config->clk); | 620 | phy->clk = clk_get_sys(NULL, ulpi_config->clk); |
666 | if (IS_ERR(phy->clk)) { | 621 | if (IS_ERR(phy->clk)) { |
@@ -698,7 +653,7 @@ static void tegra_usb_phy_close(struct usb_phy *x) | |||
698 | { | 653 | { |
699 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | 654 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
700 | 655 | ||
701 | if (phy_is_ulpi(phy)) | 656 | if (phy->is_ulpi_phy) |
702 | clk_put(phy->clk); | 657 | clk_put(phy->clk); |
703 | else | 658 | else |
704 | utmip_pad_close(phy); | 659 | utmip_pad_close(phy); |
@@ -709,7 +664,7 @@ static void tegra_usb_phy_close(struct usb_phy *x) | |||
709 | 664 | ||
710 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) | 665 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) |
711 | { | 666 | { |
712 | if (phy_is_ulpi(phy)) | 667 | if (phy->is_ulpi_phy) |
713 | return ulpi_phy_power_on(phy); | 668 | return ulpi_phy_power_on(phy); |
714 | else | 669 | else |
715 | return utmi_phy_power_on(phy); | 670 | return utmi_phy_power_on(phy); |
@@ -717,7 +672,7 @@ static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) | |||
717 | 672 | ||
718 | static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) | 673 | static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) |
719 | { | 674 | { |
720 | if (phy_is_ulpi(phy)) | 675 | if (phy->is_ulpi_phy) |
721 | return ulpi_phy_power_off(phy); | 676 | return ulpi_phy_power_off(phy); |
722 | else | 677 | else |
723 | return utmi_phy_power_off(phy); | 678 | return utmi_phy_power_off(phy); |
@@ -739,8 +694,9 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | |||
739 | unsigned long parent_rate; | 694 | unsigned long parent_rate; |
740 | int i; | 695 | int i; |
741 | int err; | 696 | int err; |
697 | struct device_node *np = dev->of_node; | ||
742 | 698 | ||
743 | phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); | 699 | phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); |
744 | if (!phy) | 700 | if (!phy) |
745 | return ERR_PTR(-ENOMEM); | 701 | return ERR_PTR(-ENOMEM); |
746 | 702 | ||
@@ -749,9 +705,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | |||
749 | phy->config = config; | 705 | phy->config = config; |
750 | phy->mode = phy_mode; | 706 | phy->mode = phy_mode; |
751 | phy->dev = dev; | 707 | phy->dev = dev; |
708 | phy->is_legacy_phy = | ||
709 | of_property_read_bool(np, "nvidia,has-legacy-mode"); | ||
710 | err = of_property_match_string(np, "phy_type", "ulpi"); | ||
711 | if (err < 0) | ||
712 | phy->is_ulpi_phy = false; | ||
713 | else | ||
714 | phy->is_ulpi_phy = true; | ||
752 | 715 | ||
753 | if (!phy->config) { | 716 | if (!phy->config) { |
754 | if (phy_is_ulpi(phy)) { | 717 | if (phy->is_ulpi_phy) { |
755 | pr_err("%s: ulpi phy configuration missing", __func__); | 718 | pr_err("%s: ulpi phy configuration missing", __func__); |
756 | err = -EINVAL; | 719 | err = -EINVAL; |
757 | goto err0; | 720 | goto err0; |
@@ -796,45 +759,40 @@ err0: | |||
796 | } | 759 | } |
797 | EXPORT_SYMBOL_GPL(tegra_usb_phy_open); | 760 | EXPORT_SYMBOL_GPL(tegra_usb_phy_open); |
798 | 761 | ||
799 | void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) | 762 | void tegra_usb_phy_preresume(struct usb_phy *x) |
800 | { | 763 | { |
801 | if (!phy_is_ulpi(phy)) | 764 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
765 | |||
766 | if (!phy->is_ulpi_phy) | ||
802 | utmi_phy_preresume(phy); | 767 | utmi_phy_preresume(phy); |
803 | } | 768 | } |
804 | EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); | 769 | EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); |
805 | 770 | ||
806 | void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) | 771 | void tegra_usb_phy_postresume(struct usb_phy *x) |
807 | { | 772 | { |
808 | if (!phy_is_ulpi(phy)) | 773 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
774 | |||
775 | if (!phy->is_ulpi_phy) | ||
809 | utmi_phy_postresume(phy); | 776 | utmi_phy_postresume(phy); |
810 | } | 777 | } |
811 | EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); | 778 | EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); |
812 | 779 | ||
813 | void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, | 780 | void tegra_ehci_phy_restore_start(struct usb_phy *x, |
814 | enum tegra_usb_phy_port_speed port_speed) | 781 | enum tegra_usb_phy_port_speed port_speed) |
815 | { | 782 | { |
816 | if (!phy_is_ulpi(phy)) | 783 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
784 | |||
785 | if (!phy->is_ulpi_phy) | ||
817 | utmi_phy_restore_start(phy, port_speed); | 786 | utmi_phy_restore_start(phy, port_speed); |
818 | } | 787 | } |
819 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); | 788 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); |
820 | 789 | ||
821 | void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) | 790 | void tegra_ehci_phy_restore_end(struct usb_phy *x) |
822 | { | 791 | { |
823 | if (!phy_is_ulpi(phy)) | 792 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
793 | |||
794 | if (!phy->is_ulpi_phy) | ||
824 | utmi_phy_restore_end(phy); | 795 | utmi_phy_restore_end(phy); |
825 | } | 796 | } |
826 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); | 797 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); |
827 | 798 | ||
828 | void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy) | ||
829 | { | ||
830 | if (!phy_is_ulpi(phy)) | ||
831 | utmi_phy_clk_disable(phy); | ||
832 | } | ||
833 | EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable); | ||
834 | |||
835 | void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy) | ||
836 | { | ||
837 | if (!phy_is_ulpi(phy)) | ||
838 | utmi_phy_clk_enable(phy); | ||
839 | } | ||
840 | EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable); | ||