aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenu Byravarasu <vbyravarasu@nvidia.com>2013-01-17 15:15:37 -0500
committerStephen Warren <swarren@nvidia.com>2013-01-28 13:20:05 -0500
commitbbdabdb62d86090511410728644a19291bf300cf (patch)
tree4ad3a6fa47c2368be8a84feefec222f78951ede1
parent3f9db1a19a8a17f6000973194c6a1d63c5cebf21 (diff)
usb: add APIs to access host registers from Tegra PHY
As Tegra PHY driver needs to access one of the host registers, added few APIs. Signed-off-by: Venu Byravarasu <vbyravarasu@nvidia.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> [swarren: moved assignment of phy->is_ulpi_phy to previous patch.] Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--drivers/usb/host/ehci-tegra.c51
-rw-r--r--drivers/usb/phy/tegra_usb_phy.c47
-rw-r--r--include/linux/usb/tegra_usb_phy.h4
3 files changed, 59 insertions, 43 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 55a9cdee2949..1f596fb7cf71 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,13 +26,18 @@
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 {
@@ -605,6 +610,37 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {
605 610
606#endif 611#endif
607 612
613/* Bits of PORTSC1, which will get cleared by writing 1 into them */
614#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
615
616void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
617{
618 unsigned long val;
619 struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
620 void __iomem *base = hcd->regs;
621
622 val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
623 val &= ~TEGRA_USB_PORTSC1_PTS(3);
624 val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
625 writel(val, base + TEGRA_USB_PORTSC1);
626}
627EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);
628
629void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
630{
631 unsigned long val;
632 struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
633 void __iomem *base = hcd->regs;
634
635 val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
636 if (enable)
637 val |= TEGRA_USB_PORTSC1_PHCD;
638 else
639 val &= ~TEGRA_USB_PORTSC1_PHCD;
640 writel(val, base + TEGRA_USB_PORTSC1);
641}
642EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);
643
608static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); 644static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
609 645
610static int tegra_ehci_probe(struct platform_device *pdev) 646static int tegra_ehci_probe(struct platform_device *pdev)
@@ -616,6 +652,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
616 int err = 0; 652 int err = 0;
617 int irq; 653 int irq;
618 int instance = pdev->id; 654 int instance = pdev->id;
655 struct usb_phy *u_phy;
619 656
620 pdata = pdev->dev.platform_data; 657 pdata = pdev->dev.platform_data;
621 if (!pdata) { 658 if (!pdata) {
@@ -718,6 +755,16 @@ static int tegra_ehci_probe(struct platform_device *pdev)
718 755
719 usb_phy_init(&tegra->phy->u_phy); 756 usb_phy_init(&tegra->phy->u_phy);
720 757
758 hcd->phy = u_phy = &tegra->phy->u_phy;
759 u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
760 GFP_KERNEL);
761 if (!u_phy->otg) {
762 dev_err(&pdev->dev, "Failed to alloc memory for otg\n");
763 err = -ENOMEM;
764 goto fail_io;
765 }
766 u_phy->otg->host = hcd_to_bus(hcd);
767
721 err = usb_phy_set_suspend(&tegra->phy->u_phy, 0); 768 err = usb_phy_set_suspend(&tegra->phy->u_phy, 0);
722 if (err) { 769 if (err) {
723 dev_err(&pdev->dev, "Failed to power on the phy\n"); 770 dev_err(&pdev->dev, "Failed to power on the phy\n");
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
index 48fa5258ce0b..d4657045b8b1 100644
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ b/drivers/usb/phy/tegra_usb_phy.c
@@ -36,19 +36,6 @@
36 36
37#define ULPI_VIEWPORT 0x170 37#define ULPI_VIEWPORT 0x170
38 38
39#define USB_PORTSC1 0x184
40#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
41#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26)
42#define USB_PORTSC1_PHCD (1 << 23)
43#define USB_PORTSC1_WKOC (1 << 22)
44#define USB_PORTSC1_WKDS (1 << 21)
45#define USB_PORTSC1_WKCN (1 << 20)
46#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16)
47#define USB_PORTSC1_PP (1 << 12)
48#define USB_PORTSC1_SUSP (1 << 7)
49#define USB_PORTSC1_PE (1 << 2)
50#define USB_PORTSC1_CCS (1 << 0)
51
52#define USB_SUSP_CTRL 0x400 39#define USB_SUSP_CTRL 0x400
53#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) 40#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
54#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) 41#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
@@ -311,11 +298,8 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
311 val = readl(base + USB_SUSP_CTRL); 298 val = readl(base + USB_SUSP_CTRL);
312 val &= ~USB_SUSP_SET; 299 val &= ~USB_SUSP_SET;
313 writel(val, base + USB_SUSP_CTRL); 300 writel(val, base + USB_SUSP_CTRL);
314 } else { 301 } else
315 val = readl(base + USB_PORTSC1); 302 tegra_ehci_set_phcd(&phy->u_phy, true);
316 val |= USB_PORTSC1_PHCD;
317 writel(val, base + USB_PORTSC1);
318 }
319 303
320 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)
321 pr_err("%s: timeout waiting for phy to stabilize\n", __func__); 305 pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
@@ -336,11 +320,8 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
336 val = readl(base + USB_SUSP_CTRL); 320 val = readl(base + USB_SUSP_CTRL);
337 val &= ~USB_SUSP_CLR; 321 val &= ~USB_SUSP_CLR;
338 writel(val, base + USB_SUSP_CTRL); 322 writel(val, base + USB_SUSP_CTRL);
339 } else { 323 } else
340 val = readl(base + USB_PORTSC1); 324 tegra_ehci_set_phcd(&phy->u_phy, false);
341 val &= ~USB_PORTSC1_PHCD;
342 writel(val, base + USB_PORTSC1);
343 }
344 325
345 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,
346 USB_PHY_CLK_VALID)) 327 USB_PHY_CLK_VALID))
@@ -462,11 +443,8 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
462 443
463 utmi_phy_clk_enable(phy); 444 utmi_phy_clk_enable(phy);
464 445
465 if (!phy->is_legacy_phy) { 446 if (!phy->is_legacy_phy)
466 val = readl(base + USB_PORTSC1); 447 tegra_ehci_set_pts(&phy->u_phy, 0);
467 val &= ~USB_PORTSC1_PTS(~0);
468 writel(val, base + USB_PORTSC1);
469 }
470 448
471 return 0; 449 return 0;
472} 450}
@@ -611,10 +589,6 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
611 return ret; 589 return ret;
612 } 590 }
613 591
614 val = readl(base + USB_PORTSC1);
615 val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
616 writel(val, base + USB_PORTSC1);
617
618 val = readl(base + USB_SUSP_CTRL); 592 val = readl(base + USB_SUSP_CTRL);
619 val |= USB_SUSP_CLR; 593 val |= USB_SUSP_CLR;
620 writel(val, base + USB_SUSP_CTRL); 594 writel(val, base + USB_SUSP_CTRL);
@@ -629,17 +603,8 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
629 603
630static int ulpi_phy_power_off(struct tegra_usb_phy *phy) 604static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
631{ 605{
632 unsigned long val;
633 void __iomem *base = phy->regs;
634 struct tegra_ulpi_config *config = phy->config; 606 struct tegra_ulpi_config *config = phy->config;
635 607
636 /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
637 * Controller to immediately bring the ULPI PHY out of low power
638 */
639 val = readl(base + USB_PORTSC1);
640 val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
641 writel(val, base + USB_PORTSC1);
642
643 clk_disable(phy->clk); 608 clk_disable(phy->clk);
644 return gpio_direction_output(config->reset_gpio, 0); 609 return gpio_direction_output(config->reset_gpio, 0);
645} 610}
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index a6a89d4866f4..9259d4659582 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -75,4 +75,8 @@ void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
75 75
76void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy); 76void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
77 77
78void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val);
79
80void tegra_ehci_set_phcd(struct usb_phy *x, bool enable);
81
78#endif /* __TEGRA_USB_PHY_H */ 82#endif /* __TEGRA_USB_PHY_H */