static void cable2pc_detect_works(struct work_struct *work)
{
	int usb_cable;
	static int reenum_cnt = REENUM_CNT;
	struct gadget_wrapper *d;
	d = gadget_wrapper;
	usb_cable = cable_is_usb();

	/* in factory mode, we know the cable must be usb, so we enumerate
	 * again
	 */
	if (in_factory_mode() && !usb_cable && reenum_cnt){
		pr_info("try usb enumertation again\n");
		reenum_cnt--;
		mutex_lock(&udc_lock);
		__udc_shutdown();
		queue_delayed_work(d->cable2pc_wq, &d->cable2pc,CABLE_TIMEOUT);
		__udc_startup();
		mutex_unlock(&udc_lock);
		return;
	}

	mutex_lock(&udc_lock);
	if (!usb_cable) {
		pr_info("cable is ac adapter\n");
		__udc_shutdown();
	}
	mutex_unlock(&udc_lock);
	return;
}
static void cable_detect_handler(unsigned long data)
{
	int usb_cable;
	static int reenum_cnt = REENUM_CNT;
	usb_cable = cable_is_usb();

	/* in factory mode, we know the cable must be usb, so we enumerate
	 * again
	 */
	if (in_factory_mode() && !usb_cable && reenum_cnt){
		pr_info("try usb enumertation again\n");
		reenum_cnt--;
		mutex_lock(&udc_lock);
		__udc_shutdown();
		mod_timer(&gadget_wrapper->cable_timer, jiffies +
				CABLE_TIMEOUT);
		__udc_startup();
		mutex_unlock(&udc_lock);
		return;
	}

	mutex_lock(&udc_lock);
	if (!usb_cable) {
		pr_info("cable is ac adapter\n");
		__udc_shutdown();
	}
	mutex_unlock(&udc_lock);
	return;
}
static void usb_detect_works(struct work_struct *work)
{
	struct gadget_wrapper *d;
	unsigned long flags;
	int plug_in;

	d = gadget_wrapper;

	spin_lock_irqsave(&d->lock, flags);
	plug_in = d->vbus;
	spin_unlock_irqrestore(&d->lock, flags);

	mutex_lock(&udc_lock);
	if (plug_in){
		pr_info("usb detect plug in,vbus pull up\n");
		hotplug_callback(VBUS_PLUG_IN, 0);
		if(get_usb_first_enable_store_flag()){ 
		mod_timer(&d->cable_timer, jiffies + CABLE_TIMEOUT);
		__udc_startup();
 		} 
	} else {
		pr_info("usb detect plug out,vbus pull down\n");
		del_timer(&d->cable_timer);
		__udc_shutdown();
		hotplug_callback(VBUS_PLUG_OUT, cable_is_usb());
	}
	mutex_unlock(&udc_lock);
	switch_set_state(&d->sdev, !!plug_in);
}
Esempio n. 4
0
static int pullup(struct usb_gadget *gadget, int is_on)
{
	struct gadget_wrapper *d;
	int action = is_on;

#ifndef DWC_DEVICE_ONLY	
	if(!usb_get_id_state())
		return 0;
#endif
	if (gadget == 0)
		return -ENODEV;
	else
		d = container_of(gadget, struct gadget_wrapper, gadget);
	d->softconnect = is_on;
#ifdef CONFIG_USB_EXTERNAL_DETECT
	if (!d->enabled || !d->vbus)
	{
		printk("usb: %s, d->enable = %d,  d->vbus=%d \r\n",__func__, d->enabled, d->vbus);
		return 0;
	}
	mutex_lock(&udc_lock);
	if (action) {
		__udc_startup();
	} else {
		__udc_shutdown();
	}
	mutex_unlock(&udc_lock);
#else
	if (!d->enabled || !d->vbus)
		action = 0;

	mutex_lock(&udc_lock);
	if (action) {
		queue_delayed_work(d->cable2pc_wq, &d->cable2pc,CABLE_TIMEOUT);
		__udc_startup();
	} else {
		/*
		 *this is soft disconnct, and maybe the timer started
		 *by plugin still work, need cancel this timer like plugout
		 */
		cancel_delayed_work_sync(&d->cable2pc);
		__udc_shutdown();
	}
	mutex_unlock(&udc_lock);
#endif
	return 0;
}
static int pullup(struct usb_gadget *gadget, int is_on)
{
	struct gadget_wrapper *d;
	int action = is_on;

	if (gadget == 0)
		return -ENODEV;
	else
		d = container_of(gadget, struct gadget_wrapper, gadget);

	if (is_on) {
		static int enum_enabled = 0;
		if (unlikely(!enum_enabled)) {
			enum_enabled = 1;
			enumeration_enable();
		//	return 0;
		}
	}
	if (!d->enabled || !d->vbus)
		action = 0;

	mutex_lock(&udc_lock);
	if (action) {
		mod_timer(&d->cable_timer, jiffies + CABLE_TIMEOUT);
		__udc_startup();
	} else {
		/*
		 *this is soft disconnct, and maybe the timer started
		 *by plugin still work, need cancel this timer like plugout
		 */
		if(timer_pending(&d->cable_timer))
			del_timer(&d->cable_timer);
		__udc_shutdown();
	}
	mutex_unlock(&udc_lock);

	return 0;
}
static int pullup(struct usb_gadget *gadget, int is_on)
{
	struct gadget_wrapper *d;
	int action = is_on;

#ifndef DWC_DEVICE_ONLY	
	if(!usb_get_id_state())
		return 0;
#endif
	if (gadget == 0)
		return -ENODEV;
	else
		d = container_of(gadget, struct gadget_wrapper, gadget);

#ifdef CONFIG_USB_INTERRUPT_BY_MUIC	// need to check vbus again
	if (!d->enabled)
		action = 0;
#else
	if (!d->enabled || !d->vbus)
		action = 0;
#endif

	mutex_lock(&udc_lock);
	if (action) {
		queue_delayed_work(d->cable2pc_wq, &d->cable2pc,CABLE_TIMEOUT);
		__udc_startup();
	} else {
		/*
		 *this is soft disconnct, and maybe the timer started
		 *by plugin still work, need cancel this timer like plugout
		 */
		cancel_delayed_work_sync(&d->cable2pc);
		__udc_shutdown();
	}
	mutex_unlock(&udc_lock);

	return 0;
}
/**
 * This function initialized the PCD portion of the driver.
 *
 */
