Exemplo n.º 1
0
static int ehci_fsl_drv_resume(struct platform_device *pdev)
{
    struct usb_hcd *hcd = platform_get_drvdata(pdev);
    struct ehci_hcd *ehci = hcd_to_ehci(hcd);
    u32 tmp;
    struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

    printk(KERN_INFO "USB Host resumed\n");

    pr_debug("%s('%s'): suspend=%d already_suspended=%d\n", __func__,
             pdata->name, pdata->suspended, pdata->already_suspended);

    /*
     * If the controller was already suspended at suspend time,
     * then don't resume it now.
     */
    if (pdata->already_suspended) {
        pr_debug("already suspended, leaving early\n");
        pdata->already_suspended = 0;
        return 0;
    }

    if (!pdata->suspended) {
        pr_debug("not suspended, leaving early\n");
        return 0;
    }

    pdata->suspended = 0;

    pr_debug("%s resuming...\n", __func__);

    /* set host mode */
    fsl_platform_set_host_mode(hcd);

    /* restore EHCI registers */
    ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
    ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
    ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index);
    ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment);
    ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list);
    ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next);
    ehci_writel(ehci, pdata->pm_configured_flag,
                &ehci->regs->configured_flag);
    ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);

    set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
    hcd->state = HC_STATE_RUNNING;
    pdev->dev.power.power_state = PMSG_ON;

    tmp = ehci_readl(ehci, &ehci->regs->command);
    tmp |= CMD_RUN;
    ehci_writel(ehci, tmp, &ehci->regs->command);

    usb_hcd_resume_root_hub(hcd);

    return 0;
}
/*
 * Initialize SOC FSL EHCI Controller
 *
 * This code is derived from EHCI FSL USB Linux driver for MPC5121
 *
 */
int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr,
		struct ehci_hcor **ret_hcor)
{
	volatile struct usb_ehci *ehci;
	struct ehci_hccr *hccr;
	struct ehci_hcor *hcor;

	/* Hook the memory mapped registers for EHCI-Controller */
	ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
	hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength));
	hcor = (struct ehci_hcor *)((uint32_t) hccr +
				HC_LENGTH(ehci_readl(&hccr->cr_capbase)));

	/* configure interface for UTMI_WIDE */
	usb_platform_dr_init(ehci);

	/* Init Phy USB0 to UTMI+ */
	fsl_setup_phy(hcor);

	/* Set to host mode */
	fsl_platform_set_host_mode(ehci);

	/*
	 * Setting the burst size seems to be required to prevent the
	 * USB from hanging when communicating with certain USB Mass
	 * storage devices. This was determined by analysing the
	 * EHCI registers under Linux vs U-Boot and burstsize was the
	 * major non-interrupt related difference between the two
	 * implementations.
	 *
	 * Some USB sticks behave better than others. In particular,
	 * the following USB stick is especially problematic:
	 * 0930:6545 Toshiba Corp
	 *
	 * The burstsize is set here to match the Linux implementation.
	 */
	out_be32(&ehci->burstsize, FSL_EHCI_TXPBURST(8) |
				   FSL_EHCI_RXPBURST(8));

	*ret_hccr = hccr;
	*ret_hcor = hcor;
	return 0;
}
Exemplo n.º 3
0
/**
 * usb_hcd_fsl_probe - initialize FSL-based HCDs
 * @drvier: Driver to be used for this HCD
 * @pdev: USB Host Controller being probed
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller.
 *
 */
static int usb_hcd_fsl_probe(const struct hc_driver *driver,
			     struct platform_device *pdev)
{
	struct arc_usb_config *pdata;
	struct usb_hcd *hcd;
	struct resource *res;
	int irq;
	int retval;

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

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

	retval = fsl_platform_verify(pdev);
	if (retval)
		return retval;

	/*
	 * do platform specific init: check the clock, grab/config pins, etc.
	 */
	if (pdata->platform_init && pdata->platform_init()) {
		retval = -ENODEV;
		goto err1;
	}

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

