diff options
author | Ken Chang <kenc@nvidia.com> | 2011-07-01 15:35:06 +0800 |
---|---|---|
committer | Manish Tuteja <mtuteja@nvidia.com> | 2011-07-06 03:28:09 -0700 |
commit | 894ef272deec269ccbf1caf2b9a5e4ce3bbf7a0f (patch) | |
tree | 47d7e5d06d7483b5310c97ce947c67b3682186cb | |
parent | 17cf593083f77b5a86ea29ab73741ce2950778ae (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.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_tegra_udc.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 40 | ||||
-rw-r--r-- | include/linux/fsl_devices.h | 8 | ||||
-rw-r--r-- | include/linux/platform_data/tegra_usb.h | 9 |
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 { |