static void mv_otg_disable(struct mv_otg *mvotg)
{
	if (mvotg->clock_gating)
		mv_otg_disable_internal(mvotg);

	pm_qos_update_request(&mvotg->qos_idle,
		PM_QOS_CPUIDLE_BLOCK_DEFAULT_VALUE);

	pm_relax(&mvotg->pdev->dev);
}
static int mv_otg_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct mv_otg *mvotg = platform_get_drvdata(pdev);

	if (mvotg->phy.state != OTG_STATE_B_IDLE) {
		dev_info(&pdev->dev,
			 "OTG state is not B_IDLE, it is %d!\n",
			 mvotg->phy.state);
		return -EAGAIN;
	}

	if (!mvotg->clock_gating)
		mv_otg_disable_internal(mvotg);

	return 0;
}
static int mv_otg_probe(struct platform_device *pdev)
{
	struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev);
	struct mv_otg *mvotg;
	struct usb_otg *otg;
	struct resource *r;
	int retval = 0, i;

	if (pdata == NULL) {
		dev_err(&pdev->dev, "failed to get platform data\n");
		return -ENODEV;
	}

	mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
	if (!mvotg) {
		dev_err(&pdev->dev, "failed to allocate memory!\n");
		return -ENOMEM;
	}

	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
	if (!otg)
		return -ENOMEM;

	platform_set_drvdata(pdev, mvotg);

	mvotg->pdev = pdev;
	mvotg->pdata = pdata;

	mvotg->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(mvotg->clk))
		return PTR_ERR(mvotg->clk);

	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
	if (!mvotg->qwork) {
		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
		return -ENOMEM;
	}

	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);

	/* OTG common part */
	mvotg->pdev = pdev;
	mvotg->phy.dev = &pdev->dev;
	mvotg->phy.otg = otg;
	mvotg->phy.label = driver_name;
	mvotg->phy.state = OTG_STATE_UNDEFINED;

	otg->phy = &mvotg->phy;
	otg->set_host = mv_otg_set_host;
	otg->set_peripheral = mv_otg_set_peripheral;
	otg->set_vbus = mv_otg_set_vbus;

	for (i = 0; i < OTG_TIMER_NUM; i++)
		init_timer(&mvotg->otg_ctrl.timer[i]);

	r = platform_get_resource_byname(mvotg->pdev,
					 IORESOURCE_MEM, "phyregs");
	if (r == NULL) {
		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
		retval = -ENODEV;
		goto err_destroy_workqueue;
	}

	mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
	if (mvotg->phy_regs == NULL) {
		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
		retval = -EFAULT;
		goto err_destroy_workqueue;
	}

	r = platform_get_resource_byname(mvotg->pdev,
					 IORESOURCE_MEM, "capregs");
	if (r == NULL) {
		dev_err(&pdev->dev, "no I/O memory resource defined\n");
		retval = -ENODEV;
		goto err_destroy_workqueue;
	}

	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
	if (mvotg->cap_regs == NULL) {
		dev_err(&pdev->dev, "failed to map I/O memory\n");
		retval = -EFAULT;
		goto err_destroy_workqueue;
	}

	/* we will acces controller register, so enable the udc controller */
	retval = mv_otg_enable_internal(mvotg);
	if (retval) {
		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
		goto err_destroy_workqueue;
	}

	mvotg->op_regs =
		(struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));

	if (pdata->id) {
		retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
						NULL, mv_otg_inputs_irq,
						IRQF_ONESHOT, "id", mvotg);
		if (retval) {
			dev_info(&pdev->dev,
				 "Failed to request irq for ID\n");
			pdata->id = NULL;
		}
	}

	if (pdata->vbus) {
		mvotg->clock_gating = 1;
		retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
						NULL, mv_otg_inputs_irq,
						IRQF_ONESHOT, "vbus", mvotg);
		if (retval) {
			dev_info(&pdev->dev,
				 "Failed to request irq for VBUS, "
				 "disable clock gating\n");
			mvotg->clock_gating = 0;
			pdata->vbus = NULL;
		}
	}

	if (pdata->disable_otg_clock_gating)
		mvotg->clock_gating = 0;

	mv_otg_reset(mvotg);
	mv_otg_init_irq(mvotg);

	r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0);
	if (r == NULL) {
		dev_err(&pdev->dev, "no IRQ resource defined\n");
		retval = -ENODEV;
		goto err_disable_clk;
	}

	mvotg->irq = r->start;
	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
			driver_name, mvotg)) {
		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
			mvotg->irq);
		mvotg->irq = 0;
		retval = -ENODEV;
		goto err_disable_clk;
	}

	retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
	if (retval < 0) {
		dev_err(&pdev->dev, "can't register transceiver, %d\n",
			retval);
		goto err_disable_clk;
	}

	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
	if (retval < 0) {
		dev_dbg(&pdev->dev,
			"Can't register sysfs attr group: %d\n", retval);
		goto err_remove_phy;
	}

	spin_lock_init(&mvotg->wq_lock);
	if (spin_trylock(&mvotg->wq_lock)) {
		mv_otg_run_state_machine(mvotg, 2 * HZ);
		spin_unlock(&mvotg->wq_lock);
	}

	dev_info(&pdev->dev,
		 "successful probe OTG device %s clock gating.\n",
		 mvotg->clock_gating ? "with" : "without");

	return 0;

