Esempio n. 1
0
static int s5p_ehci_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ehci->hcd;
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	unsigned long flags;
	int rc = 0;

#if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB)
	rc = get_hostwake_state();
	if (rc) {
		pr_info("%s: suspend fail by host wakeup irq\n", __func__);
		pm_runtime_resume(&pdev->dev);
		return -EBUSY;
	}
#endif

	if (time_before(jiffies, ehci->next_statechange))
		usleep_range(10000, 11000);

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */

	spin_lock_irqsave(&ehci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) {
		spin_unlock_irqrestore(&ehci->lock, flags);
		return -EINVAL;
	}
	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
	(void)ehci_readl(ehci, &ehci->regs->intr_enable);

	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	spin_unlock_irqrestore(&ehci->lock, flags);

	if (pdata && pdata->phy_exit)
		pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
#if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB)
	set_host_states(0);
#endif

	clk_disable(s5p_ehci->clk);

	return rc;
}
Esempio n. 2
0
static void s5p_wait_for_cp_resume(struct platform_device *pdev,
	struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	u32 __iomem	*portsc ;
	u32 val32, retry_cnt = 0;

	portsc = &ehci->regs->port_status[CP_PORT-1];

#if !defined(CONFIG_MDM_HSIC_PM)
	set_host_states(1);
#endif
	do {
		usleep_range(10000, 11000);
		val32 = ehci_readl(ehci, portsc);
	} while (++retry_cnt < RETRY_CNT_LIMIT && !(val32 & PORT_CONNECT));

	if (retry_cnt >= RETRY_CNT_LIMIT)
		dev_info(&pdev->dev, "%s: retry_cnt = %d, portsc = 0x%x\n",
			__func__, retry_cnt, val32);
}