Exemple #1
0
static int ehci_arc_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;

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

	vdbg("%s ehci->regs=0x%p  hcd->regs=0x%p  usbmode=0x%x\n",
	     __FUNCTION__, ehci->regs, hcd->regs, pdata->usbmode);

	tmp = USBMODE_CM_HOST;
	if (ehci_big_endian_mmio(ehci))
		tmp |= USBMODE_BE;

	ehci_writel(ehci, tmp, (u32 *)pdata->usbmode);

	memcpy(ehci->regs, (void *)&usb_ehci_regs, sizeof(struct ehci_regs));

	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);

	fsl_platform_set_vbus_power(pdata, 1);

	usb_hcd_resume_root_hub(hcd);

	return 0;
}
Exemple #2
0
static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
			       struct platform_device *pdev)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

	dbg("%s  hcd=0x%p\n", __FUNCTION__, hcd);

	/* DDD shouldn't we turn off the power here? */
	fsl_platform_set_vbus_power(pdata, 0);

	usb_remove_hcd(hcd);

	if (ehci->transceiver) {
		(void)otg_set_host(ehci->transceiver, 0);
		put_device(ehci->transceiver->dev);
	}
	usb_put_hcd(hcd);

	/*
	 * do platform specific un-initialization:
	 * release iomux pins, etc.
	 */
	if (pdata->platform_uninit)
		pdata->platform_uninit(pdata);
}
Exemple #3
0
/* These routines rely on the bus (pci, platform, etc)
 * to handle powerdown and wakeup, and currently also on
 * transceivers that don't need any software attention to set up
 * the right sort of wakeup.
 *
 * They're also used for turning on/off the port when doing OTG.
 */
static int ehci_arc_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
	u32 cmd;

	pr_debug("%s pdev=0x%p  ehci=0x%p  hcd=0x%p\n",
		 __FUNCTION__, pdev, ehci, hcd);
	pr_debug("%s ehci->regs=0x%p  hcd->regs=0x%p  hcd->state=%d\n",
		 __FUNCTION__, ehci->regs, hcd->regs, hcd->state);

	hcd->state = HC_STATE_SUSPENDED;
	pdev->dev.power.power_state = PMSG_SUSPEND;

	if (hcd->driver->suspend)
		return hcd->driver->suspend(hcd, state);

	/* ignore non-host interrupts */
	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);

	cmd = ehci_readl(ehci, &ehci->regs->command);
	cmd &= ~CMD_RUN;
	ehci_writel(ehci, cmd, &ehci->regs->command);

	memcpy((void *)&usb_ehci_regs, ehci->regs, sizeof(struct ehci_regs));
	usb_ehci_regs.port_status[0] &=
	    cpu_to_le32(~(PORT_PEC | PORT_OCC | PORT_CSC));

	fsl_platform_set_vbus_power(pdata, 0);

	return 0;
}
/**
 * usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs
 * @dev: USB Host Controller being removed
 * Context: !in_interrupt()
 *
 * Reverses the effect of usb_hcd_fsl_probe().
 *
 */
static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
                               struct platform_device *pdev)
{
    struct ehci_hcd *ehci = hcd_to_ehci(hcd);
    struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;

    /* DDD shouldn't we turn off the power here? */
    fsl_platform_set_vbus_power(pdata, 0);

    if (ehci->transceiver) {
        (void)otg_set_host(ehci->transceiver, 0);
        put_device(ehci->transceiver->dev);
    } else {
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
    }

    usb_remove_hcd(hcd);
    usb_put_hcd(hcd);

    /*
     * do platform specific un-initialization:
     * release iomux pins, etc.
     */
    if (pdata->platform_uninit)
        pdata->platform_uninit(pdata);

    iounmap(hcd->regs);
}
Exemple #5
0
/*! arc_udc_init
 */
static struct arcotg_udc *arc_udc_init (struct otg_dev *otg_dev)
{
        struct device           *device = otg_dev_get_drvdata(otg_dev);
        struct platform_device  *pdev = to_platform_device(device);

