示例#1
0
static int ehci_arc_resume(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	u32 tmp;
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

	dbg("%s pdev=0x%p  pdata=0x%p  ehci=0x%p  hcd=0x%p\n",
	    __FUNCTION__, pdev, pdata, ehci, hcd);

	vdbg("%s ehci->regs=0x%p  hcd->regs=0x%p  usbmode=0x%x\n",
	     __FUNCTION__, ehci->regs, hcd->regs, pdata->usbmode);

	tmp = USBMODE_CM_HOST;
	if (ehci_big_endian_mmio(ehci))
		tmp |= USBMODE_BE;

	ehci_writel(ehci, tmp, (u32 *)pdata->usbmode);

	memcpy(ehci->regs, (void *)&usb_ehci_regs, sizeof(struct ehci_regs));

	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	hcd->state = HC_STATE_RUNNING;
	pdev->dev.power.power_state = PMSG_ON;

	tmp = ehci_readl(ehci, &ehci->regs->command);
	tmp |= CMD_RUN;
	ehci_writel(ehci, tmp, &ehci->regs->command);

	fsl_platform_set_vbus_power(pdata, 1);

	usb_hcd_resume_root_hub(hcd);

	return 0;
}
static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
{
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	irqreturn_t irq_status;

	spin_lock(&ehci->lock);
	irq_status = tegra_usb_phy_irq(tegra->phy);
	if (irq_status == IRQ_NONE) {
		spin_unlock(&ehci->lock);
		return irq_status;
	}
	if (tegra_usb_phy_pmc_wakeup(tegra->phy)) {
		ehci_dbg(ehci, "pmc wakeup detected\n");
		usb_hcd_resume_root_hub(hcd);
		spin_unlock(&ehci->lock);
		return irq_status;
	}
	spin_unlock(&ehci->lock);

	EHCI_DBG("%s() cmd = 0x%x, int_sts = 0x%x, portsc = 0x%x\n", __func__,
		ehci_readl(ehci, &ehci->regs->command),
		ehci_readl(ehci, &ehci->regs->status),
		ehci_readl(ehci, &ehci->regs->port_status[0]));

	irq_status = ehci_irq(hcd);

	if (ehci->controller_remote_wakeup) {
		ehci->controller_remote_wakeup = false;
		tegra_usb_phy_pre_resume(tegra->phy, true);
		tegra->port_resuming = 1;
	}
	return irq_status;
}
static int ehci_mid_runtime_resume_host(struct intel_mid_otg_xceiv *iotg)
{
	int		retval;
	struct device	*dev;
	struct pci_dev	*pci_dev;
	struct usb_hcd	*hcd;


	if (iotg == NULL)
		return -EINVAL;

	if (ehci_otg_driver.driver.pm == NULL)
		return -EINVAL;

	dev = iotg->otg.dev;
	pci_dev = to_pci_dev(dev);
	hcd = pci_get_drvdata(pci_dev);

	retval = ehci_otg_driver.driver.pm->runtime_resume(dev);
	if (retval)
		dev_warn(dev, "runtime suspend failed\n");

	/* Workaround: EHCI currently unable to deal with interrupt
	*  when remote wakeup happens,
	*  so a manuallly root-hub resuming is performed here.
	*/
	if (!retval) {
		dev_dbg(dev, "resume root hub\n");
		usb_hcd_resume_root_hub(hcd);
	}
	return retval;
}
示例#4
0
static void usb3_ehci_dock_in_work_handler(struct work_struct *w)
{
	struct ehci_hcd *ehci = hcd_to_ehci (usb3_ehci_handle);

	printk(KERN_INFO "%s: usb resume root hub\n",__func__);
	usb_hcd_resume_root_hub(usb3_ehci_handle);
}
示例#5
0
static int ehci_msm_pm_resume(struct device *dev)
{
	struct usb_hcd *hcd = dev_get_drvdata(dev);
	int ret;
	u32 portsc;

	dev_dbg(dev, "ehci-msm PM resume\n");
	if (!hcd->rh_registered)
		return 0;

	/* Notify OTG to bring hw out of LPM before restoring wakeup flags */
	ret = usb_phy_set_suspend(phy, 0);
	if (ret)
		return ret;

	ehci_resume(hcd, false);
	portsc = readl_relaxed(USB_PORTSC);
	portsc &= ~PORT_RWC_BITS;
	portsc |= PORT_RESUME;
	writel_relaxed(portsc, USB_PORTSC);
	/* Resume root-hub to handle USB event if any else initiate LPM again */
	usb_hcd_resume_root_hub(hcd);

	return ret;
}
示例#6
0
static int ehci_fsl_drv_resume(struct platform_device *pdev)
{
    struct usb_hcd *hcd = platform_get_drvdata(pdev);
    struct ehci_hcd *ehci = hcd_to_ehci(hcd);
    u32 tmp;
    struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

    /* set host mode */
    tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
    ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE);

    /* restore EHCI registers */
    ehci_writel(ehci, usb_ehci_regs.command, &ehci->regs->command);
    ehci_writel(ehci, usb_ehci_regs.intr_enable, &ehci->regs->intr_enable);
    ehci_writel(ehci, usb_ehci_regs.frame_index, &ehci->regs->frame_index);
    ehci_writel(ehci, usb_ehci_regs.segment, &ehci->regs->segment);
    ehci_writel(ehci, usb_ehci_regs.frame_list, &ehci->regs->frame_list);
    ehci_writel(ehci, usb_ehci_regs.async_next, &ehci->regs->async_next);
    ehci_writel(ehci, usb_ehci_regs.configured_flag,
                &ehci->regs->configured_flag);
    ehci_writel(ehci, usb_ehci_regs.frame_list, &ehci->regs->frame_list);
    ehci_writel(ehci, usb_ehci_portsc, &ehci->regs->port_status[0]);

    set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
    hcd->state = HC_STATE_RUNNING;
    pdev->dev.power.power_state = PMSG_ON;

    tmp = ehci_readl(ehci, &ehci->regs->command);
    tmp |= CMD_RUN;
    ehci_writel(ehci, tmp, &ehci->regs->command);

    usb_hcd_resume_root_hub(hcd);

    return 0;
}
示例#7
0
文件: xhci.c 项目: redareda9/linux
static void compliance_mode_recovery(unsigned long arg)
{
	struct xhci_hcd *xhci;
	struct usb_hcd *hcd;
	u32 temp;
	int i;

	xhci = (struct xhci_hcd *)arg;

	for (i = 0; i < xhci->num_usb3_ports; i++) {
		temp = readl(xhci->usb3_ports[i]);
		if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) {
			/*
			 * Compliance Mode Detected. Letting USB Core
			 * handle the Warm Reset
			 */
			xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
					"Compliance mode detected->port %d",
					i + 1);
			xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
					"Attempting compliance mode recovery");
			hcd = xhci->shared_hcd;

			if (hcd->state == HC_STATE_SUSPENDED)
				usb_hcd_resume_root_hub(hcd);

			usb_hcd_poll_rh_status(hcd);
		}
	}

	if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1))
		mod_timer(&xhci->comp_mode_recovery_timer,
			jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
}
static int mxhci_hsic_resume(struct mxhci_hsic_hcd *mxhci)
{
	struct usb_hcd *hcd = hsic_to_hcd(mxhci);
	int ret;
	unsigned long flags;

	if (!mxhci->in_lpm) {
		dev_dbg(mxhci->dev, "%s called in !in_lpm\n", __func__);
		return 0;
	}

	pm_stay_awake(mxhci->dev);

	/* enable force-on mode for periph_on */
	clk_set_flags(mxhci->system_clk, CLKFLAG_RETAIN_PERIPH);

	if (mxhci->bus_perf_client) {
		mxhci->bus_vote = true;
		queue_work(mxhci->wq, &mxhci->bus_vote_w);
	}

	spin_lock_irqsave(&mxhci->wakeup_lock, flags);
	if (mxhci->wakeup_irq_enabled) {
		disable_irq_wake(mxhci->wakeup_irq);
		disable_irq_nosync(mxhci->wakeup_irq);
		mxhci->wakeup_irq_enabled = 0;
	}

	if (mxhci->pm_usage_cnt) {
		mxhci->pm_usage_cnt = 0;
		pm_runtime_put_noidle(mxhci->dev);
	}
	spin_unlock_irqrestore(&mxhci->wakeup_lock, flags);


	ret = regulator_set_voltage(mxhci->hsic_vddcx, mxhci->vdd_low_vol_level,
			mxhci->vdd_high_vol_level);
	if (ret < 0)
		dev_err(mxhci->dev,
			"unable to set nominal vddcx voltage (no VDD MIN)\n");


	clk_prepare_enable(mxhci->system_clk);
	clk_prepare_enable(mxhci->cal_clk);
	clk_prepare_enable(mxhci->hsic_clk);
	clk_prepare_enable(mxhci->utmi_clk);
	clk_prepare_enable(mxhci->core_clk);

	if (mxhci->wakeup_irq)
		usb_hcd_resume_root_hub(hcd);

	mxhci->in_lpm = 0;

	dev_dbg(mxhci->dev, "HSIC-USB exited from low power mode\n");
	xhci_dbg_log_event(&dbg_hsic, NULL, "Controller resumed", 0);

	return 0;
}
示例#9
0
static int ehci_fsl_drv_resume(struct platform_device *pdev)
{
    struct usb_hcd *hcd = platform_get_drvdata(pdev);
    struct ehci_hcd *ehci = hcd_to_ehci(hcd);
    u32 tmp;
    struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

    printk(KERN_INFO "USB Host resumed\n");

    pr_debug("%s('%s'): suspend=%d already_suspended=%d\n", __func__,
             pdata->name, pdata->suspended, pdata->already_suspended);

    /*
     * If the controller was already suspended at suspend time,
     * then don't resume it now.
     */
    if (pdata->already_suspended) {
        pr_debug("already suspended, leaving early\n");
        pdata->already_suspended = 0;
        return 0;
    }

    if (!pdata->suspended) {
        pr_debug("not suspended, leaving early\n");
        return 0;
    }

    pdata->suspended = 0;

    pr_debug("%s resuming...\n", __func__);

    /* set host mode */
    fsl_platform_set_host_mode(hcd);

    /* restore EHCI registers */
    ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
    ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
    ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index);
    ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment);
    ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list);
    ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next);
    ehci_writel(ehci, pdata->pm_configured_flag,
                &ehci->regs->configured_flag);
    ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);

    set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
    hcd->state = HC_STATE_RUNNING;
    pdev->dev.power.power_state = PMSG_ON;

    tmp = ehci_readl(ehci, &ehci->regs->command);
    tmp |= CMD_RUN;
    ehci_writel(ehci, tmp, &ehci->regs->command);

    usb_hcd_resume_root_hub(hcd);

    return 0;
}
示例#10
0
static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	unsigned long flags;
	int status = 0;

	spin_lock_irqsave(&uhci->lock, flags);

	uhci_scan_schedule(uhci);
	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
		goto done;
	uhci_check_ports(uhci);

	status = get_hub_status_data(uhci, buf);

	switch (uhci->rh_state) {
	    case UHCI_RH_SUSPENDED:
		
		if (status || uhci->resuming_ports) {
			status = 1;
			usb_hcd_resume_root_hub(hcd);
		}
		break;

	    case UHCI_RH_AUTO_STOPPED:
		
		if (status)
			wakeup_rh(uhci);
		break;

	    case UHCI_RH_RUNNING:
		
		if (!any_ports_active(uhci)) {
			uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
			uhci->auto_stop_time = jiffies + HZ;
		}
		break;

	    case UHCI_RH_RUNNING_NODEVS:
		
		if (any_ports_active(uhci))
			uhci->rh_state = UHCI_RH_RUNNING;
		else if (time_after_eq(jiffies, uhci->auto_stop_time) &&
				!uhci->wait_for_hp)
			suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
		break;

	    default:
		break;
	}

