Exemplo n.º 1
0
static int tegra_ehci_remove(struct platform_device *pdev)
{
	struct tegra_hcd_platform_data *pdata = pdev->dev.platform_data;
	struct usb_hcd *hcd = platform_get_drvdata(pdev);

	if (pdata == NULL || hcd == NULL)
		return -EINVAL;

	usb_remove_hcd(hcd);
	usb_put_hcd(hcd);

#ifdef CONFIG_DMABOUNCE
	dmabounce_unregister_dev(&pdev->dev);
#endif

	NvDdkUsbPhyClose(pdata->hUsbPhy);

	iounmap(hcd->regs);


	if (pdata->gpio_nr)
		gpio_free(pdata->gpio_nr);

	return 0;
}
Exemplo n.º 2
0
static int __exit tegra_otg_remove(struct platform_device *pdev)
{
	struct tegra_otg_data *tegra_otg = platform_get_drvdata(pdev);

	otg_set_transceiver(NULL);
	free_irq(tegra_otg->irq, &pdev->dev);
	iounmap(tegra_otg->regs);
	NvDdkUsbPhyClose(tegra_otg->usb_phy);
	platform_set_drvdata(pdev, NULL);
	kfree(tegra_otg);
	sg_tegra_otg = NULL;

	return 0;
}
Exemplo n.º 3
0
static int tegra_ehci_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct tegra_hcd_platform_data *pdata = pdev->dev.platform_data;
	struct usb_hcd *hcd;
	int e = 0;
	int irq;
	unsigned int temp;
	struct ehci_hcd *ehci;

	if (!pdata) {
		dev_err(&pdev->dev, "platform data must be specified\n");
		return -EINVAL;
	}

	WARN_ON(!pdev->dev.coherent_dma_mask || !pdev->dev.dma_mask);

	hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
					dev_name(&pdev->dev));
	if (IS_ERR_OR_NULL(hcd)) {
		dev_err(&pdev->dev, "Unable to create HCD\n");
		return -ENOMEM;
	}

	if (pdata->id_detect == ID_PIN_GPIO) {
		e = gpio_request(pdata->gpio_nr, dev_name(&pdev->dev));
		if (e < 0) {
			dev_err(&pdev->dev, "request ID pin GPIO failed\n");
			goto fail_hcd;
		}

		e = gpio_direction_input(pdata->gpio_nr);
		if (e < 0) {
			dev_err(&pdev->dev, "failed to set ID pin as input\n");
			goto fail_gpio;
		}
	}

	INIT_WORK(&pdata->work, tegra_ehci_busy_hint_work);

	/* Init the tegra USB phy */
	if (NvDdkUsbPhyOpen(s_hRmGlobal, pdata->instance,
			    &pdata->hUsbPhy) != NvSuccess) {
		dev_err(&pdev->dev, "failed to open USB phy DDK\n");
		e = -ENODEV;
		goto fail_gpio;
	}
	tegra_ehci_power_up(hcd);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "failed to get I/O memory\n");
		e = -ENXIO;
		goto fail_phy;
	}
	if (!pdata->otg_mode) {
		res = request_mem_region(res->start, resource_size(res),
					 dev_name(&pdev->dev));
		if (!res) {
			dev_err(&pdev->dev, "resource in use\n");
			e = -EBUSY;
			goto fail_phy;
		}
	}
	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);
	hcd->regs = ioremap(res->start, resource_size(res));
	if (!hcd->regs) {
		e = -ENOMEM;
		goto fail_mem;
	}

	/* Set to Host mode by setting bit 0-1 of USB device mode register */
	temp = readl(hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET);
	writel((temp | TEGRA_USB_USBMODE_HOST),
			(hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET));
	irq = platform_get_irq(pdev, 0);
	if (!irq) {
		e = -ENODEV;
		goto fail_iomap;
	}

	set_irq_flags(irq, IRQF_VALID);

	ehci = hcd_to_ehci(hcd);
	INIT_WORK(&ehci->irq_work, tegra_ehci_irq_work);

	e = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
	if (e != 0) {
		dev_err(&pdev->dev, "failed to add HCD\n");
		goto fail_iomap;
	}
	platform_set_drvdata(pdev, hcd);