err_remove_phy:
	usb_remove_phy(&mvotg->phy);
err_disable_clk:
	mv_otg_disable_internal(mvotg);
err_destroy_workqueue:
	flush_workqueue(mvotg->qwork);
	destroy_workqueue(mvotg->qwork);

	return retval;
}
static void mv_otg_disable(struct mv_otg *mvotg)
{
	if (mvotg->clock_gating)
		mv_otg_disable_internal(mvotg);
}
static int mv_otg_probe(struct platform_device *dev)
{
	struct mv_otg *mvotg;
	struct mv_usb_platform_data *pdata = dev->dev.platform_data;
	int retval = 0, i;
	struct resource *r;
	size_t size;

	if (the_transceiver)
		return 0;

	if (pdata == NULL) {
		dev_err(&dev->dev, "failed to get platform data\n");
		retval = -ENODEV;
		goto err_pdata;
	}

	size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
	mvotg = kzalloc(size, GFP_KERNEL);
	if (!mvotg) {
		dev_err(&dev->dev, "failed to allocate memory!\n");
		retval = -ENOMEM;
		goto err_alloc_private;
	}

	the_transceiver = mvotg;
	platform_set_drvdata(dev, mvotg);

	mvotg->dev = dev;
	mvotg->pdata = pdata;

	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
	if (!mvotg->qwork) {
		dev_dbg(&dev->dev, "cannot create workqueue for OTG\n");
		retval = -ENOMEM;
		goto err_qwork;
	}
	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);

	/* OTG common part */
	mvotg->dev = dev;
	mvotg->otg.dev = &dev->dev;
	mvotg->otg.label = driver_name;
	mvotg->otg.set_host = mv_otg_set_host;
	mvotg->otg.set_peripheral = mv_otg_set_peripheral;
	mvotg->otg.set_vbus = mv_otg_set_vbus;
	mvotg->otg.state = OTG_STATE_UNDEFINED;


	r = platform_get_resource_byname(mvotg->dev, IORESOURCE_MEM, "capregs");
	if (r == NULL) {
		dev_err(&dev->dev, "no I/O memory resource defined\n");
		retval = -ENODEV;
		goto err_get_cap_regs;
	}

	mvotg->cap_regs = (struct mv_cap_regs __iomem *)
		ioremap(r->start, resource_size(r));
	if (mvotg->cap_regs == NULL) {
		dev_err(&dev->dev, "failed to map I/O memory\n");
		retval = -EBUSY;
		goto err_map_cap_regs;
	}

	r = platform_get_resource_byname(mvotg->dev, IORESOURCE_MEM, "phyregs");
	if (r == NULL) {
		dev_err(&dev->dev, "no phy I/O memory resource defined\n");
		retval = -ENODEV;
		goto err_get_phy_regs;
	}

	mvotg->phy_regs = (unsigned int)ioremap(r->start, resource_size(r));
	if (mvotg->phy_regs == 0) {
		dev_err(&dev->dev, "failed to map phy I/O memory\n");
		retval = -EBUSY;
		goto err_map_phy_regs;
	}

	/* we will acces controller register, so enable the udc controller */
	retval = mv_otg_enable_internal(mvotg);
	if (retval) {
		dev_err(&dev->dev, "mv_otg_enable error %d\n", retval);
		goto err_otg_enable;
	}

	mvotg->op_regs = (struct mv_op_regs __iomem *)((u32)mvotg->cap_regs
		+ (readl(&mvotg->cap_regs->caplength_hciversion)
			& CAPLENGTH_MASK));

	mv_otg_reset(mvotg);
	mv_otg_init_irq(mvotg);

	r = platform_get_resource(mvotg->dev, IORESOURCE_IRQ, 0);
	if (r == NULL) {
		dev_err(&dev->dev, "no IRQ resource defined\n");
		retval = -ENODEV;
		goto err_get_irq;
	}
	mvotg->irq = r->start;
	if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
			driver_name, mvotg)) {
		dev_err(&dev->dev, "Request irq %d for OTG failed\n",
			mvotg->irq);
		mvotg->irq = 0;
		retval = -ENODEV;
		goto err_request_irq;
	}

	retval = otg_set_transceiver(&mvotg->otg);
	if (retval < 0) {
		dev_err(&dev->dev, "can't register transceiver, %d\n", retval);
		goto err_set_transceiver;
	}

	retval = sysfs_create_group(&dev->dev.kobj, &inputs_attr_group);
	if (retval < 0) {
		dev_dbg(&dev->dev, "Can't register sysfs attr group: %d\n",
			retval);
		goto err_create_sysfs;
	}

	for (i = 0; i < OTG_TIMER_NUM; i++)
		init_timer(&mvotg->otg_ctrl.timer[i]);

	if (pdata->id) {
		retval = request_threaded_irq(pdata->id->irq, NULL,
				mv_otg_inputs_irq, IRQF_ONESHOT, "id", mvotg);
		if (retval) {
			dev_info(&dev->dev,
				"Can not request irq for ID\n");
		}

		if (pdata->id->init)
			pdata->id->init();
	}

	if (pdata->vbus) {
		retval = request_threaded_irq(pdata->vbus->irq, NULL,
						mv_otg_inputs_irq,
						IRQF_ONESHOT, "vbus", mvotg);
		if (retval) {
			dev_info(&dev->dev,
				"Can not request irq for VBUS, "
				"disable clock gating\n");
		}

		if (pdata->vbus->init)
			pdata->vbus->init();
	}

	spin_lock_init(&mvotg->wq_lock);
	if (spin_trylock(&mvotg->wq_lock)) {
		mv_otg_run_state_machine(mvotg, 2*HZ);
		spin_unlock(&mvotg->wq_lock);
	}

	dev_info(&dev->dev, "successful probe OTG device without clock gating.\n");
	return 0;

