static int dwc_otg_charger_hwdet(bool enable)
{
	int				retval;
	struct usb_phy *phy;
	struct dwc_otg2 *otg = dwc3_get_otg();

	/* Just return if charger detection is not enabled */
	if (!charger_detect_enable(otg))
		return 0;

	phy = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!phy)
		return -ENODEV;

	if (enable) {
		retval = usb_phy_io_write(phy, PWCTRL_HWDETECT,
				TUSB1211_POWER_CONTROL_SET);
		if (retval)
			return retval;
		otg_dbg(otg, "set HWDETECT\n");
	} else {
		retval = usb_phy_io_write(phy, PWCTRL_HWDETECT,
				TUSB1211_POWER_CONTROL_CLR);
		if (retval)
			return retval;
		otg_dbg(otg, "clear HWDETECT\n");
	}
	usb_put_phy(phy);

	return 0;
}
Beispiel #2
0
/**
 * omap_usb2_set_comparator - links the comparator present in the sytem with
 *	this phy
 * @comparator - the companion phy(comparator) for this phy
 *
 * The phy companion driver should call this API passing the phy_companion
 * filled with set_vbus and start_srp to be used by usb phy.
 *
 * For use by phy companion driver
 */
void omap_usb2_set_comparator(struct phy_companion *comparator)
{
	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
	struct omap_usb	*phy = phy_to_omapusb(x);

	phy->comparator = comparator;
}
Beispiel #3
0
static void usb2phy_eye_optimization(struct dwc_otg2 *otg)
{
	void __iomem *addr;
	struct usb_phy *phy;
	struct intel_dwc_otg_pdata *data;

	if (!otg || !otg->otg_data)
		return;

	data = (struct intel_dwc_otg_pdata *)otg->otg_data;

	phy = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!phy)
		return;

	if ((data->usb2_phy_type == USB2_PHY_ULPI) && !!data->ulpi_eye_calibration)
		usb_phy_io_write(phy, data->ulpi_eye_calibration, TUSB1211_VENDOR_SPECIFIC1_SET);
	else if ((data->usb2_phy_type == USB2_PHY_UTMI) && !!data->utmi_eye_calibration) {
		addr = ioremap_nocache(UTMI_PHY_USB2PERPORT, 4);
		if (!addr) {
			otg_info(otg, "UTMI phy register ioremap failed, use default setup!\n");
			usb_put_phy(phy);
			return;
		}
		writel(data->utmi_eye_calibration, addr);
		iounmap(addr);
	} else
		otg_info(otg, "usb2 phy eye optimization fail, use default setup!\n");

	usb_put_phy(phy);
}
static int intel_mid_ehci_driver_register(struct pci_driver *host_driver)
{
	struct usb_phy			*otg;
	struct intel_mid_otg_xceiv	*iotg;

	otg = usb_get_phy(USB_PHY_TYPE_USB2);
	if (otg == NULL || host_driver == NULL)
		return -EINVAL;

	iotg = otg_to_mid_xceiv(otg);
	iotg->start_host = ehci_mid_start_host;
	iotg->stop_host = ehci_mid_stop_host;
	iotg->runtime_suspend_host = ehci_mid_runtime_suspend_host;
	iotg->runtime_resume_host = ehci_mid_runtime_resume_host;

	iotg->suspend_host = ehci_mid_suspend_host;
	iotg->suspend_noirq_host = ehci_mid_suspend_noirq_host;
	iotg->resume_host = ehci_mid_resume_host;
	iotg->resume_noirq_host = ehci_mid_resume_noirq_host;

	/* notify host driver is registered */
	atomic_notifier_call_chain(&iotg->iotg_notifier,
				MID_OTG_NOTIFY_HOSTADD, iotg);

	usb_put_phy(otg);

	return 0;
}
Beispiel #5
0
static int da8xx_musb_init(struct musb *musb)
{
	struct da8xx_glue *glue = dev_get_drvdata(musb->controller->parent);
	void __iomem *reg_base = musb->ctrl_base;
	u32 rev;
	int ret = -ENODEV;

	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;

	ret = clk_prepare_enable(glue->clk);
	if (ret) {
		dev_err(glue->dev, "failed to enable clock\n");
		return ret;
	}

	/* Returns zero if e.g. not clocked */
	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
	if (!rev)
		goto fail;

	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		ret = -EPROBE_DEFER;
		goto fail;
	}

	setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);

	/* Reset the controller */
	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);

	/* Start the on-chip PHY and its PLL. */
	ret = phy_init(glue->phy);
	if (ret) {
		dev_err(glue->dev, "Failed to init phy.\n");
		goto fail;
	}

	ret = phy_power_on(glue->phy);
	if (ret) {
		dev_err(glue->dev, "Failed to power on phy.\n");
		goto err_phy_power_on;
	}

	msleep(5);

	/* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */
	pr_debug("DA8xx OTG revision %08x, control %02x\n", rev,
		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));

	musb->isr = da8xx_musb_interrupt;
	return 0;

err_phy_power_on:
	phy_exit(glue->phy);
fail:
	clk_disable_unprepare(glue->clk);
	return ret;
}
Beispiel #6
0
void __init marzen_init_late(void)
{
	/* get usb phy */
	phy = usb_get_phy(USB_PHY_TYPE_USB2);

	shmobile_init_late();
	platform_add_devices(marzen_late_devices,
			     ARRAY_SIZE(marzen_late_devices));
}
Beispiel #7
0
void __init r8a7779_init_late(void)
{
	/* get USB PHY */
	phy = usb_get_phy(USB_PHY_TYPE_USB2);

	shmobile_init_late();
	platform_add_devices(r8a7779_late_devices,
			     ARRAY_SIZE(r8a7779_late_devices));
}
Beispiel #8
0
static int ux500_musb_init(struct musb *musb)
{
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -ENODEV;
	}

	return 0;
}
Beispiel #9
0
/**
 * omap_usb2_set_comparator - links the comparator present in the sytem with
 *	this phy
 * @comparator - the companion phy(comparator) for this phy
 *
 * The phy companion driver should call this API passing the phy_companion
 * filled with set_vbus and start_srp to be used by usb phy.
 *
 * For use by phy companion driver
 */