#ifdef CONFIG_DMABOUNCE
	e = dmabounce_register_dev(&pdev->dev, 1024, 32768);
	if (e != 0) {
		dev_err(&pdev->dev, "failed to register DMA bounce\n");
		goto fail_add;
	}
#endif

#ifdef CONFIG_USB_OTG_UTILS
	if (pdata->otg_mode) {
		ehci->transceiver = otg_get_transceiver();
		if (!ehci->transceiver) {
			dev_err(&pdev->dev, "Failed to get OTG transceiver\n");
			e = -ENODEV;
			goto fail_dmabounce;
		}

		otg_set_host(ehci->transceiver, (struct usb_bus *)hcd);
		/* Stop the controller and power down the phy, OTG will
		 * start the host driver based on the ID pin
		 * detection */
		ehci_halt(ehci);
		/* reset the host and put the controller in idle mode */
		temp = ehci_readl(ehci, &ehci->regs->command);
		temp |= CMD_RESET;
		ehci_writel(ehci, temp, &ehci->regs->command);
		temp = readl(hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET);
		writel((temp & ~TEGRA_USB_USBMODE_HOST),
			(hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET));
		/* indicate hcd flags, that hardware is not accessable now
		 * in host mode*/
		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
		tegra_ehci_power_down(hcd);
		ehci->host_reinited = 0;
	} else
#endif
	{
		if (pdata->id_detect == ID_PIN_CABLE_ID) {
			/* enable the cable ID interrupt */
			temp = readl(hcd->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET);
			temp |= TEGRA_USB_ID_INT_ENABLE;
			temp |= TEGRA_USB_ID_PIN_WAKEUP_ENABLE;
			writel(temp, (hcd->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET));

			/* Check if we detect any device connected */
			if (temp & TEGRA_USB_ID_PIN_STATUS) {
				tegra_ehci_power_down(hcd);
			} else {
				tegra_ehci_power_up(hcd);
			}
		}
	}

	return 0;

fail_dmabounce:
#ifdef CONFIG_DMABOUNCE
	dmabounce_unregister_dev(&pdev->dev);
#endif
fail_add:
	usb_remove_hcd(hcd);
fail_iomap:
	iounmap(hcd->regs);
fail_mem:
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	release_mem_region(res->start, resource_size(res));
fail_phy:
	NvDdkUsbPhyClose(pdata->hUsbPhy);
fail_gpio:
	if (pdata->gpio_nr)
		gpio_free(pdata->gpio_nr);
fail_hcd:
	usb_put_hcd(hcd);
	return e;
}
Exemplo n.º 4
0
/* platform driver interface */
static int __devinit tegra_otg_probe(struct platform_device *pdev)
{
	int err = 0;
	struct resource *res;
	int instance = pdev->id;
	NvError e;
	struct tegra_otg_platform_data *pdata;

	sg_tegra_otg = kzalloc(sizeof(struct tegra_otg_data), GFP_KERNEL);
	if (!sg_tegra_otg)
		return -ENOMEM;

	spin_lock_init(&sg_tegra_otg->lock);
	platform_set_drvdata(pdev, sg_tegra_otg);

	NV_CHECK_ERROR_CLEANUP(
		NvDdkUsbPhyOpen(s_hRmGlobal, instance, &sg_tegra_otg->usb_phy)
	);
	NV_CHECK_ERROR_CLEANUP(
		NvDdkUsbPhyPowerUp(sg_tegra_otg->usb_phy, NV_FALSE, 0)
	);
	sg_tegra_otg->instance = pdev->id;
	sg_tegra_otg->dev = &pdev->dev;
	sg_tegra_otg->otg.label = driver_name;
	sg_tegra_otg->otg.state = OTG_STATE_UNDEFINED;
	sg_tegra_otg->otg.set_peripheral = tegra_otg_set_peripheral;
	sg_tegra_otg->otg.set_host = tegra_otg_set_host;
	sg_tegra_otg->otg.set_power = tegra_otg_set_power;
	sg_tegra_otg->otg.set_suspend = tegra_otg_set_suspend;
	pdata = sg_tegra_otg->dev->platform_data;
	if(pdata->usb_property->IdPinDetectionType == NvOdmUsbIdPinType_CableId)
		sg_tegra_otg->id_connected = 1;
	if(pdata->usb_property->UseInternalPhyWakeup)
		sg_tegra_otg->vbus_connected = 1;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		err = -ENXIO;
		goto err_irq;
	}

	sg_tegra_otg->regs = ioremap(res->start, resource_size(res));
	if (!sg_tegra_otg->regs) {
		err = -ENOMEM;
		goto err_irq;
	}

	sg_tegra_otg->irq = platform_get_irq(pdev, 0);
	if (!sg_tegra_otg->irq) {
		err = -ENODEV;
		goto err_irq;
	}

	err = request_irq(sg_tegra_otg->irq, tegra_otg_irq, IRQF_SHARED,
			driver_name, pdev);
	if (err) {
		printk("cannot request irq %d err %d\n",
				sg_tegra_otg->irq, err);
		goto err_mem_map;
	}

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

	NvDdkUsbPhyPowerDown(sg_tegra_otg->usb_phy, NV_FALSE, 0);

	return 0;