err_create_sysfs:
	otg_set_transceiver(NULL);
err_set_transceiver:
	free_irq(mvotg->irq, mvotg);
err_request_irq:
err_get_irq:
	mv_otg_disable_internal(mvotg);
err_otg_enable:
	iounmap((void *)mvotg->phy_regs);
err_map_phy_regs:
err_get_phy_regs:
	iounmap(mvotg->cap_regs);
err_map_cap_regs:
err_get_cap_regs:
	flush_workqueue(mvotg->qwork);
	destroy_workqueue(mvotg->qwork);
err_qwork:
	the_transceiver = NULL;
	platform_set_drvdata(dev, NULL);
	kfree(mvotg);
err_alloc_private:
err_pdata:
	return retval;
}
static int mv_otg_probe(struct platform_device *pdev)
{
	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
	struct mv_otg *mvotg;
	struct usb_otg *otg;
	struct resource *r;
	int retval = 0, i;
	struct device_node *np = pdev->dev.of_node;
	const __be32 *prop;
	unsigned int proplen;

	if (pdata == NULL) {
		dev_err(&pdev->dev, "failed to get platform data\n");
		return -ENODEV;
	}

	mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
	if (!mvotg) {
		dev_err(&pdev->dev, "failed to allocate memory!\n");
		return -ENOMEM;
	}

	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
	if (!otg)
		return -ENOMEM;

	platform_set_drvdata(pdev, mvotg);

	mvotg->pdev = pdev;
	mvotg->pdata = pdata;

	mvotg->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(mvotg->clk))
		return PTR_ERR(mvotg->clk);
	clk_prepare(mvotg->clk);

	mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
	if (!mvotg->qwork) {
		dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
		return -ENOMEM;
	}

	INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);

	/* OTG common part */
	mvotg->pdev = pdev;
	mvotg->phy.dev = &pdev->dev;
	mvotg->phy.type = USB_PHY_TYPE_USB2;
	mvotg->phy.otg = otg;
	mvotg->phy.label = driver_name;
	mvotg->phy.state = OTG_STATE_UNDEFINED;

	otg->phy = &mvotg->phy;
	otg->set_host = mv_otg_set_host;
	otg->set_peripheral = mv_otg_set_peripheral;
	otg->set_vbus = mv_otg_set_vbus;

	mv_otg_phy_bind_device(mvotg);

	for (i = 0; i < OTG_TIMER_NUM; i++)
		init_timer(&mvotg->otg_ctrl.timer[i]);

	r = platform_get_resource(mvotg->pdev,
					 IORESOURCE_MEM, 0);
	if (r == NULL) {
		dev_err(&pdev->dev, "no I/O memory resource defined\n");
		retval = -ENODEV;
		goto err_destroy_workqueue;
	}

	mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
	if (mvotg->cap_regs == NULL) {
		dev_err(&pdev->dev, "failed to map I/O memory\n");
		retval = -EFAULT;
		goto err_destroy_workqueue;
	}

	mvotg->outer_phy = devm_usb_get_phy_dev(&pdev->dev, MV_USB2_PHY_INDEX);
	if (IS_ERR_OR_NULL(mvotg->outer_phy)) {
		retval = PTR_ERR(mvotg->outer_phy);
		if (retval != -EPROBE_DEFER)
			dev_err(&pdev->dev, "can not find outer phy\n");
		goto err_destroy_workqueue;
	}

	/* we will acces controller register, so enable the udc controller */
	retval = mv_otg_enable_internal(mvotg);
	if (retval) {
		dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
		goto err_destroy_workqueue;
	}

	mvotg->op_regs =
		(struct mv_otg_regs __iomem *) ((unsigned long) mvotg->cap_regs
			+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));

	if (pdata->extern_attr
		& (MV_USB_HAS_VBUS_DETECTION | MV_USB_HAS_IDPIN_DETECTION)) {
		mvotg->notifier.notifier_call = mv_otg_notifier_callback;
		pxa_usb_register_notifier(mvotg->pdata->id, &mvotg->notifier);
		if (pdata->extern_attr & MV_USB_HAS_VBUS_DETECTION) {
			mvotg->clock_gating = 1;
			pxa_usb_extern_call(mvotg->pdata->id, vbus, init);
		}
		if (pdata->extern_attr & MV_USB_HAS_IDPIN_DETECTION)
			pxa_usb_extern_call(mvotg->pdata->id, idpin, init);
	}

	if (pdata->disable_otg_clock_gating)
		mvotg->clock_gating = 0;

	mv_otg_reset(mvotg);
	mv_otg_init_irq(mvotg);

	r = platform_get_resource(mvotg->pdev, IORESOURCE_IRQ, 0);
	if (r == NULL) {
		dev_err(&pdev->dev, "no IRQ resource defined\n");
		retval = -ENODEV;
		goto err_disable_clk;
	}

	mvotg->irq = r->start;
	if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
			driver_name, mvotg)) {
		dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
			mvotg->irq);
		mvotg->irq = 0;
		retval = -ENODEV;
		goto err_disable_clk;
	}

	retval = usb_add_phy_dev(&mvotg->phy);
	if (retval < 0) {
		dev_err(&pdev->dev, "can't register transceiver, %d\n",
			retval);
		goto err_disable_clk;
	}

	prop = of_get_property(np, "lpm-qos", &proplen);
	if (!prop) {
		pr_err("lpm-qos config in DT for mv_otg is not defined\n");
		goto err_disable_clk;
	} else
		mvotg->lpm_qos = be32_to_cpup(prop);

	mvotg->qos_idle.name = mvotg->pdev->name;
	pm_qos_add_request(&mvotg->qos_idle, PM_QOS_CPUIDLE_BLOCK,
			PM_QOS_CPUIDLE_BLOCK_DEFAULT_VALUE);

	retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
	if (retval < 0) {
		dev_dbg(&pdev->dev,
			"Can't register sysfs attr group: %d\n", retval);
		goto err_remove_otg_phy;
	}

	spin_lock_init(&mvotg->wq_lock);
	if (spin_trylock(&mvotg->wq_lock)) {
		mv_otg_run_state_machine(mvotg, 2 * HZ);
		spin_unlock(&mvotg->wq_lock);
	}

	dev_info(&pdev->dev,
		 "successful probe OTG device %s clock gating.\n",
		 mvotg->clock_gating ? "with" : "without");

	device_init_wakeup(&pdev->dev, 1);

	return 0;

err_remove_otg_phy:
	usb_remove_phy(&mvotg->phy);
	pm_qos_remove_request(&mvotg->qos_idle);
err_disable_clk:
	mv_otg_disable_internal(mvotg);
	if (pdata->extern_attr
		& (MV_USB_HAS_VBUS_DETECTION | MV_USB_HAS_IDPIN_DETECTION))
		pxa_usb_unregister_notifier(mvotg->pdata->id, &mvotg->notifier);
err_destroy_workqueue:
	flush_workqueue(mvotg->qwork);
	destroy_workqueue(mvotg->qwork);

	return retval;
}