Path: blob/master/drivers/char/xillybus/xillybus_pcie.c
26282 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* linux/drivers/misc/xillybus_pcie.c3*4* Copyright 2011 Xillybus Ltd, http://xillybus.com5*6* Driver for the Xillybus FPGA/host framework using PCI Express.7*/89#include <linux/module.h>10#include <linux/pci.h>11#include <linux/slab.h>12#include "xillybus.h"1314MODULE_DESCRIPTION("Xillybus driver for PCIe");15MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");16MODULE_ALIAS("xillybus_pcie");17MODULE_LICENSE("GPL v2");1819#define PCI_DEVICE_ID_XILLYBUS 0xebeb2021#define PCI_VENDOR_ID_ACTEL 0x11aa22#define PCI_VENDOR_ID_LATTICE 0x12042324static const char xillyname[] = "xillybus_pcie";2526static const struct pci_device_id xillyids[] = {27{PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)},28{PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)},29{PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)},30{PCI_DEVICE(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_XILLYBUS)},31{ /* End: all zeroes */ }32};3334static int xilly_probe(struct pci_dev *pdev,35const struct pci_device_id *ent)36{37struct xilly_endpoint *endpoint;38int rc;3940endpoint = xillybus_init_endpoint(&pdev->dev);4142if (!endpoint)43return -ENOMEM;4445pci_set_drvdata(pdev, endpoint);4647endpoint->owner = THIS_MODULE;4849rc = pcim_enable_device(pdev);50if (rc) {51dev_err(endpoint->dev,52"pcim_enable_device() failed. Aborting.\n");53return rc;54}5556/* L0s has caused packet drops. No power saving, thank you. */5758pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);5960if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {61dev_err(endpoint->dev,62"Incorrect BAR configuration. Aborting.\n");63return -ENODEV;64}6566rc = pcim_iomap_regions(pdev, 0x01, xillyname);67if (rc) {68dev_err(endpoint->dev,69"pcim_iomap_regions() failed. Aborting.\n");70return rc;71}7273endpoint->registers = pcim_iomap_table(pdev)[0];7475pci_set_master(pdev);7677/* Set up a single MSI interrupt */78if (pci_enable_msi(pdev)) {79dev_err(endpoint->dev,80"Failed to enable MSI interrupts. Aborting.\n");81return -ENODEV;82}83rc = devm_request_irq(&pdev->dev, pdev->irq, xillybus_isr, 0,84xillyname, endpoint);85if (rc) {86dev_err(endpoint->dev,87"Failed to register MSI handler. Aborting.\n");88return -ENODEV;89}9091/*92* Some (old and buggy?) hardware drops 64-bit addressed PCIe packets,93* even when the PCIe driver claims that a 64-bit mask is OK. On the94* other hand, on some architectures, 64-bit addressing is mandatory.95* So go for the 64-bit mask only when failing is the other option.96*/9798if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {99endpoint->dma_using_dac = 0;100} else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {101endpoint->dma_using_dac = 1;102} else {103dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");104return -ENODEV;105}106107return xillybus_endpoint_discovery(endpoint);108}109110static void xilly_remove(struct pci_dev *pdev)111{112struct xilly_endpoint *endpoint = pci_get_drvdata(pdev);113114xillybus_endpoint_remove(endpoint);115}116117MODULE_DEVICE_TABLE(pci, xillyids);118119static struct pci_driver xillybus_driver = {120.name = xillyname,121.id_table = xillyids,122.probe = xilly_probe,123.remove = xilly_remove,124};125126module_pci_driver(xillybus_driver);127128129