static int tegra_ehci_remove(struct platform_device *pdev)
{
	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = NULL;

	if (tegra == NULL)
		return -EINVAL;

	hcd = ehci_to_hcd(tegra->ehci);

	if (hcd == NULL)
		return -EINVAL;

#ifdef CONFIG_USB_OTG_UTILS
	if (tegra->transceiver) {
		otg_set_host(tegra->transceiver->otg, NULL);
		usb_put_transceiver(tegra->transceiver);
	}
#endif

	if (tegra->irq)
		disable_irq_wake(tegra->irq);

	/* Make sure phy is powered ON to access USB register */
	if(!tegra_usb_phy_hw_accessible(tegra->phy))
		tegra_usb_phy_power_on(tegra->phy);

	usb_remove_hcd(hcd);
	tegra_usb_phy_power_off(tegra->phy);
	usb_phy_shutdown(get_usb_phy(tegra->phy));
	iounmap(hcd->regs);
	usb_put_hcd(hcd);

	return 0;
}
Пример #2
0
static int tegra_ehci_remove(struct platform_device *pdev)
{
	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = NULL;
	struct usb_device *rhdev = NULL;
	struct tegra_usb_platform_data *pdata;
	unsigned long timeout = 0;

	if (tegra == NULL)
		return -EINVAL;

	hcd = ehci_to_hcd(tegra->ehci);

	if (hcd == NULL)
		return -EINVAL;

#ifdef CONFIG_TEGRA_EHCI_BOOST_CPU_FREQ
	cancel_delayed_work(&tegra->boost_cpu_freq_work);
	pm_qos_update_request(&tegra->boost_cpu_freq_req,
				PM_QOS_DEFAULT_VALUE);
	tegra->cpu_boost_in_work = false;
#endif
	rhdev = hcd->self.root_hub;
	pdata = dev_get_platdata(&pdev->dev);

#ifdef CONFIG_USB_OTG_UTILS
	if (tegra->transceiver) {
		otg_set_host(tegra->transceiver->otg, NULL);
		usb_put_transceiver(tegra->transceiver);
	}
#endif

	if (tegra->irq)
		disable_irq_wake(tegra->irq);

	/* Make sure phy is powered ON to access USB register */
	if(!tegra_usb_phy_hw_accessible(tegra->phy))
		tegra_usb_phy_power_on(tegra->phy);

	if (pdata->port_otg) {

		timeout = jiffies + 5 * HZ;

		/* wait for devices connected to root hub to disconnect*/
		while (time_before(jiffies, timeout) &&
			rhdev && rhdev->children[0])
			;

		/* wait for any control packets sent to root hub to complete */
		mdelay(1000);
	}

	usb_remove_hcd(hcd);
	tegra_usb_phy_power_off(tegra->phy);
	usb_phy_shutdown(get_usb_phy(tegra->phy));
	iounmap(hcd->regs);
	usb_put_hcd(hcd);

	return 0;
}
Пример #3
0
static int tegra_ehci_remove(struct platform_device *pdev)
{
	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);

	dev_info(&pdev->dev, "%s+\n", __func__);		//htc_dbg

	if (tegra == NULL || hcd == NULL)
		return -EINVAL;

#ifdef CONFIG_USB_OTG_UTILS
	if (tegra->transceiver) {
		otg_set_host(tegra->transceiver, NULL);
		otg_put_transceiver(tegra->transceiver);
	}
