Пример #1
0
/**
 * dwc3_otg_exit
 * @dwc: Pointer to out controller context structure
 *
 * Returns 0 on success otherwise negative errno.
 */
void dwc3_otg_exit(struct dwc3 *dwc)
{
	struct dwc3_otg *dotg = dwc->dotg;

	/* dotg is null when GHWPARAMS6[10]=SRPSupport=0, see dwc3_otg_init */
	if (dotg) {
		if (dotg->charger)
			dotg->charger->start_detection(dotg->charger, false);
		cancel_work_sync(&dotg->sm_work);
		usb_set_transceiver(NULL);
		free_irq(dotg->irq, dotg);
		kfree(dotg->otg.phy);
		kfree(dotg);
		dwc->dotg = NULL;
	}
}
Пример #2
0
static int __exit gpio_vbus_remove(struct platform_device *pdev)
{
	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
	int gpio = pdata->gpio_vbus;

	regulator_put(gpio_vbus->vbus_draw);

	usb_set_transceiver(NULL);

	free_irq(gpio_to_irq(gpio), &pdev->dev);
	if (gpio_is_valid(pdata->gpio_pullup))
		gpio_free(pdata->gpio_pullup);
	gpio_free(gpio);
	platform_set_drvdata(pdev, NULL);
	kfree(gpio_vbus->phy.otg);
	kfree(gpio_vbus);

	return 0;
}
/**
 * dwc3_otg_exit
 * @dwc: Pointer to out controller context structure
 *
 * Returns 0 on success otherwise negative errno.
 */
void dwc3_otg_exit(struct dwc3 *dwc)
{
	struct dwc3_otg *dotg = dwc->dotg;

	/* dotg is null when GHWPARAMS6[10]=SRPSupport=0, see dwc3_otg_init */
	if (dotg) {
		if (dotg->charger)
			dotg->charger->start_detection(dotg->charger, false);
/* OPPO 2013-11-21 wangjc Add begin for delay charger detect */
#ifdef CONFIG_MACH_MSM8974_14001
		cancel_delayed_work_sync(&dotg->detect_work);
#endif
/* OPPO 2013-11-21 wangjc Add end */
		cancel_delayed_work_sync(&dotg->sm_work);
		usb_set_transceiver(NULL);
		pm_runtime_put(dwc->dev);
		free_irq(dotg->irq, dotg);
		kfree(dotg->otg.phy);
		kfree(dotg);
		dwc->dotg = NULL;
	}
}
Пример #4
0
/**
 * dwc3_otg_exit
 * @dwc: Pointer to out controller context structure
 *
 * Returns 0 on success otherwise negative errno.
 */
void dwc3_otg_exit(struct dwc3 *dwc)
{
	struct dwc3_otg *dotg = dwc->dotg;

	/* dotg is null when GHWPARAMS6[10]=SRPSupport=0, see dwc3_otg_init */
	if (dotg) {
		if (dotg->charger)
			dotg->charger->start_detection(dotg->charger, false);
		cancel_delayed_work_sync(&dotg->sm_work);
		usb_set_transceiver(NULL);
		pm_runtime_put(dwc->dev);
		free_irq(dotg->irq, dotg);
		kfree(dotg->otg.phy);
		kfree(dotg);
		dwc->dotg = NULL;
	}
#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)
#if defined (CONFIG_TOUCHSCREEN_SYNAPTICS_G2) || defined (CONFIG_MACH_MSM8974_TIGERS)
	if (touch_otg_wq)
		destroy_workqueue(touch_otg_wq);
#endif
#endif
}
/**
 * exynos_drd_switch_init - Initializes DRD role switch.
 *
 * @drd: Pointer to DRD controller structure.
 *
 * Returns 0 on success otherwise negative errno.
 */
