summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Chang <kenc@nvidia.com>2011-07-01 15:35:06 +0800
committerManish Tuteja <mtuteja@nvidia.com>2011-07-06 03:28:09 -0700
commit894ef272deec269ccbf1caf2b9a5e4ce3bbf7a0f (patch)
tree47d7e5d06d7483b5310c97ce947c67b3682186cb
parent17cf593083f77b5a86ea29ab73741ce2950778ae (diff)
usb: ehci: tegra: fix hotplug issue on usb2
usb hotplug is supported only for UTMI phy. usb_phy_type should be carefully checked in ehci irq. bug 845612 Change-Id: I2fdc7c79b9816dd3465353375448b07f138ff950 Reviewed-on: http://git-master/r/39338 Tested-by: Ken Chang <kenc@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: Yu-Fong (Foster) Cho <ycho@nvidia.com> Reviewed-by: ChihJen Hsu <chhsu@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h5
-rw-r--r--arch/arm/mach-tegra/usb_phy.c4
-rw-r--r--drivers/usb/gadget/fsl_tegra_udc.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c40
-rw-r--r--include/linux/fsl_devices.h8
-rw-r--r--include/linux/platform_data/tegra_usb.h9
6 files changed, 46 insertions, 22 deletions
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index 0ff8f5545d31..525573c9d297 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/usb/otg.h>
+#include <linux/platform_data/tegra_usb.h>
struct tegra_utmip_config {
u8 hssync_start_delay;
@@ -92,12 +93,14 @@ struct tegra_usb_phy {
enum tegra_usb_phy_mode mode;
void *config;
struct regulator *reg_vdd;
+ enum tegra_usb_phy_type usb_phy_type;
bool regulator_on;
struct otg_transceiver *ulpi;
};
struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
- void *config, enum tegra_usb_phy_mode phy_mode);
+ void *config, enum tegra_usb_phy_mode phy_mode,
+ enum tegra_usb_phy_type usb_phy_type);
int tegra_usb_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd);
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 93310b9f3abd..5a352afb279b 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -1076,7 +1076,8 @@ static irqreturn_t usb_phy_vbus_irq_thr(int irq, void *pdata)
}
struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
- void *config, enum tegra_usb_phy_mode phy_mode)
+ void *config, enum tegra_usb_phy_mode phy_mode,
+ enum tegra_usb_phy_type usb_phy_type)
{
struct tegra_usb_phy *phy;
struct tegra_ulpi_config *ulpi_config;
@@ -1094,6 +1095,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
phy->config = config;
phy->mode = phy_mode;
phy->regulator_on = 0;
+ phy->usb_phy_type = usb_phy_type;
if (!phy->config) {
if (phy_is_ulpi(phy)) {
diff --git a/drivers/usb/gadget/fsl_tegra_udc.c b/drivers/usb/gadget/fsl_tegra_udc.c
index 712636d8ee8e..73f6bc99cd6a 100644
--- a/drivers/usb/gadget/fsl_tegra_udc.c
+++ b/drivers/usb/gadget/fsl_tegra_udc.c
@@ -74,7 +74,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
instance = 0;
phy = tegra_usb_phy_open(instance, udc_base, pdata->phy_config,
- TEGRA_USB_PHY_MODE_DEVICE);
+ TEGRA_USB_PHY_MODE_DEVICE, pdata->usb_phy_type);
if (IS_ERR(phy)) {
dev_err(&pdev->dev, "Can't open phy\n");
err = PTR_ERR(phy);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 90c88009ed45..04b9ec60b476 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -85,28 +85,30 @@ static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
struct ehci_regs __iomem *hw = ehci->regs;
u32 val;
- spin_lock (&ehci->lock);
- val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
- if ((val & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
- val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB | TEGRA_USB_PHY_CLK_VALID_INT_STS;
- writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));
-
- val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
- val &= ~TEGRA_USB_PORTSC1_WKCN;
- writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
-
- val = readl(&hw->status);
- if (!(val & STS_PCD)) {
+ if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
+ spin_lock (&ehci->lock);
+ val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
+ if ((val & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
+ val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB | TEGRA_USB_PHY_CLK_VALID_INT_STS;
+ writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));
+
+ val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
+ val &= ~TEGRA_USB_PORTSC1_WKCN;
+ writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
+
+ val = readl(&hw->status);
+ if (!(val & STS_PCD)) {
+ spin_unlock (&ehci->lock);
+ return IRQ_NONE;
+ }
+ }
+ /* we would lock if we went further without power */
+ if (!tegra->host_resumed) {
spin_unlock (&ehci->lock);
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
- }
- /* we would lock if we went further without power */
- if (!tegra->host_resumed) {
spin_unlock (&ehci->lock);
- return IRQ_HANDLED;
}
- spin_unlock (&ehci->lock);
return ehci_irq(hcd);
}
@@ -902,7 +904,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&tegra->work, tegra_hsic_connection_work);
tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
- TEGRA_USB_PHY_MODE_HOST);
+ TEGRA_USB_PHY_MODE_HOST, pdata->phy_type);
if (IS_ERR(tegra->phy)) {
dev_err(&pdev->dev, "Failed to open USB phy\n");
err = -ENXIO;
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index b39a195775e3..9517375ba9f7 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -58,12 +58,20 @@ enum fsl_usb2_phy_modes {
FSL_USB2_PHY_SERIAL,
};
+enum fsl_usb2_phy_types {
+ FSL_USB2_PHY_TYPE_UTMIP = 1,
+ FSL_USB2_PHY_TYPE_ULPI = 2,
+ FSL_USB2_PHY_TYPE_HSIC = 3,
+ FSL_USB2_PHY_TYPE_ICUSB = 4,
+};
+
struct fsl_usb2_platform_data {
/* board specific information */
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
void *phy_config;
+ enum fsl_usb2_phy_types usb_phy_type;
};
/* Flags in fsl_usb2_mph_platform_data */
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
index e48ac43dd047..dc0696c47820 100644
--- a/include/linux/platform_data/tegra_usb.h
+++ b/include/linux/platform_data/tegra_usb.h
@@ -21,11 +21,20 @@ enum tegra_usb_operating_modes {
TEGRA_USB_OTG,
};
+enum tegra_usb_phy_type {
+ TEGRA_USB_PHY_TYPE_UTMIP = 0,
+ TEGRA_USB_PHY_TYPE_LINK_ULPI = 1,
+ TEGRA_USB_PHY_TYPE_NULL_ULPI = 2,
+ TEGRA_USB_PHY_TYPE_HSIC = 3,
+ TEGRA_USB_PHY_TYPE_ICUSB = 4,
+};
+
struct tegra_ehci_platform_data {
enum tegra_usb_operating_modes operating_mode;
/* power down the phy on bus suspend */
int power_down_on_bus_suspend;
void *phy_config;
+ enum tegra_usb_phy_type phy_type;
};
struct tegra_otg_platform_data {