int omap_usb2_set_comparator(struct phy_companion *comparator)
{
	struct omap_usb	*phy;
	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);

	if (IS_ERR(x))
		return -ENODEV;

	phy = phy_to_omapusb(x);
	phy->comparator = comparator;
	return 0;
}
Beispiel #10
0
int omap_usb2_charger_detect(struct phy_companion *comparator)
{
	struct usb_phy  *x = usb_get_phy(USB_PHY_TYPE_USB2);
	struct omap_usb *phy = phy_to_omapusb(x);
	int charger = 0;

	omap_usb2_suspend(x, 0);
	charger = omap_usb_charger_detect(phy->control_dev);
	omap_usb2_suspend(x, 1);

	return charger;
}
Beispiel #11
0
static int dsps_musb_init(struct musb *musb)
{
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct platform_device *pdev = to_platform_device(dev);
	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
	const struct dsps_musb_wrapper *wrp = glue->wrp;
	struct omap_musb_board_data *data = plat->board_data;
	void __iomem *reg_base = musb->ctrl_base;
	u32 rev, val;
	int status;

	/* mentor core register starts at offset of 0x400 from musb base */
	musb->mregs += wrp->musb_core_offset;

	/* NOP driver needs change if supporting dual instance */
	usb_nop_xceiv_register();
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv))
		return -ENODEV;

	/* Returns zero if e.g. not clocked */
	rev = dsps_readl(reg_base, wrp->revision);
	if (!rev) {
		status = -ENODEV;
		goto err0;
	}

	setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);

	/* Reset the musb */
	dsps_writel(reg_base, wrp->control, (1 << wrp->reset));

	/* Start the on-chip PHY and its PLL. */
	if (data->set_phy_power)
		data->set_phy_power(1);

	musb->isr = dsps_interrupt;

	/* reset the otgdisable bit, needed for host mode to work */
	val = dsps_readl(reg_base, wrp->phy_utmi);
	val &= ~(1 << wrp->otg_disable);
	dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);

	/* clear level interrupt */
	dsps_writel(reg_base, wrp->eoi, 0);

	return 0;
err0:
	usb_put_phy(musb->xceiv);
	usb_nop_xceiv_unregister();
	return status;
}
Beispiel #12
0
static int jz4740_musb_init(struct musb *musb)
{
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!musb->xceiv) {
		pr_err("HS UDC: no transceiver configured\n");
		return -ENODEV;
	}

	/* Silicon does not implement ConfigData register.
	 * Set dyn_fifo to avoid reading EP config from hardware.
	 */
	musb->dyn_fifo = true;

	musb->isr = jz4740_musb_interrupt;

	return 0;
}
static int usb_otg_suspend(struct usb_hcd *hcd)
{
	struct usb_phy			*otg;
	struct intel_mid_otg_xceiv	*iotg;

	otg = usb_get_phy(USB_PHY_TYPE_USB2);
	if (otg == NULL) {
		pr_err("%s: failed to get otg transceiver\n", __func__);
		return -EINVAL;
	}
	iotg = otg_to_mid_xceiv(otg);
	pr_info("%s: OTG HNP update suspend\n", __func__);

	atomic_notifier_call_chain(&iotg->iotg_notifier,
				MID_OTG_NOTIFY_HSUSPEND, iotg);
	usb_put_phy(otg);
	return 0;
}
static void usb2phy_eye_optimization(struct dwc_otg2 *otg)
{
	struct intel_dwc_otg_pdata *data;
	struct usb_phy *phy;

	data = (struct intel_dwc_otg_pdata *)otg->otg_data;

	phy = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!phy)
		return;

	/* Modify VS1 for better quality in eye diagram */
	if (data && data->ti_phy_vs1)
		usb_phy_io_write(phy, data->ti_phy_vs1,
			TUSB1211_VENDOR_SPECIFIC1_SET);

	usb_put_phy(phy);
}
static int usb_otg_resume(struct usb_hcd *hcd)
{
	struct usb_phy			*otg;
	struct intel_mid_otg_xceiv	*iotg;

	otg = usb_get_phy(USB_PHY_TYPE_USB2);
	if (otg == NULL) {
		pr_err("%s: failed to get otg transceiver\n", __func__);
		return -EINVAL;
	}
	iotg = otg_to_mid_xceiv(otg);
	dev_dbg(otg->dev, "%s OTG HNP update resume\n", __func__);

	atomic_notifier_call_chain(&iotg->iotg_notifier,
				MID_OTG_NOTIFY_HRESUME, iotg);
	usb_put_phy(otg);
	return 0;
}
Beispiel #16
0
static int am35x_musb_init(struct musb *musb)
{
	struct device *dev = musb->controller;
	struct musb_hdrc_platform_data *plat = dev->platform_data;
	struct omap_musb_board_data *data = plat->board_data;
	void __iomem *reg_base = musb->ctrl_base;
	u32 rev;

	musb->mregs += USB_MENTOR_CORE_OFFSET;

	/* Returns zero if e.g. not clocked */
	rev = musb_readl(reg_base, USB_REVISION_REG);
	if (!rev)
		return -ENODEV;

	usb_nop_xceiv_register();
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv))
		return -ENODEV;

	if (is_host_enabled(musb))
		setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);

	/* Reset the musb */
	if (data->reset)
		data->reset();

	/* Reset the controller */
	musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);

	/* Start the on-chip PHY and its PLL. */
	if (data->set_phy_power)
		data->set_phy_power(1);

	msleep(5);

	musb->isr = am35x_musb_interrupt;

	/* clear level interrupt */
	if (data->clear_irq)
		data->clear_irq();

	return 0;
}
static int xhci_dwc_drv_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct usb_phy *usb_phy;
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);

	usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
	otg_set_host(usb_phy->otg, NULL);
	usb_put_phy(usb_phy);

	if (xhci)
		dwc3_stop_host(hcd);
	usb_put_hcd(hcd);

	pm_runtime_disable(hcd->self.controller);
	pm_runtime_set_suspended(hcd->self.controller);
	wake_lock_destroy(&dwc3_xhci.wakelock);
	return 0;
}
Beispiel #18
0
int r8a7778_usb_phy_power(bool enable)
{
	static struct usb_phy *phy = NULL;
	int ret = 0;

	if (!phy)
		phy = usb_get_phy(USB_PHY_TYPE_USB2);

	if (IS_ERR(phy)) {
		pr_err("kernel doesn't have usb phy driver\n");
		return PTR_ERR(phy);
	}

	if (enable)
		ret = usb_phy_init(phy);
	else
		usb_phy_shutdown(phy);

	return ret;
}
static void intel_mid_ehci_driver_unregister(struct pci_driver *host_driver)
{
	struct usb_phy			*otg;
	struct intel_mid_otg_xceiv	*iotg;

	otg = usb_get_phy(USB_PHY_TYPE_USB2);
	if (otg == NULL)
		return;

	iotg = otg_to_mid_xceiv(otg);
	iotg->start_host = NULL;
	iotg->stop_host = NULL;
	iotg->runtime_suspend_host = NULL;
	iotg->runtime_resume_host = NULL;

	/* notify host driver is unregistered */
	atomic_notifier_call_chain(&iotg->iotg_notifier,
				MID_OTG_NOTIFY_HOSTREMOVE, iotg);

	usb_put_phy(otg);
}
Beispiel #20
0
static int ux500_musb_init(struct musb *musb)
{
	int status;

	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		pr_err("HS USB OTG: no transceiver configured\n");
		return -EPROBE_DEFER;
	}

	musb->nb.notifier_call = musb_otg_notifications;
	status = usb_register_notifier(musb->xceiv, &musb->nb);
	if (status < 0) {
		dev_dbg(musb->controller, "notification register failed\n");
		return status;
	}

	musb->isr = ux500_musb_interrupt;

	return 0;
}
Beispiel #21
0
static int da8xx_musb_init(struct musb *musb)
{
	void __iomem *reg_base = musb->ctrl_base;
	u32 rev;
	int ret = -ENODEV;

	musb->mregs += DA8XX_MENTOR_CORE_OFFSET;

	/* Returns zero if e.g. not clocked */
	rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG);
	if (!rev)
		goto fail;

	usb_nop_xceiv_register();
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		ret = -EPROBE_DEFER;
		goto fail;
	}

	setup_timer(&otg_workaround, otg_timer, (unsigned long)musb);

	/* Reset the controller */
	musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);

	/* Start the on-chip PHY and its PLL. */
	phy_on();

	msleep(5);

	/* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */
	pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n",
		 rev, __raw_readl(CFGCHIP2),
		 musb_readb(reg_base, DA8XX_USB_CTRL_REG));

	musb->isr = da8xx_musb_interrupt;
	return 0;