int exynos_drd_switch_init(struct exynos_drd *drd)
{
    struct dwc3_exynos_data *pdata = drd->pdata;
    struct exynos_drd_switch *drd_switch;
    int ret = 0;
    unsigned long irq_flags = 0;

    dev_dbg(drd->dev, "%s\n", __func__);

    drd_switch = devm_kzalloc(drd->dev, sizeof(struct exynos_drd_switch),
                              GFP_KERNEL);
    if (!drd_switch) {
        dev_err(drd->dev, "not enough memory for DRD switch\n");
        return -ENOMEM;
    }

    drd_switch->core = &drd->core;
    atomic_set(&drd_switch->sm_reset, 0);

    /* ID pin gpio IRQ */
    drd_switch->id_irq = pdata->id_irq;
    if (drd_switch->id_irq < 0)
        dev_dbg(drd->dev, "cannot find ID irq\n");

    init_timer(&drd_switch->id_db_timer);
    drd_switch->id_db_timer.data = (unsigned long) drd_switch;
    drd_switch->id_db_timer.function = exynos_drd_switch_debounce;

    /* VBus pin gpio IRQ */
    drd_switch->vbus_irq = pdata->vbus_irq;
    if (drd_switch->vbus_irq < 0)
        dev_dbg(drd->dev, "cannot find VBUS irq\n");

    init_timer(&drd_switch->vbus_db_timer);
    drd_switch->vbus_db_timer.data = (unsigned long) drd_switch;
    drd_switch->vbus_db_timer.function = exynos_drd_switch_debounce;

    irq_flags = pdata->irq_flags;

    drd_switch->otg.set_peripheral = exynos_drd_switch_set_peripheral;
    drd_switch->otg.set_host = exynos_drd_switch_set_host;

    /* Save for using by host and peripheral */
    drd->core.otg = &drd_switch->otg;

    drd_switch->otg.phy = devm_kzalloc(drd->dev, sizeof(struct usb_phy),
                                       GFP_KERNEL);
    if (!drd_switch->otg.phy) {
        dev_err(drd->dev, "cannot allocate OTG phy\n");
        return -ENOMEM;
    }

    drd_switch->otg.phy->otg = &drd_switch->otg;
    drd_switch->otg.phy->dev = drd->dev;
#if 0
    /*
     * TODO: we need to have support for multiple transceivers here.
     * Kernel > 3.5 should already have it. Now it works only for one
     * drd channel.
     */
    ret = usb_set_transceiver(drd_switch->otg.phy);
    if (ret) {
        dev_err(drd->dev,
                "failed to set transceiver, already exists\n",
                __func__);
        goto err2;
    }
#endif
    spin_lock_init(&drd_switch->lock);
#if !defined(CONFIG_USB_HOST_NOTIFY)
    wake_lock_init(&drd_switch->wakelock,
                   WAKE_LOCK_SUSPEND, "drd_switch");
#endif
    exynos_drd_switch_reset(drd, 0);

    drd_switch->wq = create_freezable_workqueue("drd_switch");
    if (!drd_switch->wq) {
        dev_err(drd->dev, "cannot create workqueue\n");
        ret = -ENOMEM;
        goto err_wq;
    }

    INIT_DELAYED_WORK(&drd_switch->work, exynos_drd_switch_work);

    if (drd_switch->id_irq >= 0) {
        ret = devm_request_irq(drd->dev, drd_switch->id_irq,
                               exynos_drd_switch_id_interrupt, irq_flags,
                               "drd_switch_id", drd_switch);
        if (ret) {
            dev_err(drd->dev, "cannot claim ID irq\n");
            goto err_irq;
        }
    }

    if (drd_switch->vbus_irq >= 0) {
        ret = devm_request_irq(drd->dev, drd_switch->vbus_irq,
                               exynos_drd_switch_vbus_interrupt, irq_flags,
                               "drd_switch_vbus", drd_switch);
        if (ret) {
            dev_err(drd->dev, "cannot claim VBUS irq\n");
            goto err_irq;
        }
    }

    ret = sysfs_create_group(&drd->dev->kobj, &exynos_drd_switch_attr_group);
    if (ret) {
        dev_err(drd->dev, "cannot create switch attributes\n");
        goto err_irq;
    }

    dev_dbg(drd->dev, "DRD switch initialization finished normally\n");

    return 0;

err_irq:
    cancel_delayed_work_sync(&drd_switch->work);
    destroy_workqueue(drd_switch->wq);
err_wq:
#if !defined(CONFIG_USB_HOST_NOTIFY)
    wake_lock_destroy(&drd_switch->wakelock);
#endif
    return ret;
}
Пример #6
0
/**
 * dwc3_otg_init - Initializes otg related registers
 * @dwc: Pointer to out controller context structure
 *
 * Returns 0 on success otherwise negative errno.
 */
