Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/misc/xillybus_pcie.c
0004  *
0005  * Copyright 2011 Xillybus Ltd, http://xillybus.com
0006  *
0007  * Driver for the Xillybus FPGA/host framework using PCI Express.
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/pci.h>
0012 #include <linux/slab.h>
0013 #include "xillybus.h"
0014 
0015 MODULE_DESCRIPTION("Xillybus driver for PCIe");
0016 MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
0017 MODULE_ALIAS("xillybus_pcie");
0018 MODULE_LICENSE("GPL v2");
0019 
0020 #define PCI_DEVICE_ID_XILLYBUS      0xebeb
0021 
0022 #define PCI_VENDOR_ID_ACTEL     0x11aa
0023 #define PCI_VENDOR_ID_LATTICE       0x1204
0024 
0025 static const char xillyname[] = "xillybus_pcie";
0026 
0027 static const struct pci_device_id xillyids[] = {
0028     {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)},
0029     {PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)},
0030     {PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)},
0031     {PCI_DEVICE(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_XILLYBUS)},
0032     { /* End: all zeroes */ }
0033 };
0034 
0035 static int xilly_probe(struct pci_dev *pdev,
0036                const struct pci_device_id *ent)
0037 {
0038     struct xilly_endpoint *endpoint;
0039     int rc;
0040 
0041     endpoint = xillybus_init_endpoint(&pdev->dev);
0042 
0043     if (!endpoint)
0044         return -ENOMEM;
0045 
0046     pci_set_drvdata(pdev, endpoint);
0047 
0048     endpoint->owner = THIS_MODULE;
0049 
0050     rc = pcim_enable_device(pdev);
0051     if (rc) {
0052         dev_err(endpoint->dev,
0053             "pcim_enable_device() failed. Aborting.\n");
0054         return rc;
0055     }
0056 
0057     /* L0s has caused packet drops. No power saving, thank you. */
0058 
0059     pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
0060 
0061     if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
0062         dev_err(endpoint->dev,
0063             "Incorrect BAR configuration. Aborting.\n");
0064         return -ENODEV;
0065     }
0066 
0067     rc = pcim_iomap_regions(pdev, 0x01, xillyname);
0068     if (rc) {
0069         dev_err(endpoint->dev,
0070             "pcim_iomap_regions() failed. Aborting.\n");
0071         return rc;
0072     }
0073 
0074     endpoint->registers = pcim_iomap_table(pdev)[0];
0075 
0076     pci_set_master(pdev);
0077 
0078     /* Set up a single MSI interrupt */
0079     if (pci_enable_msi(pdev)) {
0080         dev_err(endpoint->dev,
0081             "Failed to enable MSI interrupts. Aborting.\n");
0082         return -ENODEV;
0083     }
0084     rc = devm_request_irq(&pdev->dev, pdev->irq, xillybus_isr, 0,
0085                   xillyname, endpoint);
0086     if (rc) {
0087         dev_err(endpoint->dev,
0088             "Failed to register MSI handler. Aborting.\n");
0089         return -ENODEV;
0090     }
0091 
0092     /*
0093      * Some (old and buggy?) hardware drops 64-bit addressed PCIe packets,
0094      * even when the PCIe driver claims that a 64-bit mask is OK. On the
0095      * other hand, on some architectures, 64-bit addressing is mandatory.
0096      * So go for the 64-bit mask only when failing is the other option.
0097      */
0098 
0099     if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
0100         endpoint->dma_using_dac = 0;
0101     } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
0102         endpoint->dma_using_dac = 1;
0103     } else {
0104         dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");
0105         return -ENODEV;
0106     }
0107 
0108     return xillybus_endpoint_discovery(endpoint);
0109 }
0110 
0111 static void xilly_remove(struct pci_dev *pdev)
0112 {
0113     struct xilly_endpoint *endpoint = pci_get_drvdata(pdev);
0114 
0115     xillybus_endpoint_remove(endpoint);
0116 }
0117 
0118 MODULE_DEVICE_TABLE(pci, xillyids);
0119 
0120 static struct pci_driver xillybus_driver = {
0121     .name = xillyname,
0122     .id_table = xillyids,
0123     .probe = xilly_probe,
0124     .remove = xilly_remove,
0125 };
0126 
0127 module_pci_driver(xillybus_driver);