fail:
	return ret;
}
Beispiel #22
0
static int __devinit dwc_otg_driver_probe(struct platform_device *ofdev)
{
	int retval;
	struct dwc_otg_device *dwc_dev;
	struct device *dev = &ofdev->dev;
	struct resource res;
	ulong gusbcfg_addr;
	u32 usbcfg = 0;
	struct resource *nres = 0;
#ifdef CONFIG_OF
	u32 prop;
	u32 prop_array[15];
#endif

	dwc_dev = kzalloc(sizeof(*dwc_dev), GFP_KERNEL);
	if (!dwc_dev) {
		dev_err(dev, "kmalloc of dwc_otg_device failed\n");
		retval = -ENOMEM;
		goto fail_dwc_dev;
	}

	/* Retrieve the memory and IRQ resources. */
	dwc_dev->irq = platform_get_irq(ofdev, 0);
	if (dwc_dev->irq == NO_IRQ) {
		dev_err(dev, "no device irq\n");
		retval = -ENODEV;
		goto fail_of_irq;
	}

	nres = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
	res = *nres;
	if(nres == 0) {
		dev_err(dev, "%s: Can't get USB-OTG register address\n",
			__func__);
		retval = -ENOMEM;
		goto fail_of_irq;
	}

	dwc_dev->phys_addr = res.start;
	dwc_dev->base_len = res.end - res.start + 1;
	if (!request_mem_region(dwc_dev->phys_addr,
				dwc_dev->base_len, dwc_driver_name)) {
		dev_err(dev, "request_mem_region failed\n");
		retval = -EBUSY;
		goto fail_of_irq;
	}

	/* Map the DWC_otg Core memory into virtual address space. */
	dwc_dev->base = ioremap(platform_get_resource(ofdev, IORESOURCE_MEM, 0)->start, SZ_256K);
	if (!dwc_dev->base) {
		dev_err(dev, "ioremap() failed\n");
		retval = -ENOMEM;
		goto fail_ioremap;
	}
	dev_dbg(dev, "mapped base=0x%08x\n", (__force u32)dwc_dev->base);

	/*
	 * Initialize driver data to point to the global DWC_otg
	 * Device structure.
	 */
	dev_set_drvdata(dev, dwc_dev);//driver

	dwc_dev->core_if =
	    dwc_otg_cil_init(dwc_dev->base, &dwc_otg_module_params);
	if (!dwc_dev->core_if) {
		dev_err(dev, "CIL initialization failed!\n");
		retval = -ENOMEM;
		goto fail_cil_init;
	}

	/*
	* Set the wqfunc of this core_if as "not set"
	*/
	dwc_dev->core_if->wqfunc_setup_done = 0;

	/*
	 * Validate parameter values after dwc_otg_cil_init.
	 */
	if (check_parameters(dwc_dev->core_if)) {
		retval = -EINVAL;
		goto fail_check_param;
	}

#ifdef CONFIG_OF
	if(!of_property_read_u32(ofdev->dev.of_node,
		"dma-mask", (u32*)&dwc_otg_dma_mask)) {
		dev->dma_mask = &dwc_otg_dma_mask;
	}
	else {
		dev->dma_mask = NULL;
	}

	if(!of_property_read_u32(ofdev->dev.of_node,
		"ulpi-ddr", &prop)) {
		dwc_otg_module_params.phy_ulpi_ddr = prop;
	}

	if(!of_property_read_u32(ofdev->dev.of_node,
		"host-rx-fifo-size", &prop)) {
		dwc_otg_module_params.host_rx_fifo_size = prop;
	}
	if(!of_property_read_u32(ofdev->dev.of_node,
		"dev-rx-fifo-size", &prop)) {
		dwc_otg_module_params.dev_rx_fifo_size = prop;
	}
	if(!of_property_read_u32(ofdev->dev.of_node,
		"host-nperio-tx-fifo-size", &prop)) {
		dwc_otg_module_params.host_nperio_tx_fifo_size = prop;
	}
	if(!of_property_read_u32(ofdev->dev.of_node,
		"dev-nperio-tx-fifo-size", &prop)) {
		dwc_otg_module_params.dev_nperio_tx_fifo_size = prop;
	}
	if(!of_property_read_u32(ofdev->dev.of_node,
		"host-perio-tx-fifo-size", &prop)) {
		dwc_otg_module_params.host_perio_tx_fifo_size = prop;
	}
	if(!of_property_read_u32_array(ofdev->dev.of_node,
		"dev-perio-tx-fifo-size", prop_array, MAX_PERIO_FIFOS)) {
		int i;
		for(i=0; i<MAX_PERIO_FIFOS; i++)
			dwc_otg_module_params.dev_tx_fifo_size[i]
				= prop_array[i];
	}
	if(!of_property_read_u32_array(ofdev->dev.of_node,
		"dev-tx-fifo-size", prop_array, MAX_TX_FIFOS)) {
		int i;
		for(i=0; i<MAX_TX_FIFOS; i++)
			dwc_otg_module_params.dev_perio_tx_fifo_size[i]
				= prop_array[i];
	}
#endif

	usb_nop_xceiv_register();
	dwc_dev->core_if->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!dwc_dev->core_if->xceiv) {
		retval = -ENODEV;
		goto fail_xceiv;
	}
	dwc_set_feature(dwc_dev->core_if);

	/* Initialize the DWC_otg core. */
	dwc_otg_core_init(dwc_dev->core_if);

	/*
	 * Disable the global interrupt until all the interrupt
	 * handlers are installed.
	 */
	spin_lock(&dwc_dev->lock);
	dwc_otg_disable_global_interrupts(dwc_dev->core_if);
	spin_unlock(&dwc_dev->lock);

	/*
	 * Install the interrupt handler for the common interrupts before
	 * enabling common interrupts in core_init below.
	 */
	retval = request_irq(dwc_dev->irq, dwc_otg_common_irq,
			     IRQF_SHARED, "dwc_otg", dwc_dev);
	if (retval) {
		dev_err(dev, "request of irq%d failed retval: %d\n",
			dwc_dev->irq, retval);
		retval = -EBUSY;
		goto fail_req_irq;
	} else {
		dwc_dev->common_irq_installed = 1;
	}

	if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) {
	//if (dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) {
		/* Initialize the PCD */
		retval = dwc_otg_pcd_init(dev);
		if (retval) {
			dev_err(dev, "dwc_otg_pcd_init failed\n");
			dwc_dev->pcd = NULL;
			goto fail_req_irq;
		}
	}

	gusbcfg_addr = (ulong) (dwc_dev->core_if->core_global_regs)
		+ DWC_GUSBCFG;
	if (!dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) {
	//if (dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) {
		/* Initialize the HCD and force_host_mode */
		usbcfg = dwc_reg_read(gusbcfg_addr, 0);
		usbcfg |= DWC_USBCFG_FRC_HST_MODE;
		dwc_reg_write(gusbcfg_addr, 0, usbcfg);

		retval = dwc_otg_hcd_init(dev, dwc_dev);
		if (retval) {
			dev_err(dev, "dwc_otg_hcd_init failed\n");
			dwc_dev->hcd = NULL;
			goto fail_hcd;
		}
		/* configure chargepump interrupt */
		dwc_dev->hcd->cp_irq = platform_get_irq_byname(ofdev, "chargepumpirq");
		if(dwc_dev->hcd->cp_irq != -ENXIO) {
			retval = request_irq(dwc_dev->hcd->cp_irq,
					     dwc_otg_externalchgpump_irq,
					     IRQF_SHARED,
					     "dwc_otg_ext_chg_pump", dwc_dev);
			if (retval) {
				dev_err(dev,
					"request of irq failed retval: %d\n",
					retval);
				retval = -EBUSY;
				goto fail_hcd;
			} else {
				dev_dbg(dev, "%s: ExtChgPump Detection "
					"IRQ registered\n", dwc_driver_name);
			}
		}
	}
	/*
	 * Enable the global interrupt after all the interrupt
	 * handlers are installed.
	 */
	dwc_otg_enable_global_interrupts(dwc_dev->core_if);