int dwc3_otg_init(struct dwc3 *dwc)
{
	u32	reg;
	int ret = 0;
	struct dwc3_otg *dotg;

	dev_dbg(dwc->dev, "dwc3_otg_init\n");

	/*
	 * GHWPARAMS6[10] bit is SRPSupport.
	 * This bit also reflects DWC_USB3_EN_OTG
	 */
	reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
	if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
		/*
		 * No OTG support in the HW core.
		 * We return 0 to indicate no error, since this is acceptable
		 * situation, just continue probe the dwc3 driver without otg.
		 */
		dev_dbg(dwc->dev, "dwc3_otg address space is not supported\n");
		return 0;
	}

	/* Allocate and init otg instance */
	dotg = kzalloc(sizeof(struct dwc3_otg), GFP_KERNEL);
	if (!dotg) {
		dev_err(dwc->dev, "unable to allocate dwc3_otg\n");
		return -ENOMEM;
	}

	/* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
	dotg->irq = platform_get_irq_byname(to_platform_device(dwc->dev),
								"otg_irq");
	if (dotg->irq < 0) {
		dev_err(dwc->dev, "%s: missing OTG IRQ\n", __func__);
		ret = -ENODEV;
		goto err1;
	}

	dotg->regs = dwc->regs;

	dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
	dotg->otg.set_host = dwc3_otg_set_host;

	/* This reference is used by dwc3 modules for checking otg existance */
	dwc->dotg = dotg;

	dotg->otg.phy = kzalloc(sizeof(struct usb_phy), GFP_KERNEL);
	if (!dotg->otg.phy) {
		dev_err(dwc->dev, "unable to allocate dwc3_otg.phy\n");
		ret = -ENOMEM;
		goto err1;
	}

	dotg->dwc = dwc;
	dotg->otg.phy->otg = &dotg->otg;
	dotg->otg.phy->dev = dwc->dev;
	dotg->otg.phy->set_power = dwc3_otg_set_power;
	dotg->otg.phy->set_suspend = dwc3_otg_set_suspend;

	ret = usb_set_transceiver(dotg->otg.phy);
	if (ret) {
		dev_err(dotg->otg.phy->dev,
			"%s: failed to set transceiver, already exists\n",
			__func__);
		goto err2;
	}

	dotg->otg.phy->state = OTG_STATE_UNDEFINED;

	init_completion(&dotg->dwc3_xcvr_vbus_init);
	INIT_DELAYED_WORK(&dotg->sm_work, dwc3_otg_sm_work);

	ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
				"dwc3_otg", dotg);
	if (ret) {
		dev_err(dotg->otg.phy->dev, "failed to request irq #%d --> %d\n",
				dotg->irq, ret);
		goto err3;
	}

	pm_runtime_get(dwc->dev);

	return 0;

err3:
	cancel_delayed_work_sync(&dotg->sm_work);
	usb_set_transceiver(NULL);
err2:
	kfree(dotg->otg.phy);
err1:
	dwc->dotg = NULL;
	kfree(dotg);

	return ret;
}
Пример #7
0
/**
 * dwc3_otg_sm_work - workqueue function.
 *
 * @w: Pointer to the dwc3 otg workqueue
 *
 * NOTE: After any change in phy->state,
 * we must reschdule the state machine.
 */
