Beispiel #1
0
int usb_lowlevel_init(int index, void **controller)
{
	u8 power;
	void *mbase;
	int timeout = MUSB_HOST_TIMEOUT;

	if (!host) {
		printf("MUSB host is not registered\n");
		return -ENODEV;
	}

	musb_start(host);
	mbase = host->mregs;
	do {
		if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
			break;
	} while (--timeout);
	if (!timeout)
		return -ENODEV;

	power = musb_readb(mbase, MUSB_POWER);
	musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
	udelay(30000);
	power = musb_readb(mbase, MUSB_POWER);
	musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
	host->isr(0, host);
	host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
			USB_SPEED_HIGH :
			(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
			USB_SPEED_FULL : USB_SPEED_LOW;
	host->is_active = 1;
	hcd.hcd_priv = host;

	return 0;
}
Beispiel #2
0
int musb_lowlevel_init(struct musb_host_data *host)
{
	void *mbase;
	/* USB spec says it may take up to 1 second for a device to connect */
	unsigned long timeout = get_timer(0) + 1000;
	int ret;

	if (!host->host) {
		printf("MUSB host is not registered\n");
		return -ENODEV;
	}

	ret = musb_start(host->host);
	if (ret)
		return ret;

	mbase = host->host->mregs;
	do {
		if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
			break;
	} while (get_timer(0) < timeout);
	if (get_timer(0) >= timeout) {
		musb_stop(host->host);
		return -ENODEV;
	}

	_musb_reset_root_port(host, NULL);
	host->host->is_active = 1;
	host->hcd.hcd_priv = host->host;

	return 0;
}
Beispiel #3
0
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
{
	void *mbase;
	/* USB spec says it may take up to 1 second for a device to connect */
	unsigned long timeout = get_timer(0) + 1000;

	if (!host) {
		printf("MUSB host is not registered\n");
		return -ENODEV;
	}

	musb_start(host);
	mbase = host->mregs;
	do {
		if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
			break;
	} while (get_timer(0) < timeout);
	if (get_timer(0) >= timeout)
		return -ENODEV;

	usb_reset_root_port();
	host->is_active = 1;
	hcd.hcd_priv = host;

	return 0;
}
Beispiel #4
0
void mt_usb_connect(void)
{
	os_printk(K_DEBUG,"%s+\n", __func__);

	musb_start(mu3d_musb);

	os_printk(K_DEBUG,"%s-\n", __func__);
}
void mt_usb_connect(void)
{
    DBG(0,"[MUSB] USB is ready for connect\n");
    DBG(3, "is ready %d is_host %d power %d\n",mtk_musb->is_ready,mtk_musb->is_host , mtk_musb->power);
    if(!mtk_musb || !mtk_musb->is_ready || mtk_musb->is_host || mtk_musb->power)
        return;
	if(cable_mode == CABLE_MODE_CHRG_ONLY)
	{
		musb_sync_with_bat(mtk_musb,USB_CONFIGURED);
		mtk_musb->power = true;
		return;
	}
    musb_start(mtk_musb);
	DBG(0,"USB connect\n");
}
Beispiel #6
0
static void musb_id_pin_work(struct work_struct *data)
{
	//bool is_ready = mtk_musb->is_ready;
	//u8 opstate = 0;
	down(&mtk_musb->musb_lock);
	DBG(0, "work start, is_host=%d\n", mtk_musb->is_host);
	if(mtk_musb->in_ipo_off) {
		DBG(0, "do nothing due to in_ipo_off\n");
		goto out;
	}
	//mtk_musb->is_ready = FALSE;
	mtk_musb ->is_host = musb_is_host();
	DBG(0,"musb is as %s\n",mtk_musb->is_host?"host":"device");
	switch_set_state((struct switch_dev *)&otg_state,mtk_musb->is_host);
	if(mtk_musb ->is_host) {
        	//setup fifo for host mode
        ep_config_from_table_for_host(mtk_musb);
    	wake_lock(&mtk_musb->usb_lock);
    	ignore_vbuserr = false;
		musb_set_vbus(mtk_musb,true);
		musb_start(mtk_musb);
		switch_int_to_device();
	} else {
		DBG(0,"devctl is %x\n",musb_readb(mtk_musb->mregs,MUSB_DEVCTL));
		dumpTime(funcWriteb, 0);
		musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,0);
		wake_unlock(&mtk_musb->usb_lock);
		musb_set_vbus(mtk_musb,FALSE);
		/*
		opstate = musb_readb(mtk_musb->mregs,MUSB_OPSTATE);
		while(opstate != OTG_IDLE)
		{
			msleep(10);
			DBG(1,"wait OTG enter IDLE,opstate is %d\n",opstate);
			opstate = musb_readb(mtk_musb->mregs,MUSB_OPSTATE);
		}
		*/
        DBG(0,"musb_stop is called\n");
        //switch_int_to_host(); // move to musb_stop
		musb_stop(mtk_musb);

	}
	//mtk_musb->is_ready = is_ready;
out:
	DBG(0, "work end, is_host=%d\n", mtk_musb->is_host);
	up(&mtk_musb->musb_lock);

}
Beispiel #7
0
/* ================================ */
void connection_work(struct work_struct *data)
{
	struct musb *musb = container_of(to_delayed_work(data), struct musb, connection_work);
	static bool is_on = true;
	bool is_usb_cable = usb_cable_connected();

	os_printk(K_INFO, "%s musb %s, cable %s\n", __func__, (is_on?"ON":"OFF"), (is_usb_cable?"IN":"OUT"));

	if ((is_usb_cable == true) && (is_on == false) && (musb->usb_mode == CABLE_MODE_NORMAL)) {

		is_on = true;

		if (!wake_lock_active(&musb->usb_wakelock))
			wake_lock(&musb->usb_wakelock);

		/* FIXME: Should use usb_udc_start() & usb_gadget_connect(), like usb_udc_softconn_store().
		 * But have no time to think how to handle. However i think it is the correct way.*/
		musb_start(musb);

		os_printk(K_INFO, "%s ----Connect----\n", __func__);
	} else if (((is_usb_cable == false) && (is_on == true)) || (musb->usb_mode != CABLE_MODE_NORMAL)) {

		is_on = false;

		if (wake_lock_active(&musb->usb_wakelock))
			wake_unlock(&musb->usb_wakelock);

		/*FIXME: we should use usb_gadget_disconnect() & usb_udc_stop().  like usb_udc_softconn_store().
		 * But have no time to think how to handle. However i think it is the correct way.*/
		musb_stop(musb);

		os_printk(K_INFO, "%s ----Disconnect----\n", __func__);
	} else {
		/* This if-elseif is to set wakelock when booting with USB cable.
		 * Because battery driver does _NOT_ notify at this codition.*/
		if( (is_usb_cable == true) && !wake_lock_active(&musb->usb_wakelock)) {
			os_printk(K_INFO, "%s Boot wakelock\n", __func__);
			wake_lock(&musb->usb_wakelock);
		} else if( (is_usb_cable == false) && wake_lock_active(&musb->usb_wakelock)) {
			os_printk(K_INFO, "%s Boot unwakelock\n", __func__);
			wake_unlock(&musb->usb_wakelock);
		}

		os_printk(K_INFO, "%s directly return\n", __func__);
	}
}
Beispiel #8
0
int musb_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength)
{
	struct musb	*musb = hcd_to_musb(hcd);
	u32		temp;
	int		retval = 0;
	unsigned long	flags;

	spin_lock_irqsave(&musb->lock, flags);

	if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) {
		spin_unlock_irqrestore(&musb->lock, flags);
		return -ESHUTDOWN;
	}

	/* hub features:  always zero, setting is a NOP
	 * port features: reported, sometimes updated when host is active
	 * no indicators
	 */
	switch (typeReq) {
	case ClearHubFeature:
	case SetHubFeature:
		switch (wValue) {
		case C_HUB_OVER_CURRENT:
		case C_HUB_LOCAL_POWER:
			break;
		default:
			goto error;
		}
		break;
	case ClearPortFeature:
		if ((wIndex & 0xff) != 1)
			goto error;

		switch (wValue) {
		case USB_PORT_FEAT_ENABLE:
			break;
		case USB_PORT_FEAT_SUSPEND:
			musb_port_suspend(musb, false);
			break;
		case USB_PORT_FEAT_POWER:
			if (!hcd->self.is_b_host)
				musb_platform_set_vbus(musb, 0);
			break;
		case USB_PORT_FEAT_C_CONNECTION:
		case USB_PORT_FEAT_C_ENABLE:
		case USB_PORT_FEAT_C_OVER_CURRENT:
		case USB_PORT_FEAT_C_RESET:
		case USB_PORT_FEAT_C_SUSPEND:
			break;
		default:
			goto error;
		}
		dev_dbg(musb->controller, "clear feature %d\n", wValue);
		musb->port1_status &= ~(1 << wValue);
		break;
	case GetHubDescriptor:
		{
		struct usb_hub_descriptor *desc = (void *)buf;

		desc->bDescLength = 9;
		desc->bDescriptorType = 0x29;
		desc->bNbrPorts = 1;
		desc->wHubCharacteristics = cpu_to_le16(
				  0x0001	/* per-port power switching */
				| 0x0010	/* no overcurrent reporting */
				);
		desc->bPwrOn2PwrGood = 5;	/* msec/2 */
		desc->bHubContrCurrent = 0;

		/* workaround bogus struct definition */
		desc->u.hs.DeviceRemovable[0] = 0x02;	/* port 1 */
		desc->u.hs.DeviceRemovable[1] = 0xff;
		}
		break;
	case GetHubStatus:
		temp = 0;
		*(__le32 *) buf = cpu_to_le32(temp);
		break;
	case GetPortStatus:
		if (wIndex != 1)
			goto error;

		put_unaligned(cpu_to_le32(musb->port1_status
					& ~MUSB_PORT_STAT_RESUME),
				(__le32 *) buf);

		/* port change status is more interesting */
		dev_dbg(musb->controller, "port status %08x\n",
				musb->port1_status);
		break;
	case SetPortFeature:
		if ((wIndex & 0xff) != 1)
			goto error;

		switch (wValue) {
		case USB_PORT_FEAT_POWER:
			/* NOTE: this controller has a strange state machine
			 * that involves "requesting sessions" according to
			 * magic side effects from incompletely-described
			 * rules about startup...
			 *
			 * This call is what really starts the host mode; be
			 * very careful about side effects if you reorder any
			 * initialization logic, e.g. for OTG, or change any
			 * logic relating to VBUS power-up.
			 */
			if (!hcd->self.is_b_host && musb_has_gadget(musb))
				musb_start(musb);
			break;
		case USB_PORT_FEAT_RESET:
			musb_port_reset(musb, true);
			break;
		case USB_PORT_FEAT_SUSPEND:
			musb_port_suspend(musb, true);
			break;
		case USB_PORT_FEAT_TEST:
			if (unlikely(is_host_active(musb)))
				goto error;

			wIndex >>= 8;
			switch (wIndex) {
			case 1:
				pr_debug("TEST_J\n");
				temp = MUSB_TEST_J;
				break;
			case 2:
				pr_debug("TEST_K\n");
				temp = MUSB_TEST_K;
				break;
			case 3:
				pr_debug("TEST_SE0_NAK\n");
				temp = MUSB_TEST_SE0_NAK;
				break;
			case 4:
				pr_debug("TEST_PACKET\n");
				temp = MUSB_TEST_PACKET;
				musb_load_testpacket(musb);
				break;
			case 5:
				pr_debug("TEST_FORCE_ENABLE\n");
				temp = MUSB_TEST_FORCE_HOST
					| MUSB_TEST_FORCE_HS;

				musb_writeb(musb->mregs, MUSB_DEVCTL,
						MUSB_DEVCTL_SESSION);
				break;
			case 6:
				pr_debug("TEST_FIFO_ACCESS\n");
				temp = MUSB_TEST_FIFO_ACCESS;
				break;
			default:
				goto error;
			}
			musb_writeb(musb->mregs, MUSB_TESTMODE, temp);
			break;
		default:
			goto error;
		}
		dev_dbg(musb->controller, "set feature %d\n", wValue);
		musb->port1_status |= 1 << wValue;
		break;

	default:
error:
		/* "protocol stall" on error */
		retval = -EPIPE;
	}
	spin_unlock_irqrestore(&musb->lock, flags);
	return retval;
}
int musb_hub_control(
	struct usb_hcd	*hcd,
	u16		typeReq,
	u16		wValue,
	u16		wIndex,
	char		*buf,
	u16		wLength)
{
	struct musb	*musb = hcd_to_musb(hcd);
	u32		temp;
	int		retval = 0;
	unsigned long	flags;

	spin_lock_irqsave(&musb->lock, flags);

	if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
		spin_unlock_irqrestore(&musb->lock, flags);
		return -ESHUTDOWN;
	}

	/* hub features:  always zero, setting is a NOP
	 * port features: reported, sometimes updated when host is active
	 * no indicators
	 */
	switch (typeReq) {
	case ClearHubFeature:
	case SetHubFeature:
		switch (wValue) {
		case C_HUB_OVER_CURRENT:
		case C_HUB_LOCAL_POWER:
			break;
		default:
			goto error;
		}
		break;
	case ClearPortFeature:
		if ((wIndex & 0xff) != 1)
			goto error;

		switch (wValue) {
		case USB_PORT_FEAT_ENABLE:
			break;
		case USB_PORT_FEAT_SUSPEND:
			musb_port_suspend(musb, false);
			break;
		case USB_PORT_FEAT_POWER:
			if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
				musb_set_vbus(musb, 0);
			break;
		case USB_PORT_FEAT_C_CONNECTION:
		case USB_PORT_FEAT_C_ENABLE:
		case USB_PORT_FEAT_C_OVER_CURRENT:
		case USB_PORT_FEAT_C_RESET:
		case USB_PORT_FEAT_C_SUSPEND:
			break;
		default:
			goto error;
		}
		DBG(5, "clear feature %d\n", wValue);
		musb->port1_status &= ~(1 << wValue);
		break;
	case GetHubDescriptor:
		{
		struct usb_hub_descriptor *desc = (void *)buf;

		desc->bDescLength = 9;
		desc->bDescriptorType = 0x29;
		desc->bNbrPorts = 1;
		desc->wHubCharacteristics = cpu_to_le16(
				  0x0001	/* per-port power switching */
				| 0x0010	/* no overcurrent reporting */
				);
		desc->bPwrOn2PwrGood = 5;	/* msec/2 */
		desc->bHubContrCurrent = 0;

		/* workaround bogus struct definition */
		desc->DeviceRemovable[0] = 0x02;	/* port 1 */
		desc->DeviceRemovable[1] = 0xff;
		}
		break;
	case GetHubStatus:
		temp = 0;
		*(__le32 *) buf = cpu_to_le32(temp);
		break;
	case GetPortStatus:
		if (wIndex != 1)
			goto error;

		/* finish RESET signaling? */
		if ((musb->port1_status & USB_PORT_STAT_RESET)
				&& time_after_eq(jiffies, musb->rh_timer))
			musb_port_reset(musb, false);

		/* finish RESUME signaling? */
		if ((musb->port1_status & MUSB_PORT_STAT_RESUME)
				&& time_after_eq(jiffies, musb->rh_timer)) {
			u8		power;

			power = musb_readb(musb->mregs, MUSB_POWER);
			power &= ~MUSB_POWER_RESUME;
			DBG(4, "root port resume stopped, power %02x\n",
					power);
			musb_writeb(musb->mregs, MUSB_POWER, power);

			/* ISSUE:  DaVinci (RTL 1.300) disconnects after
			 * resume of high speed peripherals (but not full
			 * speed ones).
			 */

			musb->is_active = 1;
			musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
					| MUSB_PORT_STAT_RESUME);
			musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
			usb_hcd_poll_rh_status(musb_to_hcd(musb));
			/* NOTE: it might really be A_WAIT_BCON ... */
			musb->xceiv->state = OTG_STATE_A_HOST;
		}

		put_unaligned(cpu_to_le32(musb->port1_status
					& ~MUSB_PORT_STAT_RESUME),
				(__le32 *) buf);

		/* port change status is more interesting */
		DBG(get_unaligned((u16 *)(buf+2)) ? 2 : 5, "port status %08x\n",
				musb->port1_status);
		break;
	case SetPortFeature:
		if ((wIndex & 0xff) != 1)
			goto error;

		switch (wValue) {
		case USB_PORT_FEAT_POWER:
			/* NOTE: this controller has a strange state machine
			 * that involves "requesting sessions" according to
			 * magic side effects from incompletely-described
			 * rules about startup...
			 *
			 * This call is what really starts the host mode; be
			 * very careful about side effects if you reorder any
			 * initialization logic, e.g. for OTG, or change any
			 * logic relating to VBUS power-up.
			 */
			if (!(is_otg_enabled(musb) && hcd->self.is_b_host))
				musb_start(musb);
			break;
		case USB_PORT_FEAT_RESET:
			musb_port_reset(musb, true);
			break;
		case USB_PORT_FEAT_SUSPEND:
			musb_port_suspend(musb, true);
			break;
		case USB_PORT_FEAT_TEST:
			wIndex >>= 8;
			switch (wIndex) {
			case 1:
				pr_debug("TEST_J\n");
				temp = MUSB_TEST_J;
				break;
			case 2:
				pr_debug("TEST_K\n");
				temp = MUSB_TEST_K;
				break;
			case 3:
				pr_debug("TEST_SE0_NAK\n");
				temp = MUSB_TEST_SE0_NAK;
				break;
			case 4:
				pr_debug("TEST_PACKET\n");
				temp = MUSB_TEST_PACKET;
				musb_load_testpacket(musb);
				break;
			case 5:
				pr_debug("TEST_FORCE_ENABLE\n");
				temp = MUSB_TEST_FORCE_HOST
					| MUSB_TEST_FORCE_HS;

				musb_writeb(musb->mregs, MUSB_DEVCTL,
						MUSB_DEVCTL_SESSION);
				break;
			case 6:
				pr_debug("TEST_FIFO_ACCESS\n");
				temp = MUSB_TEST_FIFO_ACCESS;
				break;
			default:
				goto error;
			}
			musb_writeb(musb->mregs, MUSB_TESTMODE, temp);
			break;
		default:
			goto error;
		}
		DBG(5, "set feature %d\n", wValue);
		musb->port1_status |= 1 << wValue;
		break;

	default:
error:
		/* "protocol stall" on error */
		retval = -EPIPE;
	}
	spin_unlock_irqrestore(&musb->lock, flags);
	return retval;
}
Beispiel #10
0
static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
{
	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;
	unsigned long	flags;
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
	int ret = 0;
#endif

	kfree(otg_work);

	switch (xceiv_event) {
	case USB_EVENT_ID:
		dev_info(musb->controller, "ID GND\n");
		musb->xceiv->state = OTG_STATE_A_IDLE;
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
		ret = omap2430_async_resume(musb);
		if (ret < 0)
			return;
#endif
		if (is_otg_enabled(musb)) {
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
			if (musb->gadget_driver) {
				musb_otg_init(musb);
			}
#endif
		} else {
			musb_otg_init(musb);
		}
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
		musb_add_hcd(musb);
#endif
		break;
	case USB_EVENT_VBUS_CHARGER:
		dev_info(musb->controller, "USB/TA Connect\n");
		/*  This event received from ta_connect_irq
		 * when a usb cable is connected. Logic has still
		 * not identified whether this is a usb cable or TA.
		 *  So just break here.
		 */
		break;
	case USB_EVENT_VBUS:
		dev_info(musb->controller, "VBUS Connect\n");
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
		ret = omap2430_async_resume(musb);
		if (ret < 0)
			return;
#endif
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
		if (musb->gadget_driver)
			pm_runtime_get_sync(musb->controller);
#endif
		otg_init(musb->xceiv);
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
		musb_start(musb);
		musb_platform_pullup(musb, 1);
#endif
		break;

	case USB_EVENT_CHARGER:
		dev_info(musb->controller, "Dedicated charger connect\n");
		musb->is_ac_charger = true;
		break;
	case USB_EVENT_HOST_NONE:
#ifdef CONFIG_USB_SAMSUNG_OMAP_NORPM
		dev_info(musb->controller, "USB host Disconnect. ID float\n");
		if (!omap2430_async_resumed(musb)) {
			dev_err(musb->controller, "async suspended. abnormal state.\n");
			return;
		}
		musb_stop(musb);
		musb_remove_hcd(musb);
		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);
		musb_otg_core_reset(musb);
		ret = omap2430_async_suspend(musb);
		if (ret < 0)
			return;
		break;
#endif
	case USB_EVENT_NONE:
		if (musb->is_ac_charger) {
			dev_info(musb->controller,
				"Dedicated charger disconnect\n");
			musb->is_ac_charger = false;
			break;
		}

		dev_info(musb->controller, "VBUS Disconnect\n");
#ifndef CONFIG_USB_SAMSUNG_OMAP_NORPM
		if (pm_runtime_suspended(musb->controller)) {
			dev_err(musb->controller, "runtime pm suspended. abnormal state.\n");
			return;
		}
		spin_lock_irqsave(&musb->lock, flags);
		musb_g_disconnect(musb);
		spin_unlock_irqrestore(&musb->lock, flags);

#ifdef CONFIG_USB_GADGET_MUSB_HDRC
		if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
			if (musb->gadget_driver)
#endif
			{
				pm_runtime_mark_last_busy(musb->controller);
				pm_runtime_put_autosuspend(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);
#else
		if (!omap2430_async_resumed(musb)) {
			dev_err(musb->controller, "async suspended. abnormal state.\n");
			return;
		}
		musb_platform_pullup(musb, 0);
		spin_lock_irqsave(&musb->lock, flags);
		musb_stop(musb);
		musb_g_disconnect(musb);
		musb_all_ep_flush(musb);
		spin_unlock_irqrestore(&musb->lock, flags);
		if (data->interface_type == MUSB_INTERFACE_UTMI)
			omap2430_musb_set_vbus(musb, 0);
		otg_shutdown(musb->xceiv);
		musb_otg_core_reset(musb);
		ret = omap2430_async_suspend(musb);
		if (ret < 0)
			return;
#endif
		break;
	default:
		dev_info(musb->controller, "ID float\n");
	}
}
Beispiel #11
0
static void musb_id_pin_work(struct work_struct *data)
{
    u8 devctl = 0;
    unsigned long flags;

    spin_lock_irqsave(&mtk_musb->lock, flags);
    musb_generic_disable(mtk_musb);
    spin_unlock_irqrestore(&mtk_musb->lock, flags);

	down(&mtk_musb->musb_lock);
	DBG(0, "work start, is_host=%d\n", mtk_musb->is_host);
	if(mtk_musb->in_ipo_off) {
		DBG(0, "do nothing due to in_ipo_off\n");
		goto out;
	}

	mtk_musb ->is_host = musb_is_host();
	DBG(0,"musb is as %s\n",mtk_musb->is_host?"host":"device");
	switch_set_state((struct switch_dev *)&otg_state, mtk_musb->is_host);

	if (mtk_musb->is_host) {
		//setup fifo for host mode
		ep_config_from_table_for_host(mtk_musb);
		wake_lock(&mtk_musb->usb_lock);
		musb_platform_set_vbus(mtk_musb, 1);

        /* for no VBUS sensing IP*/
        #if 1
		/* wait VBUS ready */
		msleep(100);
		/* clear session*/
		devctl = musb_readb(mtk_musb->mregs,MUSB_DEVCTL);
		musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, (devctl&(~MUSB_DEVCTL_SESSION)));
		/* USB MAC OFF*/
		/* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X */
		USBPHY_SET8(0x6c, 0x10);
		USBPHY_CLR8(0x6c, 0x2e);
		USBPHY_SET8(0x6d, 0x3e);
		DBG(0,"force PHY to idle, 0x6d=%x, 0x6c=%x\n",USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
		/* wait */
		msleep(5);
		/* restart session */
		devctl = musb_readb(mtk_musb->mregs,MUSB_DEVCTL);
		musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, (devctl| MUSB_DEVCTL_SESSION));
		/* USB MAC ONand Host Mode*/
		/* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=0 */
		USBPHY_CLR8(0x6c, 0x10);
		USBPHY_SET8(0x6c, 0x2c);
		USBPHY_SET8(0x6d, 0x3e);
		DBG(0,"force PHY to host mode, 0x6d=%x, 0x6c=%x\n",USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
        #endif

		musb_start(mtk_musb);
		MUSB_HST_MODE(mtk_musb);
		switch_int_to_device(mtk_musb);
	} else {
		DBG(0,"devctl is %x\n",musb_readb(mtk_musb->mregs,MUSB_DEVCTL));
		musb_writeb(mtk_musb->mregs,MUSB_DEVCTL,0);
		if (wake_lock_active(&mtk_musb->usb_lock))
			wake_unlock(&mtk_musb->usb_lock);
		musb_platform_set_vbus(mtk_musb, 0);

        /* for no VBUS sensing IP */
        #if 1
        /* USB MAC OFF*/
		/* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X */
		USBPHY_SET8(0x6c, 0x10);
		USBPHY_CLR8(0x6c, 0x2e);
		USBPHY_SET8(0x6d, 0x3e);
		DBG(0,"force PHY to idle, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
        #endif

		musb_stop(mtk_musb);
		//ALPS00849138
		mtk_musb->xceiv->state =  OTG_STATE_B_IDLE;
		MUSB_DEV_MODE(mtk_musb);
		switch_int_to_host(mtk_musb);
	}
out:
	DBG(0, "work end, is_host=%d\n", mtk_musb->is_host);
	up(&mtk_musb->musb_lock);

}
 /* blocking notifier support */
void cpcap_musb_notifier_call(unsigned long event)
{
	struct musb	*musb = g_musb;
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *pdata = dev->platform_data;
	struct omap_musb_board_data *data = pdata->board_data;
	static int hostmode;
	u32 val;
	u8 power;

	switch (event) {
	case USB_EVENT_ID:
		DBG(1, "ID GND\n");

		/* configure musb into smartidle with wakeup enabled
		 * smart standby mode.
		 */

		omap_pm_set_max_mpu_wakeup_lat(&pdata->musb_qos_request, 4000);

		musb_writel(musb->mregs, OTG_FORCESTDBY, 0);
		val = musb_readl(musb->mregs, OTG_SYSCONFIG);
		if (cpu_is_omap44xx())
			val |= SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP;
		else
			val |= SMARTIDLE | SMARTSTDBY | ENABLEWAKEUP;
		musb_writel(musb->mregs, OTG_SYSCONFIG, val);

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			phy_init();
			otg_init(musb->xceiv);
			/* enable VBUS valid, id groung*/
			__raw_writel(AVALID | VBUSVALID, ctrl_base +
							USBOTGHS_CONTROL);
			val = __raw_readl(phymux_base +
					USBA0_OTG_CE_PAD1_USBA0_OTG_DP);

			val |= DP_WAKEUPENABLE;
			__raw_writel(val, phymux_base +
						USBA0_OTG_CE_PAD1_USBA0_OTG_DP);
		}

		hostmode = 1;
		musb_start(musb);
		musb_set_vbus(musb, 1);

		break;

	case USB_EVENT_VBUS:
		DBG(1, "VBUS Connect\n");

		/* configure musb into smartidle with wakeup enabled
		 * smart standby mode.
		 */
		musb_writel(musb->mregs, OTG_FORCESTDBY, 0);
		val = musb_readl(musb->mregs, OTG_SYSCONFIG);
		if (cpu_is_omap44xx())
			val |= SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP;
		else
			val |= SMARTIDLE | SMARTSTDBY | ENABLEWAKEUP;
		musb_writel(musb->mregs, OTG_SYSCONFIG, val);

		power = musb_readb(musb->mregs, MUSB_POWER);
		power &= ~MUSB_POWER_SOFTCONN;
		musb_writeb(musb->mregs, MUSB_POWER, power);


		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			phy_init();
			otg_init(musb->xceiv);
			if (!hostmode) {
				/* Enable VBUS Valid, AValid. Clear SESSEND.*/
				__raw_writel(IDDIG | AVALID | VBUSVALID,
					ctrl_base + USBOTGHS_CONTROL);
			}
		}

		break;

	case USB_EVENT_NONE:
		DBG(1, "VBUS Disconnect\n");

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			/* enable this clock because in suspend interrupt
			 * handler phy clocks are disabled. If phy clocks are
			 * not enabled then DISCONNECT interrupt will not be
			 * reached to mentor
			 */
			otg_set_clk(musb->xceiv, 1);
			__raw_writel(SESSEND | IDDIG, ctrl_base +
							USBOTGHS_CONTROL);
			if (musb->xceiv->set_vbus)
				otg_set_vbus(musb->xceiv, 0);
			otg_shutdown(musb->xceiv);
			phy_shutdown();
		}
		/* configure in force idle/ standby */
		musb_writel(musb->mregs, OTG_FORCESTDBY, 1);
		val = musb_readl(musb->mregs, OTG_SYSCONFIG);
		val &= ~(SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP);
		val |= FORCEIDLE | FORCESTDBY;
		musb_writel(musb->mregs, OTG_SYSCONFIG, val);

		omap_pm_set_max_mpu_wakeup_lat(&pdata->musb_qos_request, -1);

		if (data->interface_type == MUSB_INTERFACE_UTMI) {
			val = __raw_readl(phymux_base +
					USBA0_OTG_CE_PAD1_USBA0_OTG_DP);

			val &= ~DP_WAKEUPENABLE;
			__raw_writel(val, phymux_base +
						USBA0_OTG_CE_PAD1_USBA0_OTG_DP);
		}

		if (hostmode) {
			musb_stop(musb);
			musb_set_vbus(musb, 0);
		}
		hostmode = 0;
		break;
	default:
		DBG(1, "ID float\n");
	}

}