示例#1
0
//------------------------------------------------------------------------------
tOplkError pciedrv_shutdown(void)
{
    // Unregister PCI driver
    DEBUG_LVL_DRVINTF_TRACE("%s calling pci_unregister_driver()\n", __FUNCTION__);
    pci_unregister_driver(&oplkPcieDriver_l);

    return kErrorOk;
}
//------------------------------------------------------------------------------
tOplkError zynqdrv_exit(void)
{
    DEBUG_LVL_DRVINTF_TRACE("%s(): Calling platform_driver_unregister()\n",
                            __func__);
    platform_driver_unregister(&pcpDriver_l);

    return kErrorOk;
}
示例#3
0
//------------------------------------------------------------------------------
static void removeOnePciDev(struct pci_dev* pPciDev_p)
{
    UINT8       barCount = 0;
    tBarInfo*   pBarInfo = NULL;

    if (pcieDrvInstance_l.pPciDev != pPciDev_p)
    {
        // Trying to remove unknown device
        BUG_ON(pcieDrvInstance_l.pPciDev != pPciDev_p);
        goto Exit;
    }

    // Remove interrupt handler
    if (pPciDev_p->irq != 0)
        free_irq(pPciDev_p->irq, pPciDev_p);

    // Disable Message Signaled Interrupt
    DEBUG_LVL_DRVINTF_TRACE("%s Disable MSI\n", __FUNCTION__);
    pci_disable_msi(pPciDev_p);

    // unmap controller's register space
    for (barCount = 0; barCount < OPLK_MAX_BAR_COUNT; barCount++)
    {
        pBarInfo = &pcieDrvInstance_l.aBarInfo[barCount];

        if (pBarInfo->virtualAddr != (ULONG)NULL)
        {
            iounmap((void __iomem*)pBarInfo->virtualAddr);
            pBarInfo->virtualAddr = (ULONG)NULL;
        }
    }

    // disable the PCI device
    pci_disable_device(pPciDev_p);

    // release memory regions
    pci_release_regions(pPciDev_p);

    pcieDrvInstance_l.pPciDev = NULL;

Exit:
    return;
}
示例#4
0
//------------------------------------------------------------------------------
static INT initOnePciDev(struct pci_dev* pPciDev_p,
                         const struct pci_device_id* pId_p)
{
    INT         result = 0;
    UINT8       barCount = 0;
    tBarInfo*   pBarInfo = NULL;

    UNUSED_PARAMETER(pId_p);

    if (pcieDrvInstance_l.pPciDev != NULL)
    {
        // This driver is already connected to a PCIe device
        DEBUG_LVL_DRVINTF_TRACE("%s device %s discarded\n",
                                __FUNCTION__, pci_name(pPciDev_p));
        result = -ENODEV;
        goto Exit;
    }

    pcieDrvInstance_l.pPciDev = pPciDev_p;

    // Enable the PCIe device
    DEBUG_LVL_DRVINTF_TRACE("%s enable device\n", __FUNCTION__);
    result = pci_enable_device(pPciDev_p);
    if (result != 0)
    {
        goto Exit;
    }

    DEBUG_LVL_DRVINTF_TRACE("%s request PCIe regions\n", __FUNCTION__);
    result = pci_request_regions(pPciDev_p, PLK_DRV_NAME);
    if (result != 0)
    {
        goto ExitFail;
    }

    // Ignoring whether or not any BAR is accessible
    for (barCount = 0; barCount < OPLK_MAX_BAR_COUNT; barCount++)
    {
        pBarInfo = &pcieDrvInstance_l.aBarInfo[barCount];

        if (pBarInfo->virtualAddr != (ULONG)NULL)
        {
            // The instance is already present
            result = -EIO;
            goto ExitFail;
        }

        // Look for the MMIO BARs
        if ((pci_resource_flags(pPciDev_p, barCount) & IORESOURCE_MEM) == 0)
        {
            continue;
        }

        // get the size of this field
        pBarInfo->length = pci_resource_len(pPciDev_p, barCount);

        // $$: Add check for weird broken IO regions

        pBarInfo->virtualAddr = (ULONG)ioremap_nocache(pci_resource_start(pPciDev_p,
                                                       barCount),
                                                       pBarInfo->length);
        if (pBarInfo->virtualAddr == (ULONG)NULL)
        {
            // Remap of controller's register space failed
            result = -EIO;
            goto ExitFail;
        }

        pBarInfo->busAddr = (ULONG)pci_resource_start(pPciDev_p, barCount);

        DEBUG_LVL_DRVINTF_TRACE("%s() --> ioremap\n", __FUNCTION__);
        DEBUG_LVL_DRVINTF_TRACE("\tbar#\t%u\n", barCount);
        DEBUG_LVL_DRVINTF_TRACE("\tbarLen\t%lu\n", pBarInfo->length);
        DEBUG_LVL_DRVINTF_TRACE("\tbarMap\t0x%lX\n", pBarInfo->virtualAddr);
        DEBUG_LVL_DRVINTF_TRACE("\tbarPhy\t0x%lX\n", pBarInfo->busAddr);
    }

    // Enable PCI busmaster
    DEBUG_LVL_DRVINTF_TRACE("%s enable busmaster\n", __FUNCTION__);
    pci_set_master(pPciDev_p);

    // Enable msi
    DEBUG_LVL_DRVINTF_TRACE("Enable MSI\n");
    result = pci_enable_msi(pPciDev_p);
    if (result != 0)
    {
        DEBUG_LVL_DRVINTF_TRACE("%s Could not enable MSI\n", __FUNCTION__);
    }

    // Install interrupt handler
    DEBUG_LVL_DRVINTF_TRACE("%s install interrupt handler\n", __FUNCTION__);
    result = request_irq(pPciDev_p->irq,
                         pcieDrvIrqHandler,
                         IRQF_SHARED,
                         PLK_DRV_NAME, /* pPciDev_p->dev.name */
                         pPciDev_p);
    if (result != 0)
    {
        goto ExitFail;
    }

    goto Exit;

ExitFail:
    removeOnePciDev(pPciDev_p);

Exit:
    DEBUG_LVL_DRVINTF_TRACE("%s finished with %d\n", __FUNCTION__, result);
    return result;
}
//------------------------------------------------------------------------------
static int initOnePlatformDev(struct platform_device* pDev_p)
{
    INT             result = 0;
    tIoMemRegions   memId = 0;

    /* checking if Microblaze Reset pin number is valid */
    if (!gpio_is_valid(MB_RESET_PIN))
    {
        DEBUG_LVL_DRVINTF_TRACE("Microblaze Reset pin not valid\n");
        result = -EIO;
        goto Exit;
    }

    gpio_request(MB_RESET_PIN, "Reset Button");

    gpio_export(MB_RESET_PIN, false);

    gpio_direction_output(MB_RESET_PIN, MICROBLAZE_RESET);

    /* Reset Microblaze */
    gpio_set_value(MB_RESET_PIN, MICROBLAZE_RESET);

    /* Wait for Microblaze to come out of reset */
    msleep(500);

    if (pDev_p == NULL)
    {
        DEBUG_LVL_DRVINTF_TRACE("%s(): Device discarded\n", __func__);
        result = -ENODEV;
        goto ExitClean;
    }

    if (instance_l.pPlatformDev != NULL)
    {
        DEBUG_LVL_DRVINTF_TRACE("%s(): Device (%s) already registered\n",
                                __func__,
                                pDev_p->name);
        result = -ENODEV;
        goto ExitClean;
    }

    // Save the handle for the platform device
    instance_l.pPlatformDev = pDev_p;

    for (memId = 0; memId < kIoMemRegionLast; memId++)
    {
        tIoMemoryResource* pMemResource = &instance_l.aIoMemRes[memId];

        DEBUG_LVL_DRVINTF_TRACE("%s(): IOMEM resource initialization...%s",
                                __func__,
                                ((memId == 0) ? "Common Memory" : "Shared Memory"));

        pMemResource->pResource =
                  platform_get_resource(pDev_p, IORESOURCE_MEM, memId);

        if (pMemResource->pResource == NULL)
        {
            result = -ENODEV;
            goto ExitClean;
        }

        pMemResource->size = (pMemResource->pResource->end -
                              pMemResource->pResource->start + 1);

        /* Mark the region exclusively for Zynq device */
        if (!request_mem_region(pMemResource->pResource->start,
                                pMemResource->size,
                                PLK_DRV_NAME))
        {
            DEBUG_LVL_DRVINTF_TRACE("Request memory region failed for %s \n",
                                    ((memId == 0) ? "Common Memory" : "Shared Memory"));
            result = -ENOMEM;
            goto ExitClean;
        }

        DEBUG_LVL_DRVINTF_TRACE("MEM_RESOURCE: Start 0x(%X), End 0x(%X) \n",
                                pMemResource->pResource->start,
                                pMemResource->pResource->end);

        /* Remap Io memory regions into Linux virtual address space */
        pMemResource->pBase = ioremap(pMemResource->pResource->start,
                                      pMemResource->size);

        if (pMemResource->pBase == NULL)
        {
            DEBUG_LVL_DRVINTF_TRACE("Ioremap failed for %s\n",
                                    ((memId == 0) ? "Common Memory" : "Shared Memory"));
            result = -EIO;
            goto ExitClean;
        }
    }

    DEBUG_LVL_DRVINTF_TRACE("%s(): IRQ resource initialization...", __func__);

    /* Get Interrupt resource for device */
    instance_l.irqResource.pResource = platform_get_resource(pDev_p,
                                                             IORESOURCE_IRQ,
                                                             0);

    if (instance_l.irqResource.pResource == NULL)
    {
        DEBUG_LVL_DRVINTF_TRACE("Failed\n");
        result = -ENODEV;
        goto ExitClean;
    }

    /* Request IRQ */
    DEBUG_LVL_DRVINTF_TRACE("Requesting IRQ resource...");

    if (request_irq(instance_l.irqResource.pResource->start,
                    pcpIrqHandler,
                    0,
                    PLK_DRV_NAME,
                    pDev_p))
    {
        DEBUG_LVL_DRVINTF_TRACE("Request IRQ failed \n");
        result = -EIO;
        goto ExitClean;
    }

    instance_l.irqResource.irqNumber = instance_l.irqResource.pResource->start;

Exit:
    DEBUG_LVL_DRVINTF_TRACE("%s(): finished with %d\n", __func__, result);
    return result;

ExitClean:
    DEBUG_LVL_DRVINTF_TRACE("%s(): finished with %d\n", __func__, result);
    removeOnePlatformDev(pDev_p);
    return result;
}