static void dwc3_otg_sm_work(struct work_struct *w)
{
	struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work.work);
	struct usb_phy *phy = dotg->otg.phy;
	struct dwc3_charger *charger = dotg->charger;
	bool work = 0;
	int ret = 0;
	unsigned long delay = 0;

	pm_runtime_resume(phy->dev);
	dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));

	/* Check OTG state */
	switch (phy->state) {
	case OTG_STATE_UNDEFINED:
		dwc3_otg_init_sm(dotg);
		if (!dotg->psy) {
			dotg->psy = power_supply_get_by_name("usb");

			if (!dotg->psy)
				dev_err(phy->dev,
					 "couldn't get usb power supply\n");
		}

		/* Switch to A or B-Device according to ID / BSV */
		if (!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id\n");
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
		} else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
			dev_dbg(phy->dev, "b_sess_vld\n");
			phy->state = OTG_STATE_B_IDLE;
			work = 1;
		} else {
			phy->state = OTG_STATE_B_IDLE;
			dev_dbg(phy->dev, "No device, trying to suspend\n");
			pm_runtime_put_sync(phy->dev);
		}
		break;

	case OTG_STATE_B_IDLE:
		if (!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id\n");
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
			dotg->charger_retry_count = 0;
			if (charger) {
				if (charger->chg_type == DWC3_INVALID_CHARGER)
					charger->start_detection(dotg->charger,
									false);
				else
					charger->chg_type =
							DWC3_INVALID_CHARGER;
			}
		} else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
			dev_dbg(phy->dev, "b_sess_vld\n");
			if (charger) {
				/* Has charger been detected? If no detect it */
				switch (charger->chg_type) {
				case DWC3_DCP_CHARGER:
				case DWC3_PROPRIETARY_CHARGER:
					dev_dbg(phy->dev, "lpm, DCP charger\n");
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_MAX);
					pm_runtime_put_sync(phy->dev);
					break;
				case DWC3_CDP_CHARGER:
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_MAX);
					dwc3_otg_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					work = 1;
					break;
				case DWC3_SDP_CHARGER:
					dwc3_otg_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					pr_info("DWC3_SDP_CHARGER\n");
					work = 1;
					break;
				case DWC3_FLOATED_CHARGER:
					if (dotg->charger_retry_count <
							max_chgr_retry_count)
						dotg->charger_retry_count++;
					/*
					 * In case of floating charger, if
					 * retry count equal to max retry count
					 * notify PMIC about floating charger
					 * and put Hw in low power mode. Else
					 * perform charger detection again by
					 * calling start_detection() with false
					 * and then with true argument.
					 */
					if (dotg->charger_retry_count ==
						max_chgr_retry_count) {
						dwc3_otg_set_power(phy, 0);
						pm_runtime_put_sync(phy->dev);
						break;
					}
					charger->start_detection(dotg->charger,
									false);

				default:
					dev_dbg(phy->dev, "chg_det started\n");
					charger->start_detection(charger, true);
					break;
				}
			} else {
				/* no charger registered, start peripheral */
				if (dwc3_otg_start_peripheral(&dotg->otg, 1)) {
					/*
					 * Probably set_peripheral not called
					 * yet. We will re-try as soon as it
					 * will be called
					 */
					dev_err(phy->dev, "enter lpm as\n"
						"unable to start B-device\n");
					phy->state = OTG_STATE_UNDEFINED;
					pm_runtime_put_sync(phy->dev);
					return;
				}
			}
		} else {
			if (charger)
				charger->start_detection(dotg->charger, false);

			dotg->charger_retry_count = 0;
			dwc3_otg_set_power(phy, 0);
			dev_dbg(phy->dev, "No device, trying to suspend\n");
			pm_runtime_put_sync(phy->dev);
		}
		break;

	case OTG_STATE_B_PERIPHERAL:
#ifdef CONFIG_PANTECH_USB_BLOCKING_MDMSTATE
		if (get_pantech_mdm_state())
			dwc3_otg_set_power(phy, DWC3_BLOCKING_USB_MDMSTATE_MAX);
#endif
#ifndef CONFIG_PANTECH_SIO_BUG_FIX
		if (!test_bit(B_SESS_VLD, &dotg->inputs) ||
				!test_bit(ID, &dotg->inputs)) {
#else
		if (!test_bit(B_SESS_VLD, &dotg->inputs)) {
		
#endif
			dev_dbg(phy->dev, "!id || !bsv\n");
			dwc3_otg_start_peripheral(&dotg->otg, 0);
			phy->state = OTG_STATE_B_IDLE;
			if (charger)
				charger->chg_type = DWC3_INVALID_CHARGER;
			work = 1;
		}
		break;

	case OTG_STATE_A_IDLE:
		/* Switch to A-Device*/
		if (test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "id\n");
			phy->state = OTG_STATE_B_IDLE;
			dotg->vbus_retry_count = 0;
			work = 1;
		} else {
			phy->state = OTG_STATE_A_HOST;
			ret = dwc3_otg_start_host(&dotg->otg, 1);
			if ((ret == -EPROBE_DEFER) &&
						dotg->vbus_retry_count < 3) {
				/*
				 * Get regulator failed as regulator driver is
				 * not up yet. Will try to start host after 1sec
				 */
				phy->state = OTG_STATE_A_IDLE;
				dev_dbg(phy->dev, "Unable to get vbus regulator. Retrying...\n");
				delay = VBUS_REG_CHECK_DELAY;
				work = 1;
				dotg->vbus_retry_count++;
			} else if (ret) {
				/*
				 * Probably set_host was not called yet.
				 * We will re-try as soon as it will be called
				 */
				dev_dbg(phy->dev, "enter lpm as\n"
					"unable to start A-device\n");
				phy->state = OTG_STATE_A_IDLE;
				pm_runtime_put_sync(phy->dev);
				return;
			}
		}
		break;

	case OTG_STATE_A_HOST:
		if (test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "id\n");