#if 0
	usbcfg = dwc_reg_read(gusbcfg_addr, 0);
	usbcfg &= ~DWC_USBCFG_FRC_HST_MODE;
	dwc_reg_write(gusbcfg_addr, 0, usbcfg);
#endif

	return 0;
fail_hcd:
	free_irq(dwc_dev->irq, dwc_dev);
	if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) {
		if (dwc_dev->pcd)
			dwc_otg_pcd_remove(dev);
	}
fail_req_irq:
	usb_put_phy(dwc_dev->core_if->xceiv);
fail_xceiv:
	usb_nop_xceiv_unregister();
fail_check_param:
	dwc_otg_cil_remove(dwc_dev->core_if);
fail_cil_init:
	dev_set_drvdata(dev, NULL);
	iounmap(dwc_dev->base);
fail_ioremap:
	release_mem_region(dwc_dev->phys_addr, dwc_dev->base_len);
fail_of_irq:
	kfree(dwc_dev);
fail_dwc_dev:
	return retval;
}
static int xhci_dwc_drv_probe(struct platform_device *pdev)
{
	struct dwc_otg2 *otg;
	struct usb_phy *usb_phy;
	struct dwc_device_par *pdata;
	struct usb_hcd *hcd;
	struct resource *res;
	int retval = 0;
	int ret;

	if (usb_disabled())
		return -ENODEV;

	pr_debug("initializing FSL-SOC USB Controller\n");

	/* Need platform data for setup */
	pdata = (struct dwc_device_par *)pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev,
			"No platform data for %s.\n", dev_name(&pdev->dev));
		return -ENODEV;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(&pdev->dev,
			"Found HC with no IRQ. Check %s setup!\n",
			dev_name(&pdev->dev));
		return -ENODEV;
	}
	dwc3_xhci.otg_irqnum = res->start;

	hcd = usb_create_hcd(&xhci_dwc_hc_driver,
			&pdev->dev, dev_name(&pdev->dev));
	if (!hcd) {
		retval = -ENOMEM;
		return retval;
	}

	hcd->regs = pdata->io_addr;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev,
			"Found HC with no IRQ. Check %s setup!\n",
			dev_name(&pdev->dev));
		return -ENODEV;
	}
	hcd->rsrc_start = res->start;
	hcd->rsrc_len = res->end - res->start;

	usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
	if (usb_phy)
		otg_set_host(usb_phy->otg, &hcd->self);

	otg = container_of(usb_phy->otg, struct dwc_otg2, otg);
	if (otg) {
		otg->start_host = dwc3_start_host;
		otg->stop_host = dwc3_stop_host;
		otg->suspend_host = dwc3_suspend_host;
		otg->resume_host = dwc3_resume_host;
	}

	usb_put_phy(usb_phy);

	/* Enable wakeup irq */
	hcd->has_wakeup_irq = 1;
	INIT_WORK(&dwc3_xhci.reset_hcd, dwc3_host_reset);
	INIT_WORK(&dwc3_xhci.poll_loopback, dwc3_poll_lp);
	wake_lock_init(&dwc3_xhci.wakelock, WAKE_LOCK_SUSPEND,
			"dwc3_host_wakelock");

	platform_set_drvdata(pdev, hcd);
	pm_runtime_no_callbacks(hcd->self.controller);
	pm_runtime_enable(hcd->self.controller);
	ret = device_create_file(hcd->self.controller, &dev_attr_host_comp_test);
	if (ret < 0)
		dev_err(hcd->self.controller,
			"Can't register sysfs attribute: %d\n", ret);

	return retval;
}
static int davinci_musb_init(struct musb *musb)
{
	void __iomem	*tibase = musb->ctrl_base;
	u32		revision;
	int 		ret = -ENODEV;

	usb_nop_xceiv_register();
	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
	if (IS_ERR_OR_NULL(musb->xceiv)) {
		ret = -EPROBE_DEFER;
		goto unregister;
	}

	musb->mregs += DAVINCI_BASE_OFFSET;

	/* returns zero if e.g. not clocked */
	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
	if (revision == 0)
		goto fail;

	setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);

	davinci_musb_source_power(musb, 0, 1);

	/* dm355 EVM swaps D+/D- for signal integrity, and
	 * is clocked from the main 24 MHz crystal.
	 */
	if (machine_is_davinci_dm355_evm()) {
		u32	phy_ctrl = __raw_readl(USB_PHY_CTRL);

		phy_ctrl &= ~(3 << 9);
		phy_ctrl |= USBPHY_DATAPOL;
		__raw_writel(phy_ctrl, USB_PHY_CTRL);
	}

	/* On dm355, the default-A state machine needs DRVVBUS control.
	 * If we won't be a host, there's no need to turn it on.
	 */
	if (cpu_is_davinci_dm355()) {
		u32	deepsleep = __raw_readl(DM355_DEEPSLEEP);

		deepsleep &= ~DRVVBUS_FORCE;
		__raw_writel(deepsleep, DM355_DEEPSLEEP);
	}

	/* reset the controller */
	musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);

	/* start the on-chip PHY and its PLL */
	phy_on();

	msleep(5);

	/* NOTE:  irqs are in mixed mode, not bypass to pure-musb */
	pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
		revision, __raw_readl(USB_PHY_CTRL),
		musb_readb(tibase, DAVINCI_USB_CTRL_REG));

	musb->isr = davinci_musb_interrupt;
	return 0;