	if (pdata->set_vbus_power)
		pdata->set_vbus_power(1);

	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
	if (!hcd) {
		retval = -ENOMEM;
		goto err1;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev,
			"Found HC with no register addr. Check %s setup!\n",
			pdev->dev.bus_id);
		retval = -ENODEV;
		goto err2;
	}
	hcd->rsrc_start = res->start;
	hcd->rsrc_len = res->end - res->start + 1;

	vdbg("start=0x%x   end=0x%x    rsrc_start=0x%llx  rsrc_len=0x%llx\n",
	     res->start, res->end, hcd->rsrc_start, hcd->rsrc_len);

	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
				driver->description)) {
		dev_dbg(&pdev->dev, "request_mem_region failed\n");
		retval = -EBUSY;
		goto err2;
	}
	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);

	if (hcd->regs == NULL) {
		dev_dbg(&pdev->dev, "error mapping memory\n");
		retval = -EFAULT;
		goto err3;
	}

	hcd->power_budget = pdata->power_budget;

	/* DDD
	 * the following must be done by this point, otherwise the OTG
	 * host port doesn't make it thru initializtion.
	 * ehci_halt(), called by ehci_fsl_setup() returns -ETIMEDOUT
	 */
	fsl_platform_set_host_mode(hcd);

	retval = usb_add_hcd(hcd, irq, SA_SHIRQ);
	if (retval != 0)
		goto err4;

#if defined(CONFIG_USB_OTG)
	if (pdata->does_otg) {
		struct ehci_hcd *ehci = hcd_to_ehci(hcd);

		dbg("pdev=0x%p  hcd=0x%p  ehci=0x%p\n", pdev, hcd, ehci);

		ehci->transceiver = otg_get_transceiver();
		dbg("ehci->transceiver=0x%p\n", ehci->transceiver);

		if (ehci->transceiver) {
			retval = otg_set_host(ehci->transceiver,
					      &ehci_to_hcd(ehci)->self);
			dev_dbg(ehci->transceiver->dev,
				"init %s transceiver, retval %d\n",
				ehci->transceiver->label, retval);
			if (retval) {
				if (ehci->transceiver)
					put_device(ehci->transceiver->dev);
				goto err3;
			}
		} else {
			printk(KERN_ERR "can't find transceiver\n");
			retval = -ENODEV;
			goto err3;
		}
	}
#endif

	return retval;

      err4:
	iounmap(hcd->regs);
      err3:
	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
      err2:
	usb_put_hcd(hcd);
      err1:
	dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
	if (pdata->platform_uninit)
		pdata->platform_uninit();
	return retval;
}
Exemplo n.º 4
0
/**
 * usb_hcd_fsl_probe - initialize FSL-based HCDs
 * @drvier: Driver to be used for this HCD
 * @pdev: USB Host Controller being probed
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller.
 *
 */
static int usb_hcd_fsl_probe(const struct hc_driver *driver,
			     struct platform_device *pdev)
{
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
	struct usb_hcd *hcd;
	struct resource *res;
	int irq;
	int retval;

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

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

	retval = fsl_platform_verify(pdev);
	if (retval)
		return retval;

	/*
	 * do platform specific init: check the clock, grab/config pins, etc.
	 */
	if (pdata->platform_init && pdata->platform_init(pdev)) {
		retval = -ENODEV;
		goto err1;
	}

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

	fsl_platform_set_vbus_power(pdata, 1);

	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
	if (!hcd) {
		retval = -ENOMEM;
		goto err1;
	}

	hcd->rsrc_start = pdata->r_start;
	hcd->rsrc_len = pdata->r_len;
	hcd->regs = pdata->regs;
	vdbg("rsrc_start=0x%llx rsrc_len=0x%llx virtual=0x%x\n",
	     hcd->rsrc_start, hcd->rsrc_len, hcd->regs);

	hcd->power_budget = pdata->power_budget;