        struct fsl_usb2_platform_data *pdata = (struct fsl_usb2_platform_data*)pdev->dev.platform_data;

        struct otg_instance     *otg = otg_dev->otg_instance;
        struct pcd_instance     *pcd = otg_dev->pcd_instance;
        struct arcotg_udc       *udc = NULL;
        int                     timeout;


        /* Setting up the udc structure */
        THROW_UNLESS((udc = (struct arcotg_udc *) CKMALLOC(sizeof(struct arcotg_udc))), error);

        /* Allocate queue */
        THROW_UNLESS((udc->ep_qh = (struct ep_queue_head *) KMALLOC_ALIGN(    USB_MAX_PIPES * sizeof(struct ep_queue_head),
                                        GFP_KERNEL | GFP_DMA, 2 * 1024, (void **)&ep_qh_base)), error);
        THROW_UNLESS(ep_qh_base, error);
        THROW_UNLESS((udc->ep_dtd = (struct ep_td_struct *) CKMALLOC(USB_MAX_PIPES * sizeof(struct ep_td_struct))), error);

        /* Stop, reset and wait for the UDC to reset */
        UOG_USBCMD &= ~USB_CMD_RUN_STOP;
        UOG_USBCMD |= USB_CMD_CTRL_RESET;

        timeout = 10000000;     // XXX This needs to be fixed, should not need to resort to timeout
        while ((UOG_USBCMD & USB_CMD_CTRL_RESET) && --timeout) { continue; }
        if (timeout == 0) {
                printk(KERN_DEBUG "%s: TIMEOUT\n", __FUNCTION__);
                return NULL;
        }

        /* Setup UDC mode and disable lock out mode*/
        UOG_USBMODE |= USB_MODE_CTRL_MODE_DEVICE | USB_MODE_SETUP_LOCK_OFF;

        UOG_EPLISTADDR = virt_to_phys(udc->ep_qh);
        UOG_EPLISTADDR &= USB_EP_LIST_ADDRESS_MASK;

        /* Setup transceiver type, N.B. this must be done in one assignment */
        UOG_PORTSC1 = (UOG_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | pdata->xcvr_type;

        #if !defined(CONFIG_OTG_HIGH_SPEED)
        UOG_PORTSC1 |= (0x01000000);
        #endif
	fsl_platform_set_vbus_power(pdata, 0);

        CATCH(error) {
                if (ep_qh_base) kfree(ep_qh_base);
                if (udc) {
                        if (udc->ep_dtd) LKFREE(udc->ep_dtd);
                        LKFREE(udc);
                }
                udc = NULL;
        }
        return udc;
}
Exemple #6
0
/**
 * usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs
 * @dev: USB Host Controller being removed
 * Context: !in_interrupt()
 *
 * Reverses the effect of usb_hcd_fsl_probe().
 *
 */
static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
			       struct platform_device *pdev)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
	u32 tmp;

	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
		/* 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]);
		if (tmp & PORT_PTS_PHCD) {
			tmp &= ~PORT_PTS_PHCD;
			ehci_writel(ehci, tmp, &ehci->regs->port_status[0]);
			msleep(100);

			if (pdata->usb_clock_for_pm)
				pdata->usb_clock_for_pm(false);
		}
	}

	/* DDD shouldn't we turn off the power here? */
	fsl_platform_set_vbus_power(pdata, 0);

	if (ehci->transceiver) {
		(void)otg_set_host(ehci->transceiver, 0);
		otg_put_transceiver(ehci->transceiver);
	} else {
		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
	}

	usb_remove_hcd(hcd);
	usb_put_hcd(hcd);

	/*
	 * do platform specific un-initialization:
	 * release iomux pins, etc.
	 */
	if (pdata->exit)
		pdata->exit(pdata->pdev);

	iounmap(hcd->regs);
}
Exemple #7
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;
}
Exemple #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.
 *
 */
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;
}
Exemple #9
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;
}