err_otg:
	free_irq(sg_tegra_otg->irq, &pdev->dev);
err_mem_map:
	iounmap(sg_tegra_otg->regs);
err_irq:
	NvDdkUsbPhyClose(sg_tegra_otg->usb_phy);
fail:
	platform_set_drvdata(pdev, NULL);
	kfree(sg_tegra_otg);
	return err;
}
NvError
NvDdkUsbPhyOpen(
    NvRmDeviceHandle hRm,
    NvU32 Instance,
    NvDdkUsbPhyHandle *hUsbPhy)
{
    NvError e;
    NvU32 MaxInstances = 0;
    NvDdkUsbPhy *pUsbPhy = NULL;
    NvOsMutexHandle UsbPhyMutex = NULL;
    NvRmModuleInfo info[MAX_USB_INSTANCES];
    NvU32 j;

    NV_ASSERT(hRm);
    NV_ASSERT(hUsbPhy);
    NV_ASSERT(Instance < MAX_USB_INSTANCES);

    NV_CHECK_ERROR(NvRmModuleGetModuleInfo( hRm, NvRmModuleID_Usb2Otg, &MaxInstances, NULL ));
    if (MaxInstances > MAX_USB_INSTANCES)
    {
       // Ceil "instances" to MAX_USB_INSTANCES
       MaxInstances = MAX_USB_INSTANCES;
    }
    NV_CHECK_ERROR(NvRmModuleGetModuleInfo( hRm, NvRmModuleID_Usb2Otg, &MaxInstances, info ));
    for (j = 0; j < MaxInstances; j++)
    {
    // Check whether the requested instance is present
        if(info[j].Instance == Instance)
            break;
    }
    // No match found return
    if (j == MaxInstances)
    {
        return NvError_ModuleNotPresent;
    }

    if (!s_UsbPhyMutex)
    {
        e = NvOsMutexCreate(&UsbPhyMutex);
        if (e!=NvSuccess)
            return e;

        if (NvOsAtomicCompareExchange32(
                (NvS32*)&s_UsbPhyMutex, 0, (NvS32)UsbPhyMutex)!=0)
        {
            NvOsMutexDestroy(UsbPhyMutex);
        }
    }

    NvOsMutexLock(s_UsbPhyMutex);
    if (!s_pUsbPhy)
    {
        s_pUsbPhy = NvOsAlloc(MaxInstances * sizeof(NvDdkUsbPhy));
        if (s_pUsbPhy)
            NvOsMemset(s_pUsbPhy, 0, MaxInstances * sizeof(NvDdkUsbPhy));
    }
    NvOsMutexUnlock(s_UsbPhyMutex);

    if (!s_pUsbPhy)
        return NvError_InsufficientMemory;

    NvOsMutexLock(s_UsbPhyMutex);
    if (!s_pUtmiPadConfig)
    {
        s_pUtmiPadConfig = NvOsAlloc(sizeof(NvDdkUsbPhyUtmiPadConfig));
        if (s_pUtmiPadConfig)
        {
            NvRmPhysAddr PhyAddr;

            NvOsMemset(s_pUtmiPadConfig, 0, sizeof(NvDdkUsbPhyUtmiPadConfig));
            NvRmModuleGetBaseAddress(
                hRm, 
                NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, 0),
                &PhyAddr, &s_pUtmiPadConfig->BankSize);

            NV_CHECK_ERROR_CLEANUP(
                NvRmPhysicalMemMap(
                    PhyAddr, s_pUtmiPadConfig->BankSize, NVOS_MEM_READ_WRITE,
                    NvOsMemAttribute_Uncached, (void **)&s_pUtmiPadConfig->pVirAdr));
        }
    }
    NvOsMutexUnlock(s_UsbPhyMutex);

    if (!s_pUtmiPadConfig)
        return NvError_InsufficientMemory;

    pUsbPhy = &s_pUsbPhy[Instance];

    NvOsMutexLock(s_UsbPhyMutex);
    if (!pUsbPhy->RefCount)
    {
        NvRmPhysAddr PhysAddr;
        NvOsMutexHandle ThreadSafetyMutex = NULL;

        NvOsMemset(pUsbPhy, 0, sizeof(NvDdkUsbPhy));
        pUsbPhy->Instance = Instance;
        pUsbPhy->hRmDevice = hRm;
        pUsbPhy->RefCount = 1;
        pUsbPhy->IsPhyPoweredUp = NV_FALSE;
        pUsbPhy->pUtmiPadConfig = s_pUtmiPadConfig;
        pUsbPhy->pProperty = NvOdmQueryGetUsbProperty(
                                    NvOdmIoModule_Usb, pUsbPhy->Instance);
        pUsbPhy->TurnOffPowerRail = UsbPhyTurnOffPowerRail(MaxInstances);

        NV_CHECK_ERROR_CLEANUP(NvOsMutexCreate(&ThreadSafetyMutex));
        if (NvOsAtomicCompareExchange32(
                (NvS32*)&pUsbPhy->ThreadSafetyMutex, 0,
                (NvS32)ThreadSafetyMutex)!=0)
        {
            NvOsMutexDestroy(ThreadSafetyMutex);
        }

        NvRmModuleGetBaseAddress(
            pUsbPhy->hRmDevice,
            NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, pUsbPhy->Instance),
            &PhysAddr, &pUsbPhy->UsbBankSize);

        NV_CHECK_ERROR_CLEANUP(
            NvRmPhysicalMemMap(
                PhysAddr, pUsbPhy->UsbBankSize, NVOS_MEM_READ_WRITE,
                NvOsMemAttribute_Uncached, (void **)&pUsbPhy->UsbVirAdr));

        NvRmModuleGetBaseAddress(
            pUsbPhy->hRmDevice,
            NVRM_MODULE_ID(NvRmModuleID_Misc, 0),
            &PhysAddr, &pUsbPhy->MiscBankSize);

        NV_CHECK_ERROR_CLEANUP(
            NvRmPhysicalMemMap(
                PhysAddr, pUsbPhy->MiscBankSize, NVOS_MEM_READ_WRITE,
                NvOsMemAttribute_Uncached, (void **)&pUsbPhy->MiscVirAdr));

        if ( ( pUsbPhy->pProperty->UsbInterfaceType ==
               NvOdmUsbInterfaceType_UlpiNullPhy) ||
             ( pUsbPhy->pProperty->UsbInterfaceType ==
               NvOdmUsbInterfaceType_UlpiExternalPhy))
        {
            if (NvRmSetModuleTristate(
                    pUsbPhy->hRmDevice,
                    NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, pUsbPhy->Instance),
                    NV_FALSE) != NvSuccess )
               return NvError_NotSupported;
        }

        // Register with Power Manager
        NV_CHECK_ERROR_CLEANUP(
            NvOsSemaphoreCreate(&pUsbPhy->hPwrEventSem, 0));

        pUsbPhy->RmPowerClientId = NVRM_POWER_CLIENT_TAG('U','S','B','p');
        NV_CHECK_ERROR_CLEANUP(
            NvRmPowerRegister(pUsbPhy->hRmDevice,
            pUsbPhy->hPwrEventSem, &pUsbPhy->RmPowerClientId));

        // Open the H/W interface
        UsbPhyOpenHwInterface(pUsbPhy);

        // Initialize the USB Phy
        NV_CHECK_ERROR_CLEANUP(UsbPhyInitialize(pUsbPhy));
    }
    else
    {
        pUsbPhy->RefCount++;
    }

    *hUsbPhy = pUsbPhy;
    NvOsMutexUnlock(s_UsbPhyMutex);

    return NvSuccess;

fail:

    NvDdkUsbPhyClose(pUsbPhy);
    NvOsMutexUnlock(s_UsbPhyMutex);
    return e;
}