	/* DDD
	 * the following must be done by this point, otherwise the OTG
	 * host port doesn't make it thru initializtion.
	 * ehci_halt(), called by ehci_fsl_setup() returns -ETIMEDOUT
	 */
	fsl_platform_set_host_mode(hcd);

	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
	if (retval != 0) {
		pr_debug("failed with usb_add_hcd\n");
		goto err2;
	}
#if defined(CONFIG_USB_OTG)
	if (pdata->does_otg) {
		struct ehci_hcd *ehci = hcd_to_ehci(hcd);

		dbg("pdev=0x%p  hcd=0x%p  ehci=0x%p\n", pdev, hcd, ehci);

		ehci->transceiver = otg_get_transceiver();
		dbg("ehci->transceiver=0x%p\n", ehci->transceiver);

		if (ehci->transceiver) {
			retval = otg_set_host(ehci->transceiver,
					      &ehci_to_hcd(ehci)->self);
			if (retval) {
				if (ehci->transceiver)
					put_device(ehci->transceiver->dev);
				goto err2;
			}
		} else {
			printk(KERN_ERR "can't find transceiver\n");
			retval = -ENODEV;
			goto err2;
		}
	}
#endif

	return retval;

err2:
	usb_put_hcd(hcd);
err1:
	dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
	if (pdata->platform_uninit)
		pdata->platform_uninit(pdata);
	return retval;
}
Exemplo n.º 5
0
static int ehci_fsl_drv_resume(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct usb_device *roothub = hcd->self.root_hub;
	u32 tmp;
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
	struct fsl_usb2_wakeup_platform_data *wake_up_pdata = pdata->wakeup_pdata;
	/* Only handles OTG mode switch event */
	printk(KERN_DEBUG "ehci fsl drv resume begins: %s\n", pdata->name);
	if (pdata->pmflags == 0) {
		printk(KERN_DEBUG "%s,pm event, wait for wakeup irq if needed\n", __func__);
		wait_event_interruptible(wake_up_pdata->wq, !wake_up_pdata->usb_wakeup_is_pending);
		if (!host_can_wakeup_system(pdev)) {
			if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
				fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
			}
			usb_host_set_wakeup(hcd->self.controller, true);

			if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
				fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
			}
		}
		return 0;
	}
	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
		fsl_usb_clk_gate(hcd->self.controller->platform_data, true);
		usb_host_set_wakeup(hcd->self.controller, false);
		fsl_usb_lowpower_mode(pdata, false);
	}

	/* set host mode */
	fsl_platform_set_host_mode(hcd);

	/* restore EHCI registers */
	ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);
	ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
	ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
	ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index);
	ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment);
	ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list);
	ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next);
	ehci_writel(ehci, pdata->pm_configured_flag,
		    &ehci->regs->configured_flag);


	tmp = ehci_readl(ehci, &ehci->regs->command);
	tmp |= CMD_RUN;
	ehci_writel(ehci, tmp, &ehci->regs->command);

	if ((hcd->state & HC_STATE_SUSPENDED)) {
		printk(KERN_DEBUG "will resume roothub and its children\n");
		usb_lock_device(roothub);
		usb_resume(&roothub->dev, PMSG_USER_RESUME);
		usb_unlock_device(roothub);
	}
	pdata->pmflags = 0;
	printk(KERN_DEBUG "ehci fsl drv resume ends: %s\n", pdata->name);

	return 0;
}
Exemplo n.º 6
0
/**
 * usb_hcd_fsl_probe - initialize FSL-based HCDs
 * @drvier: Driver to be used for this HCD
 * @pdev: USB Host Controller being probed
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller.
 *
 */
int usb_hcd_fsl_probe(const struct hc_driver *driver,
		      struct platform_device *pdev)
{
	struct fsl_usb2_platform_data *pdata;
	struct usb_hcd *hcd;
	struct resource *res;
	int irq;
	int retval;

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

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