fail:
	usb_put_phy(musb->xceiv);
unregister:
	usb_nop_xceiv_unregister();
	return ret;
}
static int __devinit isp1704_charger_probe(struct platform_device *pdev)
{
	struct isp1704_charger	*isp;
	int			ret = -ENODEV;

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

	isp->phy = usb_get_phy();
	if (!isp->phy)
		goto fail0;

	isp->dev = &pdev->dev;
	platform_set_drvdata(pdev, isp);

	isp1704_charger_set_power(isp, 1);

	ret = isp1704_test_ulpi(isp);
	if (ret < 0)
		goto fail1;

	isp->psy.name		= "isp1704";
	isp->psy.type		= POWER_SUPPLY_TYPE_USB;
	isp->psy.properties	= power_props;
	isp->psy.num_properties	= ARRAY_SIZE(power_props);
	isp->psy.get_property	= isp1704_charger_get_property;

	ret = power_supply_register(isp->dev, &isp->psy);
	if (ret)
		goto fail1;

	/*
	 * REVISIT: using work in order to allow the usb notifications to be
	 * made atomically in the future.
	 */
	INIT_WORK(&isp->work, isp1704_charger_work);

	isp->nb.notifier_call = isp1704_notifier_call;

	ret = usb_register_notifier(isp->phy, &isp->nb);
	if (ret)
		goto fail2;

	dev_info(isp->dev, "registered with product id %s\n", isp->model);

	/*
	 * Taking over the D+ pullup.
	 *
	 * FIXME: The device will be disconnected if it was already
	 * enumerated. The charger driver should be always loaded before any
	 * gadget is loaded.
	 */
	if (isp->phy->otg->gadget)
		usb_gadget_disconnect(isp->phy->otg->gadget);

	/* Detect charger if VBUS is valid (the cable was already plugged). */
	ret = isp1704_read(isp, ULPI_USB_INT_STS);
	isp1704_charger_set_power(isp, 0);
	if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) {
		isp->event = USB_EVENT_VBUS;
		schedule_work(&isp->work);
	}

	return 0;
fail2:
	power_supply_unregister(&isp->psy);
fail1:
	usb_put_phy(isp->phy);
fail0:
	kfree(isp);

	dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);

	isp1704_charger_set_power(isp, 0);
	return ret;
}
Beispiel #26
0
static int pda_power_probe(struct platform_device *pdev)
{
	int ret = 0;

	dev = &pdev->dev;

	if (pdev->id != -1) {
		dev_err(dev, "it's meaningless to register several "
			"pda_powers; use id = -1\n");
		ret = -EINVAL;
		goto wrongid;
	}

	pdata = pdev->dev.platform_data;

	if (pdata->init) {
		ret = pdata->init(dev);
		if (ret < 0)
			goto init_failed;
	}

	ac_draw = regulator_get(dev, "ac_draw");
	if (IS_ERR(ac_draw)) {
		dev_dbg(dev, "couldn't get ac_draw regulator\n");
		ac_draw = NULL;
	}

	update_status();
	update_charger();

	if (!pdata->wait_for_status)
		pdata->wait_for_status = 500;

	if (!pdata->wait_for_charger)
		pdata->wait_for_charger = 500;

	if (!pdata->polling_interval)
		pdata->polling_interval = 2000;

	if (!pdata->ac_max_uA)
		pdata->ac_max_uA = 500000;

	setup_timer(&charger_timer, charger_timer_func, 0);
	setup_timer(&supply_timer, supply_timer_func, 0);

	ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");

	if (pdata->supplied_to) {
		pda_psy_ac.supplied_to = pdata->supplied_to;
		pda_psy_ac.num_supplicants = pdata->num_supplicants;
		pda_psy_usb.supplied_to = pdata->supplied_to;
		pda_psy_usb.num_supplicants = pdata->num_supplicants;
	}

#if IS_ENABLED(CONFIG_USB_PHY)
	transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!IS_ERR_OR_NULL(transceiver)) {
		if (!pdata->is_usb_online)
			pdata->is_usb_online = otg_is_usb_online;
		if (!pdata->is_ac_online)
			pdata->is_ac_online = otg_is_ac_online;
	}