done:
	spin_unlock_irqrestore(&uhci->lock, flags);
	return status;
}
示例#11
0
static void msm_hsusb_request_host(void *handle, int request)
{
	struct msmusb_hcd *mhcd = handle;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;
	struct msm_otg *otg = container_of(mhcd->xceiv, struct msm_otg, otg);

	switch (request) {
	case REQUEST_RESUME:
		usb_hcd_resume_root_hub(hcd);
		break;
	case REQUEST_START:
		if (mhcd->running)
			break;
		wake_lock(&mhcd->wlock);
		msm_xusb_pm_qos_update(mhcd, 1);
		msm_xusb_enable_clks(mhcd);
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			if (otg->set_clk)
				otg->set_clk(mhcd->xceiv, 1);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 1);
		if (pdata->config_gpio)
			pdata->config_gpio(1);
		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
		mhcd->running = 1;
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			if (otg->set_clk)
				otg->set_clk(mhcd->xceiv, 0);
		break;
	case REQUEST_STOP:
		if (!mhcd->running)
			break;
		mhcd->running = 0;
		
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_SERIAL_PMIC) {
			usb_lpm_exit(hcd);
			if (cancel_work_sync(&(mhcd->lpm_exit_work)))
				usb_lpm_exit_w(&mhcd->lpm_exit_work);
		}
		usb_remove_hcd(hcd);
		if (pdata->config_gpio)
			pdata->config_gpio(0);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 0);
		msm_xusb_disable_clks(mhcd);
		wake_lock_timeout(&mhcd->wlock, HZ/2);
		msm_xusb_pm_qos_update(mhcd, 0);
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) {
			otg->reset(mhcd->xceiv);
			otg_set_suspend(mhcd->xceiv, 1);
		}
		break;
	}
}
示例#12
0
static irqreturn_t ehci_hcd_omap_hack_handler(int irq, void *dev)
{
	struct ehci_hcd_omap *omap = dev_get_drvdata(dev);
	struct ehci_hcd *ehci = omap->ehci;
        struct usb_hcd *hcd = ehci_to_hcd(ehci);

	/* resume root hub? */
	usb_hcd_resume_root_hub(hcd);
	
	return IRQ_HANDLED;
}
示例#13
0
static int str9100_ohci_resume(struct platform_device *pdev)
{
	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));

	if (time_before(jiffies, ohci->next_statechange))
		msleep(5);
	ohci->next_statechange = jiffies;
	pdev->power.power_state = PMSG_ON;
	usb_hcd_resume_root_hub(dev_get_drvdata(pdev));
	return 0;
}
示例#14
0
/*
 * Work thread function for handling the USB power sequence.
 *
 * This work thread is created to avoid the pre-emption from the ISR context.
 * USB Power Rail and Vbus are controlled based on the USB cable connection.
 * USB Power rail function and VBUS control function cannot be called from ISR
 * as NvRmPmuSetVoltage() uses I2C driver, that waits on semaphore
 * during the I2C transaction this will cause the pre-emption if called in ISR.
 */
static void tegra_ehci_irq_work(struct work_struct* irq_work)
{
	struct ehci_hcd *ehci = container_of(irq_work, struct ehci_hcd, irq_work);
	struct usb_hcd *hcd = ehci_to_hcd(ehci);
	struct tegra_hcd_platform_data *pdata;
	u32 status;
	bool kick_rhub = false;

	pdata = hcd->self.controller->platform_data;

#ifdef CONFIG_USB_OTG_UTILS
	if (pdata->otg_mode && ehci->transceiver) {
		if (ehci->transceiver->state == OTG_STATE_A_HOST) {
			if (!ehci->host_reinited) {
				ehci->host_reinited = 1;
				tegra_ehci_power_up(hcd);
				if (hcd->state == HC_STATE_SUSPENDED)
					kick_rhub = true;
				tegra_ehci_restart(hcd);
			}
                } else if (ehci->transceiver->state == OTG_STATE_A_SUSPEND) {
			if (ehci->host_reinited) {
				/* indicate hcd flags, that hardware is not accessible now */
				clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
				ehci_halt(ehci);
				tegra_ehci_power_down(hcd);
				ehci->transceiver->state = OTG_STATE_UNDEFINED;
				ehci->host_reinited = 0;
			}

		}
	} else
#endif
	{
		if (pdata->id_detect == ID_PIN_CABLE_ID) {
			/* read otgsc register for ID pin status change */
			status = readl(hcd->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET);
			/* Check pin status and enable/disable the power */
			if (status & TEGRA_USB_ID_PIN_STATUS) {
				tegra_ehci_power_down(hcd);
			} else {
				tegra_ehci_power_up(hcd);
				if (hcd->state == HC_STATE_SUSPENDED)
					kick_rhub = true;
			}
		}
	}

	if (kick_rhub) {
		hcd->state = HC_STATE_SUSPENDED;
		usb_hcd_resume_root_hub(hcd);
	}
}
示例#15
0
static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
{
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	unsigned long flags;
	int status = 0;

	spin_lock_irqsave(&uhci->lock, flags);

	uhci_scan_schedule(uhci);
	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
		goto done;
	uhci_check_ports(uhci);

	status = get_hub_status_data(uhci, buf);

	switch (uhci->rh_state) {
	    case UHCI_RH_SUSPENDING:
	    case UHCI_RH_SUSPENDED:
		/* if port change, ask to be resumed */
		if (status)
			usb_hcd_resume_root_hub(hcd);
		break;

	    case UHCI_RH_AUTO_STOPPED:
		/* if port change, auto start */
		if (status)
			wakeup_rh(uhci);
		break;

	    case UHCI_RH_RUNNING:
		/* are any devices attached? */
		if (!any_ports_active(uhci)) {
			uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
			uhci->auto_stop_time = jiffies + HZ;
		}
		break;

	    case UHCI_RH_RUNNING_NODEVS:
		/* auto-stop if nothing connected for 1 second */
		if (any_ports_active(uhci))
			uhci->rh_state = UHCI_RH_RUNNING;
		else if (time_after_eq(jiffies, uhci->auto_stop_time))
			suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
		break;

	    default:
		break;
	}

done:
	spin_unlock_irqrestore(&uhci->lock, flags);
	return status;
}
示例#16
0
static int ohci_omap_resume(struct platform_device *dev)
{
	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(dev));

	if (time_before(jiffies, ohci->next_statechange))
		msleep(5);
	ohci->next_statechange = jiffies;

	omap_ohci_clock_power(1);
	dev->dev.power.power_state = PMSG_ON;
	usb_hcd_resume_root_hub(platform_get_drvdata(dev));
	return 0;
}
示例#17
0
static int ohci_hcd_s3c2410_drv_resume(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
	if (time_before(jiffies, ohci->next_statechange))
		msleep(5);
	ohci->next_statechange = jiffies;

	s3c2410_start_hc(pdev, hcd);
	pdev->dev.power.power_state = PMSG_ON;
	usb_hcd_resume_root_hub(hcd);

	return 0;
}
示例#18
0
static void msm_hsusb_request_host(void *handle, int request)
{
	struct msmusb_hcd *mhcd = handle;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	struct msm_usb_host_platform_data *pdata = mhcd->pdata;

	switch (request) {
	case REQUEST_RESUME:
		usb_hcd_resume_root_hub(hcd);
		break;
	case REQUEST_START:
		if (mhcd->running)
			break;
		wake_lock(&mhcd->wlock);
		msm_xusb_pm_qos_update(mhcd, 1);
		msm_xusb_enable_clks(mhcd);
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			clk_enable(mhcd->clk);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 1);
		if (pdata->config_gpio)
			pdata->config_gpio(1);
		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
		mhcd->running = 1;
		if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED)
			clk_disable(mhcd->clk);
		break;
	case REQUEST_STOP:
		if (!mhcd->running)
			break;
		mhcd->running = 0;
		/* come out of lpm before deregistration */
		usb_lpm_exit(hcd);
		if (cancel_work_sync(&(mhcd->lpm_exit_work)))
			usb_lpm_exit_w(&mhcd->lpm_exit_work);
		usb_remove_hcd(hcd);
		if (pdata->config_gpio)
			pdata->config_gpio(0);
		if (pdata->vbus_power)
			pdata->vbus_power(pdata->phy_info, 0);
		msm_xusb_disable_clks(mhcd);
		wake_lock_timeout(&mhcd->wlock, HZ/2);
		msm_xusb_pm_qos_update(mhcd, 0);
		break;
	}
}
示例#19
0
static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 val;

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	/* Fence read for coherency of AHB master intiated writes */
	if (tegra->phy->instance == 0)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
	else if (tegra->phy->instance == 1)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
	else if (tegra->phy->instance == 2)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));
#endif

	if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
		(tegra->ehci->has_hostpc)) {
		/* check if there is any remote wake event */
		if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
			usb_hcd_resume_root_hub(hcd);
		}
	}
	if (tegra->phy->hotplug) {
		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(&hw->status);
			if (!(val  & STS_PCD)) {
				spin_unlock(&ehci->lock);
				return 0;
			}
			val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
			val &= ~(TEGRA_USB_PORTSC1_WKCN | PORT_RWC_BITS);
			writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
		}
		spin_unlock(&ehci->lock);
	}
	return ehci_irq(hcd);
}
示例#20
0
static int s5p_ehci_runtime_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
	int rc = 0;

	if (dev->power.is_suspended)
		return 0;

	dev_dbg(dev, "%s\n", __func__);

	if (s5p_ehci->phy) {
		struct usb_phy *phy = s5p_ehci->phy;

		if (s5p_ehci->post_lpa_resume)
			usb_phy_init(phy);
		pm_runtime_get_sync(phy->dev);
	} else if (pdata && pdata->phy_resume) {
		rc = pdata->phy_resume(pdev, USB_PHY_TYPE_HOST);
		s5p_ehci->post_lpa_resume = !!rc;
	}

	if (s5p_ehci->post_lpa_resume)
		s5p_ehci_configurate(hcd);

	ehci_resume(hcd, false);

	/*
	 * REVISIT: in case of LPA bus won't be resumed, so we do it here.
	 * Alternatively, we can try to setup HC in such a way that it starts
	 * to sense connections. In this case, root hub will be resumed from
	 * interrupt (ehci_irq()).
	 */
	if (s5p_ehci->post_lpa_resume)
		usb_hcd_resume_root_hub(hcd);

	s5p_ehci->post_lpa_resume = 0;

	return 0;
}
示例#21
0
/**
 * The hcd operation need to be done during the wakeup irq
 */
void fsl_usb_recover_hcd(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	u32 cmd = 0;

	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	/* After receive remote wakeup signaling. Must restore
	 * CMDRUN bit in 20ms to keep port status.
	 */
	cmd = ehci_readl(ehci, &ehci->regs->command);
	if (!(cmd & CMD_RUN)) {
		ehci_writel(ehci, ehci->command, &ehci->regs->command);
		/* Resume root hub here? */
		usb_hcd_resume_root_hub(hcd);
	}

	/* disable all interrupt, will re-enable in resume */
	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
}
示例#22
0
static irqreturn_t msm_ehci_dock_connect_irq(int irq, void *data)
{
	const struct msm_usb_host_platform_data *pdata;
	struct msm_hcd *mhcd = data;
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);

	pdata = mhcd->dev->platform_data;

	if (atomic_read(&mhcd->in_lpm))
		usb_hcd_resume_root_hub(hcd);

	if (irq_read_line(pdata->dock_connect_irq)) {
		dev_dbg(mhcd->dev, "%s:Dock removed disable vbus\n", __func__);
		msm_ehci_vbus_power(mhcd, 0);
	} else {
		dev_dbg(mhcd->dev, "%s:Dock connected enable vbus\n", __func__);
		msm_ehci_vbus_power(mhcd, 1);
	}

	return IRQ_HANDLED;
}
示例#23
0
static int ehci_msm_pm_resume(struct device *dev)
{
    struct usb_hcd *hcd = dev_get_drvdata(dev);
    int ret;

    dev_dbg(dev, "ehci-msm PM resume\n");

    if (!hcd->rh_registered)
        return 0;

    /* Notify OTG to bring hw out of LPM before restoring wakeup flags */
    ret = usb_phy_set_suspend(phy, 0);
    if (ret)
        return ret;

    ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
    /* Resume root-hub to handle USB event if any else initiate LPM again */
    usb_hcd_resume_root_hub(hcd);

    return ret;
}
/** Initializes the DWC_otg controller and its root hub and prepares it for host
 * mode operation. Activates the root port. Returns 0 on success and a negative
 * error code on failure. */
int hcd_start(struct usb_hcd *hcd)
{
	dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
	struct usb_bus *bus;

	DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
	bus = hcd_to_bus(hcd);

	hcd->state = HC_STATE_RUNNING;
	if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
		return 0;
	}

	/* Initialize and connect root hub if one is not already attached */
	if (bus->root_hub) {
		DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
		/* Inform the HUB driver to resume. */
		usb_hcd_resume_root_hub(hcd);
	}

	return 0;
}
示例#25
0
static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 val;

	if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
		(tegra->ehci->has_hostpc)) {
		/* check if there is any remote wake event */
		if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
			spin_lock (&ehci->lock);
			usb_hcd_resume_root_hub(hcd);
			spin_unlock (&ehci->lock);
		}
	}
	if (tegra->hotplug) {
		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 0;
			}
		}
		spin_unlock(&ehci->lock);
	}
	return ehci_irq(hcd);
}
示例#26
0
文件: xhci.c 项目: redareda9/linux
/*
 * start xHC (not bus-specific)
 *
 * This is called when the machine transition from S3/S4 mode.
 *
 */
int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
{
	u32			command, temp = 0, status;
	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
	struct usb_hcd		*secondary_hcd;
	int			retval = 0;
	bool			comp_timer_running = false;

	if (!hcd->state)
		return 0;

	/* Wait a bit if either of the roothubs need to settle from the
	 * transition into bus suspend.
	 */
	if (time_before(jiffies, xhci->bus_state[0].next_statechange) ||
			time_before(jiffies,
				xhci->bus_state[1].next_statechange))
		msleep(100);

	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);

	spin_lock_irq(&xhci->lock);
	if (xhci->quirks & XHCI_RESET_ON_RESUME)
		hibernated = true;

	if (!hibernated) {
		/* step 1: restore register */
		xhci_restore_registers(xhci);
		/* step 2: initialize command ring buffer */
		xhci_set_cmd_ring_deq(xhci);
		/* step 3: restore state and start state*/
		/* step 3: set CRS flag */
		command = readl(&xhci->op_regs->command);
		command |= CMD_CRS;
		writel(command, &xhci->op_regs->command);
		if (xhci_handshake(&xhci->op_regs->status,
			      STS_RESTORE, 0, 10 * 1000)) {
			xhci_warn(xhci, "WARN: xHC restore state timeout\n");
			spin_unlock_irq(&xhci->lock);
			return -ETIMEDOUT;
		}
		temp = readl(&xhci->op_regs->status);
	}

	/* If restore operation fails, re-initialize the HC during resume */
	if ((temp & STS_SRE) || hibernated) {

		if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
				!(xhci_all_ports_seen_u0(xhci))) {
			del_timer_sync(&xhci->comp_mode_recovery_timer);
			xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
				"Compliance Mode Recovery Timer deleted!");
		}

		/* Let the USB core know _both_ roothubs lost power. */
		usb_root_hub_lost_power(xhci->main_hcd->self.root_hub);
		usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);

		xhci_dbg(xhci, "Stop HCD\n");
		xhci_halt(xhci);
		xhci_reset(xhci);
		spin_unlock_irq(&xhci->lock);
		xhci_cleanup_msix(xhci);

		xhci_dbg(xhci, "// Disabling event ring interrupts\n");
		temp = readl(&xhci->op_regs->status);
		writel(temp & ~STS_EINT, &xhci->op_regs->status);
		temp = readl(&xhci->ir_set->irq_pending);
		writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
		xhci_print_ir_set(xhci, 0);

		xhci_dbg(xhci, "cleaning up memory\n");
		xhci_mem_cleanup(xhci);
		xhci_dbg(xhci, "xhci_stop completed - status = %x\n",
			    readl(&xhci->op_regs->status));

		/* USB core calls the PCI reinit and start functions twice:
		 * first with the primary HCD, and then with the secondary HCD.
		 * If we don't do the same, the host will never be started.
		 */
		if (!usb_hcd_is_primary_hcd(hcd))
			secondary_hcd = hcd;
		else
			secondary_hcd = xhci->shared_hcd;

		xhci_dbg(xhci, "Initialize the xhci_hcd\n");
		retval = xhci_init(hcd->primary_hcd);
		if (retval)
			return retval;
		comp_timer_running = true;

		xhci_dbg(xhci, "Start the primary HCD\n");
		retval = xhci_run(hcd->primary_hcd);
		if (!retval) {
			xhci_dbg(xhci, "Start the secondary HCD\n");
			retval = xhci_run(secondary_hcd);
		}
		hcd->state = HC_STATE_SUSPENDED;
		xhci->shared_hcd->state = HC_STATE_SUSPENDED;
		goto done;
	}

	/* step 4: set Run/Stop bit */
	command = readl(&xhci->op_regs->command);
	command |= CMD_RUN;
	writel(command, &xhci->op_regs->command);
	xhci_handshake(&xhci->op_regs->status, STS_HALT,
		  0, 250 * 1000);

	/* step 5: walk topology and initialize portsc,
	 * portpmsc and portli
	 */
	/* this is done in bus_resume */

	/* step 6: restart each of the previously
	 * Running endpoints by ringing their doorbells
	 */

	spin_unlock_irq(&xhci->lock);

 done:
	if (retval == 0) {
		/* Resume root hubs only when have pending events. */
		status = readl(&xhci->op_regs->status);
		if (status & STS_EINT) {
			usb_hcd_resume_root_hub(hcd);
			usb_hcd_resume_root_hub(xhci->shared_hcd);
		}
	}

	/*
	 * If system is subject to the Quirk, Compliance Mode Timer needs to
	 * be re-initialized Always after a system resume. Ports are subject
	 * to suffer the Compliance Mode issue again. It doesn't matter if
	 * ports have entered previously to U0 before system's suspension.
	 */
	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running)
		compliance_mode_recovery_timer_init(xhci);

	/* Re-enable port polling. */
	xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
	usb_hcd_poll_rh_status(hcd);
	set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
	usb_hcd_poll_rh_status(xhci->shared_hcd);

	return retval;
}
示例#27
0
static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci (hcd);
	struct ehci_regs __iomem *hw = ehci->regs;
	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
	u32 val;
	irqreturn_t irq_status;
	bool pmc_remote_wakeup = false;

	/* Fence read for coherency of AHB master intiated writes */
	if (tegra->phy->instance == 0)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
	else if (tegra->phy->instance == 1)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
	else if (tegra->phy->instance == 2)
		readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));

	if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
		(tegra->ehci->has_hostpc)) {
		/* check if there is any remote wake event */
		if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
			pmc_remote_wakeup = true;
			spin_lock (&ehci->lock);
			usb_hcd_resume_root_hub(hcd);
			spin_unlock (&ehci->lock);
		}
	}
	if (tegra->phy->hotplug) {
		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(&hw->status);
			if (!(val  & STS_PCD)) {
				spin_unlock(&ehci->lock);
				return 0;
			}
			val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
			val &= ~(TEGRA_USB_PORTSC1_WKCN | PORT_RWC_BITS);
			writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
		}
		spin_unlock(&ehci->lock);
	}

	irq_status = ehci_irq(hcd);

	if (pmc_remote_wakeup) {
		ehci->controller_remote_wakeup = false;
	}

	if (ehci->controller_remote_wakeup) {
		ehci->controller_remote_wakeup = false;
		/* disable interrupts */
		ehci_writel(ehci, 0, &ehci->regs->intr_enable);
		tegra_usb_phy_preresume(tegra->phy, true);
		tegra->port_resuming = 1;
	}
	return irq_status;
}
示例#28
0
static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
{
	struct usb_hcd *hcd = hsic_to_hcd(mehci);
	int cnt = 0, ret;
	unsigned temp;
	int min_vol, max_vol;

	if (!atomic_read(&mehci->in_lpm)) {
		dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
		return 0;
	}

	if (mehci->wakeup_irq_enabled) {
		disable_irq_wake(mehci->wakeup_irq);
		disable_irq_nosync(mehci->wakeup_irq);
		mehci->wakeup_irq_enabled = 0;
	}

	wake_lock(&mehci->wlock);

	if (mehci->bus_perf_client && debug_bus_voting_enabled) {
		mehci->bus_vote = true;
		queue_work(ehci_wq, &mehci->bus_vote_w);
	}

	min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
	max_vol = vdd_val[mehci->vdd_type][VDD_MAX];

	ret = regulator_set_voltage(mehci->hsic_vddcx, min_vol, max_vol);
	if (ret < 0)
		dev_err(mehci->dev, "unable to set nominal vddcx voltage (no VDD MIN)\n");

	clk_prepare_enable(mehci->core_clk);
	clk_prepare_enable(mehci->phy_clk);
	clk_prepare_enable(mehci->cal_clk);
	clk_prepare_enable(mehci->ahb_clk);

	temp = readl_relaxed(USB_USBCMD);
	temp &= ~ASYNC_INTR_CTRL;
	temp &= ~ULPI_STP_CTRL;
	writel_relaxed(temp, USB_USBCMD);

	if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
		goto skip_phy_resume;

	temp = readl_relaxed(USB_PORTSC);
	temp &= ~(PORT_RWC_BITS | PORTSC_PHCD);
	writel_relaxed(temp, USB_PORTSC);
	while (cnt < PHY_RESUME_TIMEOUT_USEC) {
		if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD) &&
			(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE))
			break;
		udelay(1);
		cnt++;
	}

	if (cnt >= PHY_RESUME_TIMEOUT_USEC) {
		/*
		 * This is a fatal error. Reset the link and
		 * PHY to make hsic working.
		 */
		dev_err(mehci->dev, "Unable to resume USB. Reset the hsic\n");
		msm_hsic_config_gpios(mehci, 0);
		msm_hsic_reset(mehci);
	}