#ifdef CONFIG_PANTECH_SIO_BUG_FIX
			/* FIXME : If OTG cable is disconnecting, below process is must completed 
			 * before pm_runtime_suspend.
			 * So we are ignored pm_runtime_suspend request.
			 * LS4-USB tarial
			 */
			pm_runtime_get_noresume(phy->dev);
#endif
			dwc3_otg_start_host(&dotg->otg, 0);
			phy->state = OTG_STATE_B_IDLE;
			dotg->vbus_retry_count = 0;
			work = 1;
#ifdef CONFIG_PANTECH_SIO_BUG_FIX
			pm_runtime_put_noidle(phy->dev);
#endif
		}
		break;

	default:
		dev_err(phy->dev, "%s: invalid otg-state\n", __func__);

	}

	if (work)
		queue_delayed_work(system_nrt_wq, &dotg->sm_work, delay);
}


/**
 * dwc3_otg_reset - reset dwc3 otg registers.
 *
 * @w: Pointer to the dwc3 otg workqueue
 */
static void dwc3_otg_reset(struct dwc3_otg *dotg)
{
	static int once;
	struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;

	/*
	 * OCFG[2] - OTG-Version = 1
	 * OCFG[1] - HNPCap = 0
	 * OCFG[0] - SRPCap = 0
	 */
	if (ext_xceiv && !ext_xceiv->otg_capability)
		dwc3_writel(dotg->regs, DWC3_OCFG, 0x4);

	/*
	 * OCTL[6] - PeriMode = 1
	 * OCTL[5] - PrtPwrCtl = 0
	 * OCTL[4] - HNPReq = 0
	 * OCTL[3] - SesReq = 0
	 * OCTL[2] - TermSelDLPulse = 0
	 * OCTL[1] - DevSetHNPEn = 0
	 * OCTL[0] - HstSetHNPEn = 0
	 */
	if (!once) {
		if (ext_xceiv && !ext_xceiv->otg_capability)
			dwc3_writel(dotg->regs, DWC3_OCTL, 0x40);
		once++;
	}

	/* Clear all otg events (interrupts) indications  */
	dwc3_writel(dotg->regs, DWC3_OEVT, 0xFFFF);

	/* Enable ID/BSV StsChngEn event*/
	if (ext_xceiv && !ext_xceiv->otg_capability)
		dwc3_writel(dotg->regs, DWC3_OEVTEN,
				DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT |
				DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT);
}

/**
 * dwc3_otg_init - Initializes otg related registers
 * @dwc: Pointer to out controller context structure
 *
 * Returns 0 on success otherwise negative errno.
 */