	/*
	 * This is a host mode driver, verify that we're supposed to be
	 * in host mode.
	 */
	if (!((pdata->operating_mode == FSL_USB2_DR_HOST) ||
	      (pdata->operating_mode == FSL_USB2_MPH_HOST) ||
	      (pdata->operating_mode == FSL_USB2_DR_OTG))) {
		dev_err(&pdev->dev,
			"Non Host Mode configured for %s. Wrong driver linked.\n",
			dev_name(&pdev->dev));
		return -ENODEV;
	}

	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
	if (!hcd) {
		retval = -ENOMEM;
		goto err1;
	}

	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;
	}
	irq = res->start;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);

	if (pdata->operating_mode != FSL_USB2_DR_OTG) {
		if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
					driver->description)) {
			dev_dbg(&pdev->dev, "controller already in use\n");
			retval = -EBUSY;
			goto err2;
		}
	}

	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);

	if (hcd->regs == NULL) {
		dev_dbg(&pdev->dev, "error mapping memory\n");
		retval = -EFAULT;
		goto err3;
	}
	pdata->regs = hcd->regs;

	/*
	 * do platform specific init: check the clock, grab/config pins, etc.
	 */
	if (pdata->init && pdata->init(pdev)) {
		retval = -ENODEV;
		goto err3;
	}

	fsl_platform_set_host_mode(hcd);
	hcd->power_budget = pdata->power_budget;

	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
	if (retval != 0)
		goto err4;

	if (pdata->operating_mode == FSL_USB2_DR_OTG) {
		struct ehci_hcd *ehci = hcd_to_ehci(hcd);

		dbg("pdev=0x%p  hcd=0x%p  ehci=0x%p\n", pdev, hcd, ehci);

		ehci->transceiver = otg_get_transceiver();
		dbg("ehci->transceiver=0x%p\n", ehci->transceiver);

		if (!ehci->transceiver) {
			printk(KERN_ERR "can't find transceiver\n");
			retval = -ENODEV;
			goto err5;
		}

		retval = otg_set_host(ehci->transceiver, &ehci_to_hcd(ehci)->self);
		if (retval)
			otg_put_transceiver(ehci->transceiver);
	} else if ((pdata->operating_mode == FSL_USB2_MPH_HOST) || \
			(pdata->operating_mode == FSL_USB2_DR_HOST))
		fsl_platform_set_vbus_power(pdata, 1);

	fsl_platform_set_ahb_burst(hcd);
	ehci_testmode_init(hcd_to_ehci(hcd));
	return retval;
err5:
	usb_remove_hcd(hcd);
err4:
	iounmap(hcd->regs);
err3:
	if (pdata->operating_mode != FSL_USB2_DR_OTG)
		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err2:
	usb_put_hcd(hcd);
err1:
	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
	if (pdata->exit)
		pdata->exit(pdata->pdev);
	return retval;
}
Exemplo n.º 7
0
static int ehci_fsl_drv_resume(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	u32 tmp;
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

	pr_debug("%s('%s'): suspend=%d already_suspended=%d\n", __func__,
		pdata->name, pdata->suspended, pdata->already_suspended);

	/*
	 * If the controller was already suspended at suspend time,
	 * then don't resume it now.
	 */
	if (pdata->already_suspended) {
		pr_debug("already suspended, leaving early\n");
		pdata->already_suspended = 0;
		return 0;
	}

	if (!pdata->suspended) {
		pr_debug("not suspended, leaving early\n");
		return 0;
	}

	/* If hcd is resumed by non-usb wakeup events,
	 * then usb clocks are still not open when come here */
	if (device_may_wakeup(&(pdev->dev))) {
		/* Need open clock for register access */
		if (pdata->usb_clock_for_pm)
			pdata->usb_clock_for_pm(true);
	}

	tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);

	pdata->suspended = 0;

	pr_debug("%s resuming...\n", __func__);

	/* set host mode */
	fsl_platform_set_host_mode(hcd);

	if (pdata->platform_resume)
		pdata->platform_resume(pdata);

	/* restore EHCI registers */
	ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);
	ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
	ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
	ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index);
	ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment);
	ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list);
	ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next);
	ehci_writel(ehci, pdata->pm_configured_flag,
		    &ehci->regs->configured_flag);

	/* set bit should be done by wakeup irq routine if may wakeup */
	if (!device_may_wakeup(&(pdev->dev)))
		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	else
		while (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
			msleep(1);

	pdev->dev.power.power_state = PMSG_ON;

	tmp = ehci_readl(ehci, &ehci->regs->command);
	tmp |= CMD_RUN;
	ehci_writel(ehci, tmp, &ehci->regs->command);

	usb_hcd_resume_root_hub(hcd);

	printk(KERN_INFO "USB Host resumed\n");

	if (device_may_wakeup(&(pdev->dev))) {
		if (pdata->usb_clock_for_pm)
			pdata->usb_clock_for_pm(false);
	}

	return 0;
}
Exemplo n.º 8
0
/**
 * usb_hcd_fsl_probe - initialize FSL-based HCDs
 * @drvier: Driver to be used for this HCD
 * @pdev: USB Host Controller being probed
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller.
 *
 */