int pcd_init(
	struct platform_device *_dev
	)
{
	dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
	int retval = 0;
	int irq;

	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);

	wake_lock_init(&usb_wake_lock, WAKE_LOCK_SUSPEND, "usb_work");
	otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);

	if (!otg_dev->pcd) {
		DWC_ERROR("dwc_otg_pcd_init failed\n");
		return -ENOMEM;
	}

	gadget_wrapper = alloc_wrapper(_dev);

	/*
	 * Initialize EP structures
	 */
	gadget_add_eps(gadget_wrapper);

	/*
	 * Setup interupt handler
	 */
	irq = platform_get_irq(_dev, 0);
	DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", irq);
	retval = request_irq(irq, dwc_otg_pcd_irq,
			0, gadget_wrapper->gadget.name,
			otg_dev->pcd);
	//SA_SHIRQ, gadget_wrapper->gadget.name,
	if (retval != 0) {
		DWC_ERROR("request of irq%d failed\n", irq);
		free_wrapper(gadget_wrapper);
		return -EBUSY;
	}
	/*
	 * initialize a timer for checking cable type.
	 */
	{
		setup_timer(&setup_transfer_timer,setup_transfer_timer_fun,(unsigned long)gadget_wrapper);
		setup_transfer_timer_start = 0;
	}
	setup_timer(&gadget_wrapper->cable_timer, cable_detect_handler,
			(unsigned long)gadget_wrapper);
	/*
	 * setup usb cable detect interupt
	 */
	{
		int plug_irq;
		plug_irq = usb_alloc_vbus_irq();
		if (plug_irq < 0) {
			pr_warning("cannot alloc vbus irq\n");
			return -EBUSY;
		}
		usb_set_vbus_irq_type(plug_irq, VBUS_PLUG_IN);
		gadget_wrapper->vbus = usb_get_vbus_state();
		pr_info("now usb vbus is :%d\n", gadget_wrapper->vbus);
		retval = request_irq(plug_irq, usb_detect_handler, IRQF_SHARED,
				"usb detect", otg_dev->pcd);
	}
	spin_lock_init(&gadget_wrapper->lock);

	INIT_WORK(&gadget_wrapper->detect_work, usb_detect_works);
	gadget_wrapper->detect_wq = create_singlethread_workqueue("usb detect wq");
	/*
	 * register a switch device for sending pnp message,
	 * for the user app need be notified immediately
	 * when plug in & plug out happen;
	 */
	gadget_wrapper->sdev.name = "charger_cable";
	retval = switch_dev_register(&gadget_wrapper->sdev);
	if (retval){
		pr_warning("register switch dev error:%s\n", __func__);
	}

	dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);

	/*
	 * dwc driver is ok, check if the cable is insert, if no,
	 * shutdown udc for saving power.
	 */
	if (!gadget_wrapper->vbus){
		pr_debug("vbus is not power now \n");
		gadget_wrapper->udc_startup = 1;
		__udc_shutdown();
	}
	gadget_wrapper->udc_startup = gadget_wrapper->vbus;
	gadget_wrapper->enabled = 0;

	return retval;
}
void dwc_udc_shutdown(void)
{
	mutex_lock(&udc_lock);
	__udc_shutdown();
	mutex_unlock(&udc_lock);
}
Esempio n. 9
0
/**
 * This function initialized the PCD portion of the driver.
 *
 */
