Exemple #1
0
static int musb_platform_suspend(struct musb *musb)
{
	u32 l;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *pdata = dev->platform_data;
	struct omap_hwmod *oh = pdata->oh;

	if (!musb->clock)
		return 0;

	/* in any role */
	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l |= ENABLEFORCE;	/* enable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);

	pdata->enable_wakeup(oh->od);
	otg_set_clk(musb->xceiv, 0);
	otg_set_suspend(musb->xceiv, 1);

	/* Disable the phy clocks*/


	return 0;
}
static int musb_platform_resume(struct musb *musb)
{
	u32 l;

	if (!musb->clock)
		return 0;

	otg_set_suspend(musb->xceiv, 0);

	if (musb->set_clock)
		musb->set_clock(musb->clock, 1);
	else
		clk_enable(musb->clock);

	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
	l &= ~ENABLEWAKEUP;	/* disable wakeup */
	musb_writel(musb->mregs, OTG_SYSCONFIG, l);

	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);

	return 0;
}
Exemple #3
0
static int musb_platform_resume(struct musb *musb)
{
    u32 l;

    if (!musb->clock)
        return 0;

    otg_set_suspend(musb->xceiv, 0);

    if (musb->set_clock)
        musb->set_clock(musb->clock, 1);
    else
        clk_enable(musb->clock);

    l = omap_readl(OTG_SYSCONFIG);
    l &= ~ENABLEWAKEUP;
    omap_writel(l, OTG_SYSCONFIG);

    l = omap_readl(OTG_FORCESTDBY);
    l &= ~ENABLEFORCE;
    omap_writel(l, OTG_FORCESTDBY);

    return 0;
}
Exemple #4
0
static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
{
	u32 val;
	struct musb_otg_work *otg_work =
		container_of(data_notifier_work, struct musb_otg_work, work);
        struct musb *musb = otg_work->musb;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *pdata = dev->platform_data;
	struct omap_musb_board_data *data = pdata->board_data;
	enum usb_xceiv_events xceiv_event = otg_work->xceiv_event;
	static int last_event = -1;

	kfree(otg_work);

	/* avoid duplicate notifications */
	if (last_event == xceiv_event) {
		WARN(1, "Duplicated event(%d): ignored\n", xceiv_event);
		return;
	}
	/* check for incorrect transitions */
	if ((last_event == USB_EVENT_VBUS && xceiv_event == USB_EVENT_ID) ||
			(last_event == USB_EVENT_ID  && xceiv_event == USB_EVENT_VBUS)) {
		WARN(1, "Incorrect transition (%d)->(%d)\n", last_event, xceiv_event);
	}
	/* store last event */
	last_event = xceiv_event;

	switch (xceiv_event) {
	case USB_EVENT_ID:
		dev_dbg(musb->controller, "ID GND\n");

		if (is_otg_enabled(musb)) {
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
			if (musb->gadget_driver) {
				pm_runtime_get_sync(musb->controller);
				val = musb_readl(musb->mregs, OTG_INTERFSEL);
				otg_set_suspend(musb->xceiv, 1);
				if (data->interface_type ==
						MUSB_INTERFACE_UTMI) {
					val &= ~ULPI_12PIN;
					val |= UTMI_8BIT;
				} else {
					val |= ULPI_12PIN;
				}
				musb_writel(musb->mregs, OTG_INTERFSEL, val);
				otg_set_suspend(musb->xceiv, 0);

				otg_init(musb->xceiv);
				omap2430_musb_set_vbus(musb, 1);
			}
#endif
		} else {
			pm_runtime_get_sync(musb->controller);
			val = musb_readl(musb->mregs, OTG_INTERFSEL);
			otg_set_suspend(musb->xceiv, 1);
			if (data->interface_type == MUSB_INTERFACE_UTMI) {
				val &= ~ULPI_12PIN;
				val |= UTMI_8BIT;
			} else {
				val |= ULPI_12PIN;
			}
			musb_writel(musb->mregs, OTG_INTERFSEL, val);
			otg_set_suspend(musb->xceiv, 0);

			otg_init(musb->xceiv);
			omap2430_musb_set_vbus(musb, 1);
		}
		break;

	case USB_EVENT_CHARGER:
		dev_dbg(musb->controller, "Dedicated charger connect\n");
		musb->is_ac_charger = true;
		break;

	case USB_EVENT_VBUS:
		dev_dbg(musb->controller, "VBUS Connect\n");

#ifdef CONFIG_USB_GADGET_MUSB_HDRC
		if (musb->gadget_driver) {
			pm_runtime_get_sync(musb->controller);
			val = musb_readl(musb->mregs, OTG_INTERFSEL);
			otg_set_suspend(musb->xceiv, 1);
			if (data->interface_type ==
					MUSB_INTERFACE_UTMI) {
				val &= ~ULPI_12PIN;
				val |= UTMI_8BIT;
			} else {
				val |= ULPI_12PIN;
			}
			musb_writel(musb->mregs, OTG_INTERFSEL, val);
			otg_set_suspend(musb->xceiv, 0);
		}

#endif
		otg_init(musb->xceiv);
		break;

	case USB_EVENT_NONE:
		if (musb->is_ac_charger) {
			dev_dbg(musb->controller,
				"Dedicated charger disconnect\n");
			musb->is_ac_charger = false;
			break;
		}

		dev_dbg(musb->controller, "VBUS Disconnect\n");
		pm_runtime_get_sync(musb->controller);

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			omap2430_musb_set_vbus(musb, 0);
			if (musb->xceiv->set_vbus)
				otg_set_vbus(musb->xceiv, 0);
		}
		otg_shutdown(musb->xceiv);
		otg_set_suspend(musb->xceiv, 1);

		val = musb_readl(musb->mregs, OTG_INTERFSEL);
		val |= ULPI_12PIN;
		musb_writel(musb->mregs, OTG_INTERFSEL, val);
		pm_runtime_mark_last_busy(musb->controller);
		pm_runtime_put_autosuspend(musb->controller);

#ifdef CONFIG_USB_GADGET_MUSB_HDRC
		if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
			if (musb->gadget_driver)
#endif
				pm_runtime_put_autosuspend(musb->controller);
		break;
	default:
		dev_dbg(musb->controller, "ID float\n");
	}

}
static void usb_do_work(struct work_struct *w)
{
	struct usb_info *ui = container_of(w, struct usb_info, work);
	unsigned long iflags;
	unsigned flags, _vbus;

	for (;;) {
		spin_lock_irqsave(&ui->lock, iflags);
		flags = ui->flags;
		ui->flags = 0;
		_vbus = vbus;
		spin_unlock_irqrestore(&ui->lock, iflags);

		/* give up if we have nothing to do */
		if (flags == 0)
			break;

		switch (ui->state) {
		case USB_STATE_IDLE:
			if (flags & USB_FLAG_START) {
				int ret;
				struct msm_otg *otg = to_msm_otg(ui->xceiv);

				if (!_vbus) {
					ui->state = USB_STATE_OFFLINE;
					break;
				}

				msm72k_pm_qos_update(1);
				pr_info("msm72k_udc: IDLE -> ONLINE\n");
				usb_reset(ui);
				ret = request_irq(otg->irq, usb_interrupt,
							IRQF_SHARED,
							ui->pdev->name, ui);
				/* FIXME: should we call BUG_ON when
				 * requst irq fails
				 */
				if (ret) {
					pr_err("hsusb: peripheral: request irq"
							" failed:(%d)", ret);
					msm72k_pm_qos_update(0);
					break;
				}
				ui->irq = otg->irq;
				msm72k_pullup(&ui->gadget, 1);

				if (ui->chg_connected) {
					msleep(500);
					ui->chg_type = is_wall_charger(ui);
					ui->chg_current =
						ui->chg_type ? 1500 : 100;
					ui->chg_connected(ui->chg_type);
				}

				ui->state = USB_STATE_ONLINE;
				usb_do_work_check_vbus(ui);
			}
			break;
		case USB_STATE_ONLINE:
			/* If at any point when we were online, we received
			 * the signal to go offline, we must honor it
			 */
			if (flags & USB_FLAG_VBUS_OFFLINE) {
				pr_info("msm72k_udc: ONLINE -> OFFLINE\n");

				otg_set_suspend(ui->xceiv, 0);
				/* synchronize with irq context */
				spin_lock_irqsave(&ui->lock, iflags);
				ui->running = 0;
				ui->online = 0;
				msm72k_pullup(&ui->gadget, 0);
				spin_unlock_irqrestore(&ui->lock, iflags);

				if (ui->chg_connected) {
					ui->chg_type = CHG_TYPE_INVALID;
					ui->chg_current = 0;
					ui->chg_connected(ui->chg_type);
				}

				if (ui->irq) {
					free_irq(ui->irq, ui);
					ui->irq = 0;
				}
				if (ui->usb_connected)
					ui->usb_connected(0);

				/* terminate any transactions, etc */
				flush_all_endpoints(ui);

				if (ui->driver) {
					printk(KERN_INFO "usb: notify offline\n");
					ui->driver->disconnect(&ui->gadget);
				}

				/* power down phy, clock down usb */
				otg_set_suspend(ui->xceiv, 1);

				ui->state = USB_STATE_OFFLINE;
				usb_do_work_check_vbus(ui);
				msm72k_pm_qos_update(0);
				break;
			}
			if (flags & USB_FLAG_SUSPEND) {
				/* TBD: Not supporting bus suspend */
				ui->chg_vbus_draw(0);
				break;
			}
			if (flags & USB_FLAG_CONFIGURED) {
				ui->chg_current = ui->b_max_pow;
				ui->chg_vbus_draw(ui->b_max_pow);
				break;
			}
			if (flags & USB_FLAG_RESET) {
				pr_info("msm72k_udc: ONLINE -> RESET\n");
				msm72k_pullup(&ui->gadget, 0);
				usb_reset(ui);
				msm72k_pullup(&ui->gadget, 1);
				pr_info("msm72k_udc: RESET -> ONLINE\n");
				break;
			}
			break;
		case USB_STATE_OFFLINE:
			/* If we were signaled to go online and vbus is still
			 * present when we received the signal, go online.
			 */
			if ((flags & USB_FLAG_VBUS_ONLINE) && _vbus) {
				int ret;
				struct msm_otg *otg = to_msm_otg(ui->xceiv);

				pr_info("msm72k_udc: OFFLINE -> ONLINE\n");

				msm72k_pm_qos_update(1);
				otg_set_suspend(ui->xceiv, 0);
				usb_reset(ui);
				if (ui->usb_connected)
					ui->usb_connected(1);

				ui->state = USB_STATE_ONLINE;
				usb_do_work_check_vbus(ui);
				ret = request_irq(otg->irq, usb_interrupt,
							IRQF_SHARED,
							ui->pdev->name, ui);
				/* FIXME: should we call BUG_ON when
				 * requst irq fails
				 */
				if (ret) {
					pr_err("hsusb: peripheral: request irq"
							" failed:(%d)", ret);
					break;
				}
				ui->irq = otg->irq;
				enable_irq_wake(otg->irq);
				msm72k_pullup(&ui->gadget, 1);

				if (ui->chg_connected) {
					msleep(500);
					ui->chg_type = is_wall_charger(ui);
					ui->chg_current =
						ui->chg_type ? 1500 : 100;
					ui->chg_connected(ui->chg_type);
				}
			}
			break;
		}
	}
}