summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrishna Yarlagadda <kyarlagadda@nvidia.com>2013-05-02 17:30:46 +0530
committerRiham Haidar <rhaidar@nvidia.com>2013-06-11 17:31:59 -0700
commit02be51ade99e6792682b387fd18fbad43bee9ebf (patch)
treeb5fcd535beaef6dbd4724d990aa6adcaa42e41c1
parentfd8b151aba563df1be5d57cae204bfee2ed5f4cb (diff)
USB: xhci: Dynamic host load support
Load xhci dynamically when otg cable is connected Bug 1242148 Change-Id: If6b9b3ad198e3d1aef7636e9a7752be7a4ccc1c7 Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Reviewed-on: http://git-master/r/234146 Reviewed-by: Riham Haidar <rhaidar@nvidia.com> Tested-by: Riham Haidar <rhaidar@nvidia.com>
-rw-r--r--drivers/usb/host/xhci-tegra.c24
-rw-r--r--drivers/usb/otg/tegra-otg.c25
2 files changed, 26 insertions, 23 deletions
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 29e96ea15d84..490de9ef6ede 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -314,15 +314,7 @@ static void update_speed(struct tegra_xhci_hcd *tegra, u8 port)
pmc_data.port_speed = USB_PMC_PORT_SPEED_UNKNOWN;
}
-static void setup_wake_detect(bool setup_wake)
-{
- if (setup_wake)
- pmc_data.pmc_ops->setup_pmc_wake_detect(&pmc_data);
- else
- pmc_data.pmc_ops->disable_pmc_bus_ctrl(&pmc_data);
-}
-
-static void pmc_init(struct tegra_xhci_hcd *tegra, bool setup_wake)
+static void pmc_init(struct tegra_xhci_hcd *tegra)
{
u32 portmap = tegra->bdata->portmap;
@@ -332,7 +324,6 @@ static void pmc_init(struct tegra_xhci_hcd *tegra, bool setup_wake)
pmc_data.phy_type = TEGRA_USB_PHY_INTF_UTMI;
update_speed(tegra, PMC_PORT_UTMIP_P0);
tegra_usb_pmc_init(&pmc_data);
- setup_wake_detect(setup_wake);
}
if (portmap & TEGRA_XUSB_USB2_P1) {
/* XUSB_USB2_P1 is PMC UTMI_P2 */
@@ -340,14 +331,12 @@ static void pmc_init(struct tegra_xhci_hcd *tegra, bool setup_wake)
pmc_data.phy_type = TEGRA_USB_PHY_INTF_UTMI;
update_speed(tegra, PMC_PORT_UTMIP_P2);
tegra_usb_pmc_init(&pmc_data);
- setup_wake_detect(setup_wake);
}
if (portmap & TEGRA_XUSB_HSIC_P0) {
pmc_data.instance = PMC_PORT_UHSIC_P0;
pmc_data.phy_type = TEGRA_USB_PHY_INTF_HSIC;
update_speed(tegra, PMC_PORT_UHSIC_P0);
tegra_usb_pmc_init(&pmc_data);
- setup_wake_detect(setup_wake);
}
}
@@ -1659,7 +1648,8 @@ static int tegra_xhci_host_elpg_entry(struct tegra_xhci_hcd *tegra)
/* STEP 1.1: Do a context save of XUSB and IPFS registers */
tegra_xhci_save_xusb_ctx(tegra);
- pmc_init(tegra, 1);
+ pmc_init(tegra);
+ pmc_data.pmc_ops->setup_pmc_wake_detect(&pmc_data);
tegra_xhci_hs_wake_on_interrupts(tegra, true);
xhci_dbg(xhci, "%s: PMC_UTMIP_UHSIC_SLEEP_CFG_0 = %x\n", __func__,
@@ -1884,7 +1874,7 @@ static void tegra_xhci_war_for_tctrl_rctrl(struct tegra_xhci_hcd *tegra)
* XUSB_PADCTL_USB2_BIAS_PAD_CTL_0_0::PD_TRK = 1
*/
reg = readl(tegra->padctl_base + USB2_BIAS_PAD_CTL_0_0);
- reg |= (1 << 12) | (1 << 13);
+ reg |= (1 << 13);
writel(reg, tegra->padctl_base + USB2_BIAS_PAD_CTL_0_0);
/* Program these values into PMC regiseter and program the
@@ -2020,7 +2010,8 @@ tegra_xhci_host_partition_elpg_exit(struct tegra_xhci_hcd *tegra)
goto out;
}
- pmc_init(tegra, 0);
+ pmc_init(tegra);
+ pmc_data.pmc_ops->disable_pmc_bus_ctrl(&pmc_data);
tegra->hc_in_elpg = false;
ret = xhci_resume(tegra->xhci, 0);
@@ -2950,6 +2941,8 @@ static int tegra_xhci_probe(struct platform_device *pdev)
tegra_xhci_debug_read_pads(tegra);
utmi_phy_pad_enable();
utmi_phy_iddq_override(false);
+ pmc_init(tegra);
+ pmc_data.pmc_ops->powerup_pmc_wake_detect(&pmc_data);
return 0;
@@ -2986,6 +2979,7 @@ static int tegra_xhci_remove(struct platform_device *pdev)
xhci = tegra->xhci;
hcd = xhci_to_hcd(xhci);
+ tegra_xhci_release_port_ownership(tegra, true);
devm_free_irq(&pdev->dev, tegra->usb3_irq, tegra);
devm_free_irq(&pdev->dev, tegra->padctl_irq, tegra);
devm_free_irq(&pdev->dev, tegra->smi_irq, tegra);
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index 23fb48f213fb..8a20c58b91e7 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -26,6 +26,7 @@
#include <linux/usb/gadget.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
+#include <mach/xusb.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -218,29 +219,37 @@ static unsigned long enable_interrupt(struct tegra_otg_data *tegra, bool en)
static void tegra_start_host(struct tegra_otg_data *tegra)
{
struct tegra_usb_otg_data *pdata = tegra->pdata;
- struct platform_device *pdev, *ehci_device = pdata->ehci_device;
+ struct platform_device *pdev, *host_device;
int val;
DBG("%s(%d) Begin\n", __func__, __LINE__);
if (tegra->pdev)
return;
+ if (pdata->is_xhci)
+ host_device = pdata->xhci_device;
+ else
+ host_device = pdata->ehci_device;
/* prepare device structure for registering host*/
- pdev = platform_device_alloc(ehci_device->name, ehci_device->id);
+ pdev = platform_device_alloc(host_device->name, host_device->id);
if (!pdev)
return ;
- val = platform_device_add_resources(pdev, ehci_device->resource,
- ehci_device->num_resources);
+ val = platform_device_add_resources(pdev, host_device->resource,
+ host_device->num_resources);
if (val)
goto error;
- pdev->dev.dma_mask = ehci_device->dev.dma_mask;
- pdev->dev.coherent_dma_mask = ehci_device->dev.coherent_dma_mask;
+ pdev->dev.dma_mask = host_device->dev.dma_mask;
+ pdev->dev.coherent_dma_mask = host_device->dev.coherent_dma_mask;
- val = platform_device_add_data(pdev, pdata->ehci_pdata,
- sizeof(struct tegra_usb_platform_data));
+ if (pdata->is_xhci)
+ val = platform_device_add_data(pdev, pdata->xhci_pdata,
+ sizeof(struct tegra_xusb_platform_data));
+ else
+ val = platform_device_add_data(pdev, pdata->ehci_pdata,
+ sizeof(struct tegra_usb_platform_data));
if (val)
goto error;