int pcd_init(
	struct platform_device *_dev
	)
{
	dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
	struct sprd_usb_platform_data *pdata= _dev->dev.platform_data;
	int retval = 0;
	int irq;
	int plug_irq;

	DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);

	device_dwc_otg = &(_dev->dev);
	if (dwc_otg_is_dma_enable(otg_dev->core_if)) {
		_dev->dev.dma_mask = &dwc_otg_pcd_dmamask;
		_dev->dev.coherent_dma_mask = dwc_otg_pcd_dmamask;
	} else {
		_dev->dev.dma_mask = (void *)0;
		_dev->dev.coherent_dma_mask = 0;
	}

	wake_lock_init(&usb_wake_lock, WAKE_LOCK_SUSPEND, "usb_work");
//	wake_lock(&usb_wake_lock);
	otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);

	if (!otg_dev->pcd) {
		DWC_ERROR("dwc_otg_pcd_init failed\n");
		return -ENOMEM;
	}

	gadget_wrapper = alloc_wrapper(_dev);

	/*
	 * Initialize EP structures
	 */
	gadget_add_eps(gadget_wrapper);

	/*
	 * Setup interupt handler
	 */
	irq = platform_get_irq(_dev, 0);
	DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", irq);
	retval = request_irq(irq, dwc_otg_pcd_irq,
			IRQF_SHARED, gadget_wrapper->gadget.name,
			otg_dev->pcd);
	//SA_SHIRQ, gadget_wrapper->gadget.name,
	if (retval != 0) {
		DWC_ERROR("request of irq%d failed\n", irq);
		free_wrapper(gadget_wrapper);
		return -EBUSY;
	}
	/*
	 * initialize a timer for checking cable type.
	 */
#ifdef USB_SETUP_TIMEOUT_RESTART
	{
		setup_timer(&setup_transfer_timer,
			setup_transfer_timer_fun,
			(unsigned long)gadget_wrapper);
		setup_transfer_timer_start = 0;
	}
#endif
	INIT_DELAYED_WORK(&gadget_wrapper->cable2pc, cable2pc_detect_works);
	gadget_wrapper->cable2pc_wq = create_singlethread_workqueue("usb 2 pc wq");

#ifdef CONFIG_USB_EXTERNAL_DETECT
	register_otg_func(NULL, dwc_peripheral_start, otg_dev);
#else

	/*
	 * setup usb cable detect interupt
	 */
#ifndef CONFIG_MFD_SM5504
	{
		plug_irq = usb_alloc_vbus_irq(pdata->gpio_chgdet);
		if (plug_irq < 0) {
			pr_warning("cannot alloc vbus irq\n");
			return -EBUSY;
		}
		usb_set_vbus_irq_type(plug_irq, VBUS_PLUG_IN);
		#ifdef CONFIG_SC_FPGA
		gadget_wrapper->vbus = 1;
		#else
		gadget_wrapper->vbus = usb_get_vbus_state();
		#endif
		pr_info("now usb vbus is :%d\n", gadget_wrapper->vbus);
		retval = request_irq(plug_irq, usb_detect_handler, IRQF_SHARED | IRQF_NO_SUSPEND,
				"usb detect", otg_dev->pcd);
#ifndef CONFIG_MUIC_CABLE_DETECT
		disable_irq(plug_irq);
#endif
	}
	//gadget_wrapper->vbus = 1;//used when debug in FPGA, which doesn't have vbus operation
#endif
	spin_lock_init(&gadget_wrapper->lock);
#ifdef CONFIG_SC_FPGA
	gadget_wrapper->vbus = 1;
#endif
	INIT_WORK(&gadget_wrapper->detect_work, usb_detect_works);
	gadget_wrapper->detect_wq = create_singlethread_workqueue("usb detect wq");
#endif
	/*
	 * register a switch device for sending pnp message,
	 * for the user app need be notified immediately
	 * when plug in & plug out happen;
	 */
	gadget_wrapper->sdev.name = "charger_cable";
	retval = switch_dev_register(&gadget_wrapper->sdev);
	if (retval){
		pr_warning("register switch dev error:%s\n", __func__);
	}

	dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);

	/*
	 * dwc driver is ok, check if the cable is insert, if no,
	 * shutdown udc for saving power.
	 */
	if (!gadget_wrapper->vbus){
		pr_debug("vbus is not power now \n");
		gadget_wrapper->udc_startup = 1;
		__udc_shutdown();
	}
	gadget_wrapper->udc_startup = gadget_wrapper->vbus;
	gadget_wrapper->enabled = 0;

	retval = usb_add_gadget_udc(&_dev->dev, &gadget_wrapper->gadget);
	if (!retval)
		return retval;

	return retval;
}