#endif

	if (pdata->is_ac_online) {
		ret = power_supply_register(&pdev->dev, &pda_psy_ac);
		if (ret) {
			dev_err(dev, "failed to register %s power supply\n",
				pda_psy_ac.name);
			goto ac_supply_failed;
		}

		if (ac_irq) {
			ret = request_irq(ac_irq->start, power_changed_isr,
					  get_irq_flags(ac_irq), ac_irq->name,
					  &pda_psy_ac);
			if (ret) {
				dev_err(dev, "request ac irq failed\n");
				goto ac_irq_failed;
			}
		} else {
			polling = 1;
		}
	}

	if (pdata->is_usb_online) {
		ret = power_supply_register(&pdev->dev, &pda_psy_usb);
		if (ret) {
			dev_err(dev, "failed to register %s power supply\n",
				pda_psy_usb.name);
			goto usb_supply_failed;
		}

		if (usb_irq) {
			ret = request_irq(usb_irq->start, power_changed_isr,
					  get_irq_flags(usb_irq),
					  usb_irq->name, &pda_psy_usb);
			if (ret) {
				dev_err(dev, "request usb irq failed\n");
				goto usb_irq_failed;
			}
		} else {
			polling = 1;
		}
	}

#if IS_ENABLED(CONFIG_USB_PHY)
	if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
		otg_nb.notifier_call = otg_handle_notification;
		ret = usb_register_notifier(transceiver, &otg_nb);
		if (ret) {
			dev_err(dev, "failure to register otg notifier\n");
			goto otg_reg_notifier_failed;
		}
		polling = 0;
	}
#endif

	if (polling) {
		dev_dbg(dev, "will poll for status\n");
		setup_timer(&polling_timer, polling_timer_func, 0);
		mod_timer(&polling_timer,
			  jiffies + msecs_to_jiffies(pdata->polling_interval));
	}

	if (ac_irq || usb_irq)
		device_init_wakeup(&pdev->dev, 1);

	return 0;

#if IS_ENABLED(CONFIG_USB_PHY)
otg_reg_notifier_failed:
	if (pdata->is_usb_online && usb_irq)
		free_irq(usb_irq->start, &pda_psy_usb);
#endif
usb_irq_failed:
	if (pdata->is_usb_online)
		power_supply_unregister(&pda_psy_usb);
usb_supply_failed:
	if (pdata->is_ac_online && ac_irq)
		free_irq(ac_irq->start, &pda_psy_ac);
#if IS_ENABLED(CONFIG_USB_PHY)
	if (!IS_ERR_OR_NULL(transceiver))
		usb_put_phy(transceiver);
#endif
ac_irq_failed:
	if (pdata->is_ac_online)
		power_supply_unregister(&pda_psy_ac);
ac_supply_failed:
	if (ac_draw) {
		regulator_put(ac_draw);
		ac_draw = NULL;
	}
	if (pdata->exit)
		pdata->exit(dev);
init_failed:
wrongid:
	return ret;
}
Beispiel #27
0
static int __init twl4030_bci_probe(struct platform_device *pdev)
{
	struct twl4030_bci *bci;
	const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
	int ret;
	u32 reg;

	bci = kzalloc(sizeof(*bci), GFP_KERNEL);
	if (bci == NULL)
		return -ENOMEM;

	if (!pdata)
		pdata = twl4030_bci_parse_dt(&pdev->dev);

	bci->dev = &pdev->dev;
	bci->irq_chg = platform_get_irq(pdev, 0);
	bci->irq_bci = platform_get_irq(pdev, 1);

	/* Only proceed further *IF* battery is physically present */
	ret = twl4030_is_battery_present(bci);
	if  (ret) {
		dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
		goto fail_no_battery;
	}

	platform_set_drvdata(pdev, bci);

	bci->ac = power_supply_register(&pdev->dev, &twl4030_bci_ac_desc,
					NULL);
	if (IS_ERR(bci->ac)) {
		ret = PTR_ERR(bci->ac);
		dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
		goto fail_register_ac;
	}

	bci->usb_reg = regulator_get(bci->dev, "bci3v1");

	bci->usb = power_supply_register(&pdev->dev, &twl4030_bci_usb_desc,
					 NULL);
	if (IS_ERR(bci->usb)) {
		ret = PTR_ERR(bci->usb);
		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
		goto fail_register_usb;
	}

	ret = request_threaded_irq(bci->irq_chg, NULL,
			twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
			bci);
	if (ret < 0) {
		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
			bci->irq_chg, ret);
		goto fail_chg_irq;
	}

	ret = request_threaded_irq(bci->irq_bci, NULL,
			twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
	if (ret < 0) {
		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
			bci->irq_bci, ret);
		goto fail_bci_irq;
	}

	INIT_WORK(&bci->work, twl4030_bci_usb_work);

	bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!IS_ERR_OR_NULL(bci->transceiver)) {
		bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
		usb_register_notifier(bci->transceiver, &bci->usb_nb);
	}

	/* Enable interrupts now. */
	reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
		TWL4030_TBATOR1 | TWL4030_BATSTS);
	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
			       TWL4030_INTERRUPTS_BCIIMR1A);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
		goto fail_unmask_interrupts;
	}

	reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
			       TWL4030_INTERRUPTS_BCIIMR2A);
	if (ret < 0)
		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);

	twl4030_charger_enable_ac(true);
	twl4030_charger_enable_usb(bci, true);
	if (pdata)
		twl4030_charger_enable_backup(pdata->bb_uvolt,
					      pdata->bb_uamp);
	else
		twl4030_charger_enable_backup(0, 0);

	return 0;

fail_unmask_interrupts:
	if (!IS_ERR_OR_NULL(bci->transceiver)) {
		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
		usb_put_phy(bci->transceiver);
	}
	free_irq(bci->irq_bci, bci);
fail_bci_irq:
	free_irq(bci->irq_chg, bci);
fail_chg_irq:
	power_supply_unregister(bci->usb);
fail_register_usb:
	power_supply_unregister(bci->ac);
