aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-tegra.c
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/host/ehci-tegra.c
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/host/ehci-tegra.c')
-rw-r--r--drivers/usb/host/ehci-tegra.c97
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
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