static int usb_hcd_fsl_probe(const struct hc_driver *driver,
                             struct platform_device *pdev)
{
    struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
    struct usb_hcd *hcd;
    struct resource *res;
    int irq;
    int retval;
    u32 temp;

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

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

    /*
     * This is a host mode driver, verify that we're supposed to be
     * in host mode.
     */
    if (!((pdata->operating_mode == FSL_USB2_DR_HOST) ||
            (pdata->operating_mode == FSL_USB2_MPH_HOST) ||
            (pdata->operating_mode == FSL_USB2_DR_OTG))) {
        dev_err(&pdev->dev,
                "Non Host Mode configured for %s. "
                "Wrong driver linked.\n", pdev->dev.bus_id);
        return -ENODEV;
    }

    hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
    if (!hcd) {
        retval = -ENOMEM;
        goto err1;
    }

#if defined(CONFIG_USB_OTG)
    if (pdata->operating_mode == FSL_USB2_DR_OTG) {
        res = otg_get_resources();
        if (!res) {
            dev_err(&pdev->dev,
                    "Found HC with no IRQ. Check %s setup!\n",
                    pdev->dev.bus_id);
            return -ENODEV;
        }
        irq = res[1].start;
        hcd->rsrc_start = res[0].start;
        hcd->rsrc_len = res[0].end - res[0].start + 1;
    } else
#endif
    {
        if ((pdev->dev.parent) &&
                (to_platform_device(pdev->dev.parent)->resource)) {
            pdev->resource =
                to_platform_device(pdev->dev.parent)->resource;
            pdev->num_resources =
                to_platform_device(pdev->dev.parent)->num_resources;
        }

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

        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        hcd->rsrc_start = res->start;
        hcd->rsrc_len = resource_size(res);

        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
                                driver->description)) {
            dev_dbg(&pdev->dev, "controller already in use\n");
            retval = -EBUSY;
            goto err2;
        }
    }

    if (!(pdata->port_enables & FSL_USB2_DONT_REMAP)) {
        hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);

        if (hcd->regs == NULL) {
            dev_dbg(&pdev->dev, "error mapping memory\n");
            retval = -EFAULT;
            goto err3;
        }
        regs_remapped = 1;
    } else
        hcd->regs = (void __iomem *)(u32)(hcd->rsrc_start);

    pdata->regs = hcd->regs;

    /*
     * do platform specific init: check the clock, grab/config pins, etc.
     */
    if (pdata->platform_init && pdata->platform_init(pdev)) {
        retval = -ENODEV;
        goto err3;
    }

    fsl_platform_set_host_mode(hcd);
    hcd->power_budget = pdata->power_budget;

    retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
    if (retval != 0)
        goto err4;

    fsl_platform_set_vbus_power(pdata, 1);

#ifdef CONFIG_USB_OTG
    if (pdata->operating_mode == FSL_USB2_DR_OTG) {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);

        dbg("pdev=0x%p  hcd=0x%p  ehci=0x%p\n", pdev, hcd, ehci);

        ehci->transceiver = otg_get_transceiver();
        dbg("ehci->transceiver=0x%p\n", ehci->transceiver);

        if (ehci->transceiver) {
            retval = otg_set_host(ehci->transceiver,
                                  &ehci_to_hcd(ehci)->self);
            if (retval) {
                if (ehci->transceiver)
                    put_device(ehci->transceiver->dev);
                goto err4;
            }
        } else {
            printk(KERN_ERR "can't find transceiver\n");
            retval = -ENODEV;
            goto err4;
        }
    }
#endif

    fsl_platform_set_ahb_burst(hcd);
    ehci_testmode_init(hcd_to_ehci(hcd));
    return retval;

err4:
    if (regs_remapped)
        iounmap(hcd->regs);
err3:
    if (pdata->operating_mode != FSL_USB2_DR_OTG)
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err2:
    usb_put_hcd(hcd);
err1:
    dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
    if (pdata->platform_uninit)
        pdata->platform_uninit(pdata);
    return retval;
}