#endif

	if (tegra->irq)
		disable_irq_wake(tegra->irq);

	/* Make sure phy is powered ON to access USB register */
	if(!tegra_usb_phy_hw_accessible(tegra->phy))
		tegra_usb_phy_power_on(tegra->phy);

	pr_info("+%s:usb_remove_hcd\n", __func__);
	uhsic_phy_remove(tegra->phy);
	usb_remove_hcd(hcd);
	usb_put_hcd(hcd);
	ehci_remove = 1;
	tegra_usb_phy_power_off(tegra->phy);
	tegra_usb_phy_close(tegra->phy);
	iounmap(hcd->regs);
	platform_set_drvdata(pdev, NULL);

	//htc++
	#ifdef CONFIG_QCT_9K_MODEM
	if (Modem_is_QCT_MDM9K())
	{
		extern struct platform_device tegra_ehci2_device;

		if (&tegra_ehci2_device == pdev)
		{
			mdm_hsic_ehci_hcd = NULL;
			mdm_hsic_usb_hcd = NULL;
			mdm_hsic_phy = NULL;
			pr_info("%s:: mdm_hsic_ehci_hcd = %x, mdm_hsic_usb_hcd = %x, mdm_hsic_phy = %x\n",
				__func__, (unsigned int)mdm_hsic_ehci_hcd, (unsigned int)mdm_hsic_usb_hcd, (unsigned int)mdm_hsic_phy);
		}
	}
	#endif	//CONFIG_QCT_9K_MODEM
	//htc--

	dev_info(&pdev->dev, "%s-\n", __func__);		//htc_dbg

	return 0;
}
Пример #4
0
static int tegra_ehci_remove(struct platform_device *pdev)
{
	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
	struct usb_device *rhdev = NULL;
	struct tegra_usb_platform_data *pdata;
	unsigned long timeout = 0;

	wake_lock_destroy(&tegra->ehci_wake_lock);

#ifdef CONFIG_TEGRA_EHCI_BOOST_CPU_FREQ
	cancel_delayed_work_sync(&tegra->boost_cpu_freq_work);
	tegra->cpu_boost_in_work = false;
	pm_qos_remove_request(&tegra->boost_cpu_freq_req);
#endif
	rhdev = hcd->self.root_hub;
	pdata = dev_get_platdata(&pdev->dev);

	if (!IS_ERR_OR_NULL(tegra->transceiver))
		otg_set_host(tegra->transceiver->otg, NULL);

	/* Make sure phy is powered ON to access USB register */
	if(!tegra_usb_phy_hw_accessible(tegra->phy))
		tegra_usb_phy_power_on(tegra->phy);

	if (pdata->port_otg) {
		timeout = jiffies + 5 * HZ;
		/* wait for devices connected to root hub to disconnect*/
		while (rhdev && usb_hub_find_child(rhdev, 1)) {
			/* wait for any control packets
			sent to root hub to complete */
			if (time_after(jiffies, timeout))
				break;
			msleep(20);
			cpu_relax();
		}
	}

#ifdef CONFIG_TEGRA_EHCI_BOOST_CPU_FREQ
	device_remove_file(hcd->self.controller, &dev_attr_boost_enable);
#endif
	usb_remove_hcd(hcd);
	usb_put_hcd(hcd);
	tegra_usb_phy_power_off(tegra->phy);
	usb_phy_shutdown(get_usb_phy(tegra->phy));

	mutex_destroy(&tegra->sync_lock);
	tegra_pd_remove_device(&pdev->dev);

	return 0;
}
Пример #5
0
static void tegra_ehci_shutdown(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct platform_device *pdev = to_platform_device(hcd->self.controller);
	struct tegra_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
	mutex_lock(&tegra->sync_lock);
	if (tegra_usb_phy_hw_accessible(tegra->phy)) {
		ehci_silence_controller(ehci);
	}
	if (pdata->port_otg)
		tegra_usb_enable_vbus(tegra->phy, false);
	mutex_unlock(&tegra->sync_lock);
}
Пример #6
0
static void tegra_ehci_shutdown(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	mutex_lock(&tegra->sync_lock);
	del_timer_sync(&ehci->watchdog);
	del_timer_sync(&ehci->iaa_watchdog);
	if (tegra_usb_phy_hw_accessible(tegra->phy)) {
		spin_lock_irq(&ehci->lock);
		ehci_silence_controller(ehci);
		spin_unlock_irq(&ehci->lock);
	}
	mutex_unlock(&tegra->sync_lock);
}
static int tegra_ehci_hub_control(
	struct usb_hcd	*hcd,
	u16	typeReq,
	u16	wValue,
	u16	wIndex,
	char	*buf,
	u16	wLength
)
{
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	int	retval = 0;
	u32 __iomem	*status_reg;

	if (!tegra_usb_phy_hw_accessible(tegra->phy)) {
		if (buf)
			memset(buf, 0, wLength);
		return retval;
	}

	/* Do tegra phy specific actions based on the type request */
	switch (typeReq) {
	case GetPortStatus:
		if (tegra->port_resuming) {
			u32 cmd;
			int delay = ehci->reset_done[wIndex-1] - jiffies;
			/* Sometimes it seems we get called too soon... In that case, wait.*/
			if (delay > 0) {
				ehci_dbg(ehci, "GetPortStatus called too soon, waiting %dms...\n", delay);
				mdelay(jiffies_to_msecs(delay));
			}
			status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
			/* Ensure the port PORT_SUSPEND and PORT_RESUME has cleared */
			if (handshake(ehci, status_reg, (PORT_SUSPEND | PORT_RESUME), 0, 25000)) {
				EHCI_DBG("%s: timeout waiting for SUSPEND to clear\n", __func__);
			}
			tegra_usb_phy_post_resume(tegra->phy);
			tegra->port_resuming = 0;
			/* If run bit is not set by now enable it */
			cmd = ehci_readl(ehci, &ehci->regs->command);
			if (!(cmd & CMD_RUN)) {
				cmd |= CMD_RUN;
				ehci->command |= CMD_RUN;
				ehci_writel(ehci, cmd, &ehci->regs->command);
			}
			/* Now we can safely re-enable irqs */
			ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
		}
		break;
	case ClearPortFeature:
		if (wValue == USB_PORT_FEAT_SUSPEND) {
			tegra_usb_phy_pre_resume(tegra->phy, false);
			tegra->port_resuming = 1;
		} else if (wValue == USB_PORT_FEAT_ENABLE) {
			u32 temp;
			temp = ehci_readl(ehci, &ehci->regs->port_status[0]) & ~PORT_RWC_BITS;
			ehci_writel(ehci, temp & ~PORT_PE, &ehci->regs->port_status[0]);
			return retval;
		}
		break;
	case SetPortFeature:
		if (wValue == USB_PORT_FEAT_SUSPEND)
			tegra_usb_phy_pre_suspend(tegra->phy);
		break;
	}

	/* handle ehci hub control request */
	retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);

	/* do tegra phy specific actions based on the type request */
	if (!retval) {
		switch (typeReq) {
		case SetPortFeature:
			if (wValue == USB_PORT_FEAT_SUSPEND) {
				tegra_usb_phy_post_suspend(tegra->phy);
			} else if (wValue == USB_PORT_FEAT_RESET) {
				if (wIndex == 1)
					tegra_usb_phy_bus_reset(tegra->phy);
			} else if (wValue == USB_PORT_FEAT_POWER) {
				if (wIndex == 1)
					tegra_usb_phy_port_power(tegra->phy);
			}
			break;
		case ClearPortFeature:
			if (wValue == USB_PORT_FEAT_SUSPEND) {
				/* tegra USB controller needs 25 ms to resume the port */
				ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
			}
			break;
		}
	}

	return retval;
}
Пример #8
0
static int tegra_ehci_hub_control(
	struct usb_hcd	*hcd,
	u16	typeReq,
	u16	wValue,
	u16	wIndex,
	char	*buf,
	u16	wLength
)
{
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	int	retval = 0;
	u32 __iomem	*status_reg;
	void  __iomem *apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE);
	struct platform_device *pdev = container_of(hcd->self.controller, struct platform_device, dev);
	int ehci_id = pdev->id;

	if (!tegra_usb_phy_hw_accessible(tegra->phy)) {
		if (buf)
			memset(buf, 0, wLength);
		return retval;
	}

	if(ehci_id == MODEM_EHCI_ID){
	printk(KERN_INFO"%s: req:0x%x wV:0x%x wI:0x%x MODE:0x%x CMD:0x%x PORTSC:0x%x STS:0x%x HOSTPC1:0x%x\n",
        __func__, typeReq, wValue, wIndex,
		readl(hcd->regs + 0x1f8),
		readl(&ehci->regs->command),
		readl(&ehci->regs->port_status[0]),
		readl(&ehci->regs->status),
		readl(hcd->regs + 0x1b4));

	printk(KERN_INFO"%s: INTR:0x%x STAT_CFG0:0x%x ASDBGREG:0x%x OBSCTRL:0x%x OBSDATA:0x%x port_resuming:%d\n",
		__func__,
		readl(hcd->regs + 0x138),
		readl(hcd->regs + 0xc28),
		readl(apb_misc + 0x810),
		readl(apb_misc + 0x818),
		readl(apb_misc + 0x81c),
		tegra->port_resuming);
	}

	/* Do tegra phy specific actions based on the type request */
	switch (typeReq) {
	case GetPortStatus:
		if (tegra->port_resuming) {
			u32 cmd;
			int delay = ehci->reset_done[wIndex-1] - jiffies;
			/* Sometimes it seems we get called too soon... In that case, wait.*/
			if (delay > 0) {
				printk(KERN_INFO"GetPortStatus called too soon, waiting %dms...\n",jiffies_to_msecs(delay));
				ehci_dbg(ehci, "GetPortStatus called too soon, waiting %dms...\n", jiffies_to_msecs(delay));
				mdelay(jiffies_to_msecs(delay));
			}
			status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
			tegra_usb_phy_post_resume(tegra->phy);
			tegra->port_resuming = 0;
			/* If run bit is not set by now enable it */
			cmd = ehci_readl(ehci, &ehci->regs->command);
			if (!(cmd & CMD_RUN)) {
				cmd |= CMD_RUN;
				ehci->command |= CMD_RUN;
				ehci_writel(ehci, cmd, &ehci->regs->command);
			}
			/* Now we can safely re-enable irqs */
			ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
		}
		break;
	case ClearPortFeature:
		if (wValue == USB_PORT_FEAT_SUSPEND) {
			tegra_usb_phy_pre_resume(tegra->phy, false);
			tegra->port_resuming = 1;
		} else if (wValue == USB_PORT_FEAT_ENABLE) {
			u32 temp;
			temp = ehci_readl(ehci, &ehci->regs->port_status[0]) & ~PORT_RWC_BITS;
			ehci_writel(ehci, temp & ~PORT_PE, &ehci->regs->port_status[0]);
			return retval;
		}
		break;
	}

	/* handle ehci hub control request */
	retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);

	/* do tegra phy specific actions based on the type request */
	if (!retval) {
		switch (typeReq) {
		case SetPortFeature:
			if (wValue == USB_PORT_FEAT_SUSPEND) {
				/* Need a 4ms delay for controller to suspend */
				mdelay(4);
				tegra_usb_phy_post_suspend(tegra->phy);
			} else if (wValue == USB_PORT_FEAT_RESET) {
				if (ehci->reset_done[0] && wIndex == 1)
					tegra_usb_phy_bus_reset(tegra->phy);
			} else if (wValue == USB_PORT_FEAT_POWER) {
				if (wIndex == 1)
					tegra_usb_phy_port_power(tegra->phy);
			}
			break;
		case ClearPortFeature:
			if (wValue == USB_PORT_FEAT_SUSPEND) {
				/* tegra USB controller needs 25 ms to resume the port */
				ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
			}
			break;
		}
	}

	return retval;
}