int dwc3_otg_init(struct dwc3 *dwc)
{
	u32	reg;
	int ret = 0;
	struct dwc3_otg *dotg;

	dev_dbg(dwc->dev, "dwc3_otg_init\n");

	/*
	 * GHWPARAMS6[10] bit is SRPSupport.
	 * This bit also reflects DWC_USB3_EN_OTG
	 */
	reg = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
	if (!(reg & DWC3_GHWPARAMS6_SRP_SUPPORT)) {
		/*
		 * No OTG support in the HW core.
		 * We return 0 to indicate no error, since this is acceptable
		 * situation, just continue probe the dwc3 driver without otg.
		 */
		dev_dbg(dwc->dev, "dwc3_otg address space is not supported\n");
		return 0;
	}

	/* Allocate and init otg instance */
	dotg = kzalloc(sizeof(struct dwc3_otg), GFP_KERNEL);
	if (!dotg) {
		dev_err(dwc->dev, "unable to allocate dwc3_otg\n");
		return -ENOMEM;
	}

	/* DWC3 has separate IRQ line for OTG events (ID/BSV etc.) */
	dotg->irq = platform_get_irq_byname(to_platform_device(dwc->dev),
								"otg_irq");
	if (dotg->irq < 0) {
		dev_err(dwc->dev, "%s: missing OTG IRQ\n", __func__);
		ret = -ENODEV;
		goto err1;
	}

	dotg->regs = dwc->regs;

	dotg->otg.set_peripheral = dwc3_otg_set_peripheral;
	dotg->otg.set_host = dwc3_otg_set_host;

	/* This reference is used by dwc3 modules for checking otg existance */
	dwc->dotg = dotg;

	dotg->otg.phy = kzalloc(sizeof(struct usb_phy), GFP_KERNEL);
	if (!dotg->otg.phy) {
		dev_err(dwc->dev, "unable to allocate dwc3_otg.phy\n");
		ret = -ENOMEM;
		goto err1;
	}

	dotg->dwc = dwc;
	dotg->otg.phy->otg = &dotg->otg;
	dotg->otg.phy->dev = dwc->dev;
	dotg->otg.phy->set_power = dwc3_otg_set_power;
	dotg->otg.phy->set_suspend = dwc3_otg_set_suspend;

	ret = usb_set_transceiver(dotg->otg.phy);
	if (ret) {
		dev_err(dotg->otg.phy->dev,
			"%s: failed to set transceiver, already exists\n",
			__func__);
		goto err2;
	}

	dotg->otg.phy->state = OTG_STATE_UNDEFINED;

	init_completion(&dotg->dwc3_xcvr_vbus_init);
	INIT_DELAYED_WORK(&dotg->sm_work, dwc3_otg_sm_work);

	ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
				"dwc3_otg", dotg);
	if (ret) {
		dev_err(dotg->otg.phy->dev, "failed to request irq #%d --> %d\n",
				dotg->irq, ret);
		goto err3;
	}

	pm_runtime_get(dwc->dev);

	return 0;

err3:
	cancel_delayed_work_sync(&dotg->sm_work);
	usb_set_transceiver(NULL);
err2:
	kfree(dotg->otg.phy);
err1:
	dwc->dotg = NULL;
	kfree(dotg);

	return ret;
}
Пример #8
0
static int __init gpio_vbus_probe(struct platform_device *pdev)
{
	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
	struct gpio_vbus_data *gpio_vbus;
	struct resource *res;
	int err, gpio, irq;

	if (!pdata || !gpio_is_valid(pdata->gpio_vbus))
		return -EINVAL;
	gpio = pdata->gpio_vbus;

	gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL);
	if (!gpio_vbus)
		return -ENOMEM;

	gpio_vbus->phy.otg = kzalloc(sizeof(struct usb_otg), GFP_KERNEL);
	if (!gpio_vbus->phy.otg) {
		kfree(gpio_vbus);
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, gpio_vbus);
	gpio_vbus->dev = &pdev->dev;
	gpio_vbus->phy.label = "gpio-vbus";
	gpio_vbus->phy.set_power = gpio_vbus_set_power;
	gpio_vbus->phy.set_suspend = gpio_vbus_set_suspend;
	gpio_vbus->phy.state = OTG_STATE_UNDEFINED;

	gpio_vbus->phy.otg->phy = &gpio_vbus->phy;
	gpio_vbus->phy.otg->set_peripheral = gpio_vbus_set_peripheral;

	err = gpio_request(gpio, "vbus_detect");
	if (err) {
		dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n",
			gpio, err);
		goto err_gpio;
	}
	gpio_direction_input(gpio);

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res) {
		irq = res->start;
		res->flags &= IRQF_TRIGGER_MASK;
		res->flags |= IRQF_SAMPLE_RANDOM | IRQF_SHARED;
	} else
		irq = gpio_to_irq(gpio);

	/* if data line pullup is in use, initialize it to "not pulling up" */
	gpio = pdata->gpio_pullup;
	if (gpio_is_valid(gpio)) {
		err = gpio_request(gpio, "udc_pullup");
		if (err) {
			dev_err(&pdev->dev,
				"can't request pullup gpio %d, err: %d\n",
				gpio, err);
			gpio_free(pdata->gpio_vbus);
			goto err_gpio;
		}
		gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
	}

	err = request_irq(irq, gpio_vbus_irq, VBUS_IRQ_FLAGS,
		"vbus_detect", pdev);
	if (err) {
		dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
			irq, err);
		goto err_irq;
	}
	INIT_WORK(&gpio_vbus->work, gpio_vbus_work);

	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
	if (IS_ERR(gpio_vbus->vbus_draw)) {
		dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
			PTR_ERR(gpio_vbus->vbus_draw));
		gpio_vbus->vbus_draw = NULL;
	}

	/* only active when a gadget is registered */
	err = usb_set_transceiver(&gpio_vbus->phy);
	if (err) {
		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
			err);
		goto err_otg;
	}

	return 0;
