aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-02-05 15:45:39 -0500
committerOlof Johansson <olof@lixom.net>2013-02-05 15:45:39 -0500
commitceca718f21270dcd7cdf7e124f15b35cb68eca13 (patch)
treeaeb6503eafe39032d624ebf30368d414196afbaa /drivers/usb
parentbda6f8e6cdcdb55db9b2961b6a7c9d0d97da4765 (diff)
parentab137d04db5a4b32250ce5ef1b288ce6cf06adf6 (diff)
Merge tag 'tegra-for-3.9-soc-usb' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/soc
From Stephen Warren: ARM: tegra: USB driver cleanup The Tegra USB driver has a number of issues: 1) The PHY driver isn't a true platform device, and doesn't implement the standard USB PHY API. 2) struct device instance numbers were used to make decisions in the driver, rather than being parameterized by DT or platform data. This pull request solves issue (2), and lays the groundwork for solving issue (1). The work on issue (1) involved introducing new DT nodes for the USB PHYs, which in turn interacted with the Tegra common clock framework changes, due to the move of clock lookups into device tree. Hence, these USB driver changes are taken through the Tegra tree with acks from USB maintainers. This pull request is based on the previous pull request, with tag tegra-for-3.9-soc-ccf. * tag 'tegra-for-3.9-soc-usb' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra: usb: host: tegra: make use of PHY pointer of HCD ARM: tegra: Add reset GPIO information to PHY DT node usb: host: tegra: don't touch EMC clock usb: add APIs to access host registers from Tegra PHY USB: PHY: tegra: Get rid of instance number to differentiate PHY type USB: PHY: tegra: get rid of instance number to differentiate legacy controller ARM: tegra: add clocks properties to USB PHY nodes ARM: tegra: add DT nodes for Tegra USB PHY usb: phy: remove unused APIs from Tegra PHY. usb: host: tegra: Resetting PORT0 based on information received via DT. ARM: tegra: Add new DT property to USB node. usb: phy: use kzalloc to allocate struct tegra_usb_phy ARM: tegra: remove USB address related macros from iomap.h
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-tegra.c97
-rw-r--r--drivers/usb/phy/tegra_usb_phy.c132
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
38struct tegra_ehci_hcd { 43struct 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
69static int tegra_ehci_internal_port_reset( 72static 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
613void 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}
624EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);
625
626void 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}
639EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);
640
607static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); 641static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
608 642
609static int tegra_ehci_probe(struct platform_device *pdev) 643static 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);
764fail_io: 802fail_io:
765 clk_disable_unprepare(tegra->emc_clk);
766fail_emc_clk:
767 clk_disable_unprepare(tegra->clk); 803 clk_disable_unprepare(tegra->clk);
768fail_clk: 804fail_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
211static inline bool phy_is_ulpi(struct tegra_usb_phy *phy)
212{
213 return (phy->instance == 1);
214}
215
216static int utmip_pad_open(struct tegra_usb_phy *phy) 199static 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
237static void utmip_pad_close(struct tegra_usb_phy *phy) 220static 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
640static int ulpi_phy_power_off(struct tegra_usb_phy *phy) 604static 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
710static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) 665static 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
718static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) 673static 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}
797EXPORT_SYMBOL_GPL(tegra_usb_phy_open); 760EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
798 761
799void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) 762void 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}
804EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); 769EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
805 770
806void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) 771void 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}
811EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); 778EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
812 779
813void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, 780void 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}
819EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); 788EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
820 789
821void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) 790void 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}
826EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); 797EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
827 798
828void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
829{
830 if (!phy_is_ulpi(phy))
831 utmi_phy_clk_disable(phy);
832}
833EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable);
834
835void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
836{
837 if (!phy_is_ulpi(phy))
838 utmi_phy_clk_enable(phy);
839}
840EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable);