Example #1
0
static ssize_t store_host_en(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
	unsigned long host;
	int err;

	err = kstrtoul(buf, 10, &host);
	if (err < 0) {
		return err;
	}

	if (host) {
		enable_interrupt(tegra, false);
		tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
		tegra_change_otg_state(tegra, OTG_STATE_A_HOST);
		tegra->interrupt_mode = false;
	} else {
		tegra->interrupt_mode = true;
		tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
		enable_interrupt(tegra, true);
	}

	return count;
}
Example #2
0
static void irq_work(struct work_struct *work)
{
	struct tegra_otg_data *tegra =
		container_of(work, struct tegra_otg_data, work);
	struct otg_transceiver *otg = &tegra->otg;
	enum usb_otg_state from = otg->state;
	enum usb_otg_state to = OTG_STATE_UNDEFINED;
	unsigned long flags;
	unsigned long status;

	spin_lock_irqsave(&tegra->lock, flags);
	status = tegra->int_status;

	/* Debug prints */
	DBG("%s(%d) status = 0x%lx\n", __func__, __LINE__, status);
	if ((status & USB_ID_INT_STATUS) &&
			(status & USB_VBUS_INT_STATUS))
		DBG("%s(%d) got vbus & id interrupt\n", __func__, __LINE__);
	else {
		if (status & USB_ID_INT_STATUS)
			DBG("%s(%d) got id interrupt\n", __func__, __LINE__);
		if (status & USB_VBUS_INT_STATUS)
			DBG("%s(%d) got vbus interrupt\n", __func__, __LINE__);
	}

	if (!(status & USB_ID_STATUS) && (status & USB_ID_INT_EN))
		to = OTG_STATE_A_HOST;
	else if (status & USB_VBUS_STATUS && from != OTG_STATE_A_HOST)
		to = OTG_STATE_B_PERIPHERAL;
	else
		to = OTG_STATE_A_SUSPEND;

	spin_unlock_irqrestore(&tegra->lock, flags);
	tegra_change_otg_state(tegra, to);
}
Example #3
0
static void tegra_otg_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
	struct otg_transceiver *otg = &tegra->otg;
	int val;
	unsigned long flags;
	DBG("%s(%d) BEGIN\n", __func__, __LINE__);

	/* Clear pending interrupts */
	clk_enable(tegra->clk);
	val = otg_readl(tegra, USB_PHY_WAKEUP);
	otg_writel(tegra, val, USB_PHY_WAKEUP);
	DBG("%s(%d) PHY WAKEUP register : 0x%x\n", __func__, __LINE__, val);
	clk_disable(tegra->clk);

	/* Handle if host cable is replaced with device during suspend state */
	if (otg->state == OTG_STATE_A_HOST && (val & USB_ID_STATUS))
		tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);

	/* Enable interrupt and call work to set to appropriate state */
	spin_lock_irqsave(&tegra->lock, flags);
	tegra->int_status = (val | USB_INT_EN);
	spin_unlock_irqrestore(&tegra->lock, flags);
	irq_work(&tegra->work);

	enable_interrupt(tegra, true);
	DBG("%s(%d) END\n", __func__, __LINE__);
}
static int tegra_otg_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
	struct otg_transceiver *otg = &tegra->otg;
	int val;

	mutex_lock(&tegra->irq_work_mutex);
	DBG("%s(%d) BEGIN state : %s\n", __func__, __LINE__,
					tegra_state_name(otg->state));

	clk_enable(tegra->clk);
	val = otg_readl(tegra, USB_PHY_WAKEUP);
	val &= ~(USB_ID_INT_EN | USB_VBUS_INT_EN);
	otg_writel(tegra, val, USB_PHY_WAKEUP);
	clk_disable(tegra->clk);

	/* Suspend peripheral mode, host mode is taken care by host driver */
	if (otg->state == OTG_STATE_B_PERIPHERAL)
		tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);

	tegra->suspended = true;

	DBG("%s(%d) END\n", __func__, __LINE__);
	mutex_unlock(&tegra->irq_work_mutex);
	return 0;
}
Example #5
0
static ssize_t store_host_en(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
	unsigned long host;

	if (sscanf(buf, "%d", &host) != 1 || host < 0 || host > 1)
		return -EINVAL;

	if (host) {
		enable_interrupt(tegra, false);
		tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
		tegra_change_otg_state(tegra, OTG_STATE_A_HOST);
		tegra->interrupt_mode = false;
	} else {
		tegra->interrupt_mode = true;
		tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
		enable_interrupt(tegra, true);
	}

	return count;
}
Example #6
0
static void irq_work(struct work_struct *work)
{
	struct tegra_otg_data *tegra =
		container_of(work, struct tegra_otg_data, work);
	struct otg_transceiver *otg = &tegra->otg;
	enum usb_otg_state from = otg->state;
	enum usb_otg_state to = OTG_STATE_UNDEFINED;
	unsigned long flags;
	unsigned long status;

	spin_lock_irqsave(&tegra->lock, flags);
	status = tegra->int_status;

/* ++ ZTE: cuijian@20120703 */	
	if( (status & USB_VBUS_STATUS) || !(status & USB_ID_STATUS)){
		if (!tegra->otg_wake_locked){
			printk(KERN_INFO "%s(%d) tegra_otg USB_EVENT_VBUS\n", __func__, __LINE__);
			tegra->otg.last_event = USB_EVENT_VBUS;
			atomic_notifier_call_chain(&tegra->otg.notifier,
					tegra->otg.last_event, NULL);
			tegra->otg_wake_locked = 1;
		}
	} else {
		if (tegra->otg_wake_locked){
			printk(KERN_INFO "%s(%d) tegra_otg USB_EVENT_NONE\n", __func__, __LINE__);
			tegra->otg.last_event = USB_EVENT_NONE;
			atomic_notifier_call_chain(&tegra->otg.notifier,
						tegra->otg.last_event, NULL);
			tegra->otg_wake_locked = 0;
		}
	}
/* -- ZTE: cuijian@20120703 */

	/* Debug prints */
	DBG("%s(%d) status = 0x%x\n", __func__, __LINE__, status);
	if ((status & USB_ID_INT_STATUS) &&
			(status & USB_VBUS_INT_STATUS)){
		DBG("%s(%d) got vbus & id interrupt\n", __func__, __LINE__);
		if ((!(status & USB_ID_STATUS)) && (status & USB_VBUS_STATUS)){
			DBG("%s(%d) MHL with ext power\n", __func__, __LINE__);
			spin_unlock_irqrestore(&tegra->lock, flags);
			return;
		}
	}
	else {
		if (status & USB_ID_INT_STATUS)
			DBG("%s(%d) got id interrupt\n", __func__, __LINE__);
		if (status & USB_VBUS_INT_STATUS)
			DBG("%s(%d) got vbus interrupt\n", __func__, __LINE__);
	}

	if (!(status & USB_ID_STATUS))
		to = OTG_STATE_A_HOST;
	else if (status & USB_VBUS_STATUS && from != OTG_STATE_A_HOST)
		to = OTG_STATE_B_PERIPHERAL;
	else
		to = OTG_STATE_A_SUSPEND;

	spin_unlock_irqrestore(&tegra->lock, flags);
	tegra_change_otg_state(tegra, to);
}