err_otg:
	free_irq(irq, &pdev->dev);
err_irq:
	if (gpio_is_valid(pdata->gpio_pullup))
		gpio_free(pdata->gpio_pullup);
	gpio_free(pdata->gpio_vbus);
err_gpio:
	platform_set_drvdata(pdev, NULL);
	kfree(gpio_vbus->phy.otg);
	kfree(gpio_vbus);
	return err;
}
Пример #9
0
static void __exit isp_exit(void)
{
    if (the_transceiver)
        usb_set_transceiver(NULL);
    i2c_del_driver(&isp1301_driver);
}
Пример #10
0
static int __devinit
isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
    int			status;
    struct isp1301		*isp;

    if (the_transceiver)
        return 0;

    isp = kzalloc(sizeof *isp, GFP_KERNEL);
    if (!isp)
        return 0;

    isp->phy.otg = kzalloc(sizeof *isp->phy.otg, GFP_KERNEL);
    if (!isp->phy.otg) {
        kfree(isp);
        return 0;
    }

    INIT_WORK(&isp->work, isp1301_work);
    init_timer(&isp->timer);
    isp->timer.function = isp1301_timer;
    isp->timer.data = (unsigned long) isp;

    i2c_set_clientdata(i2c, isp);
    isp->client = i2c;

    /* verify the chip (shouldn't be necessary) */
    status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
    if (status != I2C_VENDOR_ID_PHILIPS) {
        dev_dbg(&i2c->dev, "not philips id: %d\n", status);
        goto fail;
    }
    status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
    if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
        dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
        goto fail;
    }
    isp->i2c_release = i2c->dev.release;
    i2c->dev.release = isp1301_release;

    /* initial development used chiprev 2.00 */
    status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
    dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
             status >> 8, status & 0xff);

    /* make like power-on reset */
    isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);

    isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
    isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);

    isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
                     OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
    isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
                       ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));

    isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
    isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
    isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);

#ifdef	CONFIG_USB_OTG
    status = otg_bind(isp);
    if (status < 0) {
        dev_dbg(&i2c->dev, "can't bind OTG\n");
        goto fail;
    }
#endif

    if (machine_is_omap_h2()) {
        /* full speed signaling by default */
        isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
                         MC1_SPEED);
        isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
                         MC2_SPD_SUSP_CTRL);

        /* IRQ wired at M14 */
        omap_cfg_reg(M14_1510_GPIO2);
        if (gpio_request(2, "isp1301") == 0)
            gpio_direction_input(2);
        isp->irq_type = IRQF_TRIGGER_FALLING;
    }

    status = request_irq(i2c->irq, isp1301_irq,
                         isp->irq_type, DRIVER_NAME, isp);
    if (status < 0) {
        dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
                i2c->irq, status);
        goto fail;
    }

    isp->phy.dev = &i2c->dev;
    isp->phy.label = DRIVER_NAME;
    isp->phy.set_power = isp1301_set_power,

             isp->phy.otg->phy = &isp->phy;
    isp->phy.otg->set_host = isp1301_set_host,
                  isp->phy.otg->set_peripheral = isp1301_set_peripheral,
                                isp->phy.otg->start_srp = isp1301_start_srp,
                                              isp->phy.otg->start_hnp = isp1301_start_hnp,

                                                            enable_vbus_draw(isp, 0);
    power_down(isp);
    the_transceiver = isp;

#ifdef	CONFIG_USB_OTG
    update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
    update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
#endif

    dump_regs(isp, __func__);

#ifdef	VERBOSE
    mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
    dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
#endif

    status = usb_set_transceiver(&isp->phy);
    if (status < 0)
        dev_err(&i2c->dev, "can't register transceiver, %d\n",
                status);

    return 0;