skip_phy_resume:

	usb_hcd_resume_root_hub(hcd);

	atomic_set(&mehci->in_lpm, 0);

	if (mehci->async_int) {
		mehci->async_int = false;
		pm_runtime_put_noidle(mehci->dev);
		enable_irq(hcd->irq);
	}

	if (atomic_read(&mehci->pm_usage_cnt)) {
		atomic_set(&mehci->pm_usage_cnt, 0);
		pm_runtime_put_noidle(mehci->dev);
	}

	dev_dbg(mehci->dev, "HSIC-USB exited from low power mode\n");

	return 0;
}
示例#29
0
static int ohci_pci_resume (struct usb_hcd *hcd)
{
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	usb_hcd_resume_root_hub(hcd);
	return 0;
}
示例#30
0
static int msm_ehci_resume(struct msm_hcd *mhcd)
{
	struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
	unsigned long timeout;
	unsigned temp;
	int ret;

	if (!atomic_read(&mhcd->in_lpm)) {
		dev_dbg(mhcd->dev, "%s called in !in_lpm\n", __func__);
		return 0;
	}

	//ASUS_BSP+++ BennyCheng "implement ehci3 phy power collapse mode"
	mutex_lock(&mhcd->ehci_mutex);
	//ASUS_BSP--- BennyCheng "implement ehci3 phy power collapse mode"

	if (mhcd->pmic_gpio_dp_irq_enabled) {
		disable_irq_wake(mhcd->pmic_gpio_dp_irq);
		disable_irq_nosync(mhcd->pmic_gpio_dp_irq);
		mhcd->pmic_gpio_dp_irq_enabled = 0;
	}
	wake_lock(&mhcd->wlock);

	/* Vote for TCXO when waking up the phy */
	ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
	if (ret)
		dev_err(mhcd->dev, "%s failed to vote for "
			"TCXO D0 buffer%d\n", __func__, ret);

	clk_prepare_enable(mhcd->core_clk);
	clk_prepare_enable(mhcd->iface_clk);

	msm_ehci_config_vddcx(mhcd, 1);

	//ASUS_BSP+++ BennyCheng "implement ehci3 phy power collapse mode"
	if (mhcd->lpm_flags & PHY_PWR_COLLAPSED) {
		msm_ehci_ldo_enable(mhcd, 1);
		mhcd->lpm_flags &= ~PHY_PWR_COLLAPSED;
	}
	//ASUS_BSP--- BennyCheng "implement ehci3 phy power collapse mode"

	temp = readl_relaxed(USB_USBCMD);
	temp &= ~ASYNC_INTR_CTRL;
	temp &= ~ULPI_STP_CTRL;
	writel_relaxed(temp, USB_USBCMD);

	if (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD))
		goto skip_phy_resume;

	temp = readl_relaxed(USB_PORTSC) & ~PORTSC_PHCD;
	writel_relaxed(temp, USB_PORTSC);

	timeout = jiffies + usecs_to_jiffies(PHY_RESUME_TIMEOUT_USEC);
	while ((readl_relaxed(USB_PORTSC) & PORTSC_PHCD) ||
			!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_SYNC_STATE)) {
		if (time_after(jiffies, timeout)) {
			/*This is a fatal error. Reset the link and PHY*/
			dev_err(mhcd->dev, "Unable to resume USB. Resetting the h/w\n");
			msm_hsusb_reset(mhcd);
			break;
		}
		udelay(1);
	}

skip_phy_resume:

	usb_hcd_resume_root_hub(hcd);
	atomic_set(&mhcd->in_lpm, 0);

	if (mhcd->async_int) {
		mhcd->async_int = false;
		pm_runtime_put_noidle(mhcd->dev);
		enable_irq(hcd->irq);
	}

	if (atomic_read(&mhcd->pm_usage_cnt)) {
		atomic_set(&mhcd->pm_usage_cnt, 0);
		pm_runtime_put_noidle(mhcd->dev);
	}

	//ASUS_BSP+++ BennyCheng "implement ehci3 phy power collapse mode"
	mutex_unlock(&mhcd->ehci_mutex);
	//ASUS_BSP--- BennyCheng "implement ehci3 phy power collapse mode"

	dev_info(mhcd->dev, "EHCI USB exited from low power mode\n");

	return 0;
}