static irqreturn_t usb_detect_handler(int irq, void *dev_id)
{
	struct gadget_wrapper *d;
	int value = 0;

#ifndef DWC_DEVICE_ONLY
	/*
	 *if otg cable is connected , id state =0
	 *as host turn on vbus, in this case shouldn't call this handler
	 */
	if(!usb_get_id_state())
		return IRQ_HANDLED;
#endif
	d = gadget_wrapper;
	if (d->driver == NULL) {
		pr_info("too early, no gadget drive\n");
		return IRQ_HANDLED;
	}

	value = usb_get_vbus_state();
	if (value){
		pr_debug("usb detect plug in\n");
		usb_set_vbus_irq_type(irq, VBUS_PLUG_OUT);
	} else {
		pr_debug("usb detect plug out\n");
		usb_set_vbus_irq_type(irq, VBUS_PLUG_IN);
	}

	d->vbus = value;
	queue_work(d->detect_wq, &d->detect_work);

	return IRQ_HANDLED;
}
static irqreturn_t usb_detect_handler(int irq, void *dev_id)
{
	struct gadget_wrapper *d;
	int value = 0;

	d = gadget_wrapper;
	if (d->driver == NULL) {
		pr_info("too early, no gadget drive\n");
		return IRQ_HANDLED;
	}

	value = usb_get_vbus_state();
	if (value){
		charger_plug_flag = 1;
		pr_debug("usb detect plug in\n");
		usb_set_vbus_irq_type(irq, VBUS_PLUG_OUT);
	} else {
		charger_plug_flag = 0;
		pr_debug("usb detect plug out\n");
		usb_set_vbus_irq_type(irq, VBUS_PLUG_IN);
	}

	d->vbus = value;
	queue_work(d->detect_wq, &d->detect_work);

	return IRQ_HANDLED;
}
/**
 * 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;
}
Example #4
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;
}