fail:
    kfree(isp->phy.otg);
    kfree(isp);
    return -ENODEV;
}
static int __devinit twl6030_usb_probe(struct platform_device *pdev)
{
	struct twl6030_usb	*twl;
	int			status, err;
	struct twl4030_usb_data *pdata;
	struct usb_otg		*otg;
	struct device *dev = &pdev->dev;
	pdata = dev->platform_data;

	twl = kzalloc(sizeof *twl, GFP_KERNEL);
	if (!twl)
		return -ENOMEM;

	otg = kzalloc(sizeof *otg, GFP_KERNEL);
	if (!otg) {
		kfree(twl);
		return -ENOMEM;
	}

	twl->dev		= &pdev->dev;
	twl->irq1		= platform_get_irq(pdev, 0);
	twl->irq2		= platform_get_irq(pdev, 1);
	twl->features		= pdata->features;

	twl->phy.dev		= twl->dev;
	twl->phy.label		= "twl6030";
	twl->phy.otg		= otg;
	twl->phy.init		= twl6030_phy_init;
	twl->phy.shutdown	= twl6030_phy_shutdown;
	twl->phy.set_suspend	= twl6030_phy_suspend;

	otg->phy		= &twl->phy;
	otg->set_host		= twl6030_set_host;
	otg->set_peripheral	= twl6030_set_peripheral;
	otg->set_vbus		= twl6030_set_vbus;
	otg->start_srp		= twl6030_start_srp;

	
	spin_lock_init(&twl->lock);

	err = twl6030_usb_ldo_init(twl);
	if (err) {
		dev_err(&pdev->dev, "ldo init failed\n");
		kfree(otg);
		kfree(twl);
		return err;
	}
	usb_set_transceiver(&twl->phy);

	platform_set_drvdata(pdev, twl);
	if (device_create_file(&pdev->dev, &dev_attr_vbus))
		dev_warn(&pdev->dev, "could not create sysfs file\n");

	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);

	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);

	twl->irq_enabled = true;
	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
			"twl6030_usb", twl);
	if (status < 0) {
		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
			twl->irq1, status);
		device_remove_file(twl->dev, &dev_attr_vbus);
		kfree(otg);
		kfree(twl);
		return status;
	}

	status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
			"twl6030_usb", twl);
	if (status < 0) {
		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
			twl->irq2, status);
		free_irq(twl->irq1, twl);
		device_remove_file(twl->dev, &dev_attr_vbus);
		kfree(otg);
		kfree(twl);
		return status;
	}

	twl->asleep = 0;
	pdata->phy_init(dev);
	twl6030_phy_suspend(&twl->phy, 0);
	twl6030_enable_irq(&twl->phy);
	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");

	return 0;
}
static int __devinit twl4030_usb_probe(struct platform_device *pdev)
{
	struct twl4030_usb_data *pdata = pdev->dev.platform_data;
	struct twl4030_usb	*twl;
	int			status, err;
	struct usb_otg		*otg;

	if (!pdata) {
		dev_dbg(&pdev->dev, "platform_data not available\n");
		return -EINVAL;
	}

	twl = kzalloc(sizeof *twl, GFP_KERNEL);
	if (!twl)
		return -ENOMEM;

	otg = kzalloc(sizeof *otg, GFP_KERNEL);
	if (!otg) {
		kfree(twl);
		return -ENOMEM;
	}

	twl->dev		= &pdev->dev;
	twl->irq		= platform_get_irq(pdev, 0);
	twl->usb_mode		= pdata->usb_mode;
	twl->vbus_supplied	= false;
	twl->asleep		= 1;

	twl->phy.dev		= twl->dev;
	twl->phy.label		= "twl4030";
	twl->phy.otg		= otg;
	twl->phy.set_suspend	= twl4030_set_suspend;

	otg->phy		= &twl->phy;
	otg->set_host		= twl4030_set_host;
	otg->set_peripheral	= twl4030_set_peripheral;

	
	spin_lock_init(&twl->lock);

	err = twl4030_usb_ldo_init(twl);
	if (err) {
		dev_err(&pdev->dev, "ldo init failed\n");
		kfree(otg);
		kfree(twl);
		return err;
	}
	usb_set_transceiver(&twl->phy);

	platform_set_drvdata(pdev, twl);
	if (device_create_file(&pdev->dev, &dev_attr_vbus))
		dev_warn(&pdev->dev, "could not create sysfs file\n");

	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);

	twl->irq_enabled = true;
	status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
			"twl4030_usb", twl);
	if (status < 0) {
		dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
			twl->irq, status);
		kfree(otg);
		kfree(twl);
		return status;
	}

	twl4030_usb_phy_init(twl);

	dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
	return 0;
}