fail_register_ac:
fail_no_battery:
	kfree(bci);

	return ret;
}
static enum power_supply_charger_cable_type
			dwc3_intel_byt_get_charger_type(struct dwc_otg2 *otg)
{
	struct usb_phy *phy;
	u8 val, vdat_det, chgd_serx_dm;
	unsigned long timeout, interval;
	enum power_supply_charger_cable_type type =
		POWER_SUPPLY_CHARGER_TYPE_NONE;

	/* No need to do charger detection if not enabled */
	if (!charger_detect_enable(otg))
		return POWER_SUPPLY_CHARGER_TYPE_USB_SDP;

	phy = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!phy) {
		otg_err(otg, "Get USB2 PHY failed\n");
		return POWER_SUPPLY_CHARGER_TYPE_NONE;
	}

	/* PHY Enable:
	 * Power on PHY
	 */
	enable_usb_phy(otg, true);

	/* Wait 10ms (~5ms before PHY de-asserts DIR,
	 * XXus for initial Link reg sync-up).*/
	msleep(20);

	/* DCD Enable: Change OPMODE to 01 (Non-driving),
	 * TermSel to 0, &
	 * XcvrSel to 01 (enable FS xcvr)
	 */
	usb_phy_io_write(phy, FUNCCTRL_OPMODE(1) | FUNCCTRL_XCVRSELECT(1),
					TUSB1211_FUNC_CTRL_SET);

	usb_phy_io_write(phy, FUNCCTRL_OPMODE(2) | FUNCCTRL_XCVRSELECT(2)
					| FUNCCTRL_TERMSELECT,
					TUSB1211_FUNC_CTRL_CLR);

	/*Enable SW control*/
	usb_phy_io_write(phy, PWCTRL_SW_CONTROL, TUSB1211_POWER_CONTROL_SET);

	/* Enable IDPSRC */
	usb_phy_io_write(phy, VS3_CHGD_IDP_SRC_EN,
			TUSB1211_VENDOR_SPECIFIC3_SET);

	/* Check DCD result, use same polling parameter */
	timeout = jiffies + msecs_to_jiffies(DATACON_TIMEOUT);
	interval = DATACON_INTERVAL * 1000; /* us */

	/* DCD Check:
	 * Delay 66.5 ms. (Note:
	 * TIDP_SRC_ON + TCHGD_SERX_DEB =
	 * 347.8us + 66.1ms).
	 */
	usleep_range(66500, 67000);

	while (!time_after(jiffies, timeout)) {
		/* Read DP logic level. */
		val = usb_phy_io_read(phy, TUSB1211_VENDOR_SPECIFIC4);
		if (val < 0) {
			otg_err(otg, "ULPI read error! try again\n");
			continue;
		}

		if (!(val & VS4_CHGD_SERX_DP)) {
			otg_info(otg, "Data contact detected!\n");
			break;
		}

		/* Polling interval */
		usleep_range(interval, interval + 2000);
	}

	/* Disable DP pullup (Idp_src) */
	usb_phy_io_write(phy, VS3_CHGD_IDP_SRC_EN,
			TUSB1211_VENDOR_SPECIFIC3_CLR);

	/* SE1 Det Enable:
	 * Read DP/DM logic level. Note: use DEBUG
	 * because VS4 isn’t enabled in this situation.
	 */
	val = usb_phy_io_read(phy, TUSB1211_DEBUG);
	if (val < 0)
		otg_err(otg, "ULPI read error!\n");

	val &= DEBUG_LINESTATE;

	/* If '11': SE1 detected; goto 'Cleanup'.
	 * Else: goto 'Pri Det Enable'.
	 */
	if (val == 3) {
		type = POWER_SUPPLY_CHARGER_TYPE_SE1;
		goto cleanup;
	}

	/* Pri Det Enable:
	 * Enable VDPSRC.
	 */
	usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_SET);

	/* Wait >106.1ms (40ms for BC
	 * Tvdpsrc_on, 66.1ms for TI CHGD_SERX_DEB).
	 */
	msleep(107);

	/* Pri Det Check:
	 * Check if DM > VDATREF.
	 */
	vdat_det = usb_phy_io_read(phy, TUSB1211_POWER_CONTROL);
	if (vdat_det < 0)
		otg_err(otg, "ULPI read error!\n");

	vdat_det &= PWCTRL_VDAT_DET;

	/* Check if DM<VLGC */
	chgd_serx_dm = usb_phy_io_read(phy, TUSB1211_VENDOR_SPECIFIC4);
	if (chgd_serx_dm < 0)
		otg_err(otg, "ULPI read error!\n");

	chgd_serx_dm &= VS4_CHGD_SERX_DM;

	/* If VDAT_DET==0 || CHGD_SERX_DM==1: SDP detected
	 * If VDAT_DET==1 && CHGD_SERX_DM==0: CDP/DCP
	 */
	if (vdat_det == 0 || chgd_serx_dm == 1)
		type = POWER_SUPPLY_CHARGER_TYPE_USB_SDP;

	/* Disable VDPSRC. */
	usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_CLR);

	/* If SDP, goto “Cleanup”.
	 * Else, goto “Sec Det Enable”
	 */
	if (type == POWER_SUPPLY_CHARGER_TYPE_USB_SDP)
		goto cleanup;

	/* Sec Det Enable:
	 * delay 1ms.
	 */
	usleep_range(1000, 1500);

	/* Swap DP & DM */
	usb_phy_io_write(phy, VS1_DATAPOLARITY, TUSB1211_VENDOR_SPECIFIC1_CLR);

	/* Enable 'VDMSRC'. */
	usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_SET);

	/* Wait >73ms (40ms for BC Tvdmsrc_on, 33ms for TI TVDPSRC_DEB) */
	msleep(80);

	/* Sec Det Check:
	 * Check if DP>VDATREF.
	 */
	val = usb_phy_io_read(phy, TUSB1211_POWER_CONTROL);
	if (val < 0)
		otg_err(otg, "ULPI read error!\n");

	val &= PWCTRL_VDAT_DET;

	/* If VDAT_DET==0: CDP detected.
	 * If VDAT_DET==1: DCP detected.
	 */
	if (!val)
		type = POWER_SUPPLY_CHARGER_TYPE_USB_CDP;
	else
		type = POWER_SUPPLY_CHARGER_TYPE_USB_DCP;

	/* Disable VDMSRC. */
	usb_phy_io_write(phy, PWCTRL_DP_VSRC_EN, TUSB1211_POWER_CONTROL_CLR);

	/* Swap DP & DM. */
	usb_phy_io_write(phy, VS1_DATAPOLARITY, TUSB1211_VENDOR_SPECIFIC1_SET);

cleanup:

	/* If DCP detected, assert VDPSRC. */
	if (type == POWER_SUPPLY_CHARGER_TYPE_USB_DCP)
		usb_phy_io_write(phy, PWCTRL_SW_CONTROL | PWCTRL_DP_VSRC_EN,
				TUSB1211_POWER_CONTROL_SET);

	usb_put_phy(phy);

	switch (type) {
	case POWER_SUPPLY_CHARGER_TYPE_ACA_DOCK:
	case POWER_SUPPLY_CHARGER_TYPE_ACA_A:
	case POWER_SUPPLY_CHARGER_TYPE_ACA_B:
	case POWER_SUPPLY_CHARGER_TYPE_ACA_C:
	case POWER_SUPPLY_CHARGER_TYPE_USB_DCP:
	case POWER_SUPPLY_CHARGER_TYPE_USB_CDP:
	case POWER_SUPPLY_CHARGER_TYPE_SE1:
		dwc_otg_charger_hwdet(true);
		break;
	default:
		break;
	};

	return type;
}
Beispiel #29
0
static int ohci_omap_reset(struct usb_hcd *hcd)
{
	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
	struct omap_usb_config	*config = dev_get_platdata(hcd->self.controller);
	int			need_transceiver = (config->otg != 0);
	int			ret;

	dev_dbg(hcd->self.controller, "starting USB Controller\n");

	if (config->otg) {
		hcd->self.otg_port = config->otg;
		/* default/minimum OTG power budget:  8 mA */
		hcd->power_budget = 8;
	}

	/* boards can use OTG transceivers in non-OTG modes */
	need_transceiver = need_transceiver
			|| machine_is_omap_h2() || machine_is_omap_h3();

	/* XXX OMAP16xx only */
	if (config->ocpi_enable)
		config->ocpi_enable();

#ifdef	CONFIG_USB_OTG
	if (need_transceiver) {
		hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
		if (!IS_ERR_OR_NULL(hcd->phy)) {
			int	status = otg_set_host(hcd->phy->otg,
						&ohci_to_hcd(ohci)->self);
			dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
					hcd->phy->label, status);
			if (status) {
				usb_put_phy(hcd->phy);
				return status;
			}
		} else {
			dev_err(hcd->self.controller, "can't find phy\n");
			return -ENODEV;
		}
		ohci->start_hnp = start_hnp;
	}
#endif

	omap_ohci_clock_power(1);

	if (cpu_is_omap15xx()) {
		omap_1510_local_bus_power(1);
		omap_1510_local_bus_init();
	}

	ret = ohci_setup(hcd);
	if (ret < 0)
		return ret;

	if (config->otg || config->rwc) {
		ohci->hc_control = OHCI_CTRL_RWC;
		writel(OHCI_CTRL_RWC, &ohci->regs->control);
	}

	/* board-specific power switching and overcurrent support */
	if (machine_is_omap_osk() || machine_is_omap_innovator()) {
		u32	rh = roothub_a (ohci);

		/* power switching (ganged by default) */
		rh &= ~RH_A_NPS;

		/* TPS2045 switch for internal transceiver (port 1) */
		if (machine_is_omap_osk()) {
			ohci_to_hcd(ohci)->power_budget = 250;

			rh &= ~RH_A_NOCP;

			/* gpio9 for overcurrent detction */
			omap_cfg_reg(W8_1610_GPIO9);
			gpio_request(9, "OHCI overcurrent");
			gpio_direction_input(9);

			/* for paranoia's sake:  disable USB.PUEN */
			omap_cfg_reg(W4_USB_HIGHZ);
		}
		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
		ohci->flags &= ~OHCI_QUIRK_HUB_POWER;
	} else if (machine_is_nokia770()) {
		/* We require a self-powered hub, which should have
		 * plenty of power. */
		ohci_to_hcd(ohci)->power_budget = 0;
	}

	/* FIXME khubd hub requests should manage power switching */
	omap_ohci_transceiver_power(1);

	/* board init will have already handled HMC and mux setup.
	 * any external transceiver should already be initialized
	 * too, so all configured ports use the right signaling now.
	 */

	return 0;
}
/**
 * dwc3_core_init - Low-level initialization of DWC3 Core
 * @dwc: Pointer to our controller context structure
 *
 * Returns 0 on success otherwise negative errno.
 */
static int dwc3_core_init(struct dwc3 *dwc)
{
	unsigned long		timeout;
	u32			reg;
	int			ret;
	struct usb_phy		*usb_phy;

	reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
	/* This should read as U3 followed by revision number */
	if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
		dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
		ret = -ENODEV;
		goto err0;
	}
	dwc->revision = reg;

	/* issue device SoftReset too */
	timeout = jiffies + msecs_to_jiffies(500);
	dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
	do {
		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
		if (!(reg & DWC3_DCTL_CSFTRST))
			break;

		if (time_after(jiffies, timeout)) {
			dev_err(dwc->dev, "Reset Timed Out\n");
			ret = -ETIMEDOUT;
			goto err0;
		}

		cpu_relax();
	} while (true);

	dwc3_core_soft_reset(dwc);

	/* DCTL core soft reset may cause PHY hang, delay 1 ms and check ulpi */
	mdelay(1);

	if (!dwc->utmi_phy) {
		usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
		if (usb_phy &&
			usb_phy_io_read(usb_phy, ULPI_VENDOR_ID_LOW) < 0)
			dev_err(dwc->dev,
				"ULPI not working after DCTL soft reset\n");
		usb_put_phy(usb_phy);
	}

	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
	reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
	reg &= ~DWC3_GCTL_DISSCRAMBLE;

	switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
	case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
		reg &= ~DWC3_GCTL_DSBLCLKGTNG;
		break;
	default:
		dev_dbg(dwc->dev, "No power optimization available\n");
	}

	/*
	 * WORKAROUND: DWC3 revisions <1.90a have a bug
	 * where the device can fail to connect at SuperSpeed
	 * and falls back to high-speed mode which causes
	 * the device to enter a Connect/Disconnect loop
	 */
	if (dwc->revision < DWC3_REVISION_190A)
		reg |= DWC3_GCTL_U2RSTECN;

	dwc3_core_num_eps(dwc);

	dwc3_writel(dwc->regs, DWC3_GCTL, reg);

	return 0;

err0:
	return ret;
}