brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · 9858711 Raw
128 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * linux/drivers/misc/xillybus_pcie.c4 *5 * Copyright 2011 Xillybus Ltd, http://xillybus.com6 *7 * Driver for the Xillybus FPGA/host framework using PCI Express.8 */9 10#include <linux/module.h>11#include <linux/pci.h>12#include <linux/slab.h>13#include "xillybus.h"14 15MODULE_DESCRIPTION("Xillybus driver for PCIe");16MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");17MODULE_ALIAS("xillybus_pcie");18MODULE_LICENSE("GPL v2");19 20#define PCI_DEVICE_ID_XILLYBUS		0xebeb21 22#define PCI_VENDOR_ID_ACTEL		0x11aa23#define PCI_VENDOR_ID_LATTICE		0x120424 25static const char xillyname[] = "xillybus_pcie";26 27static const struct pci_device_id xillyids[] = {28	{PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)},29	{PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)},30	{PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)},31	{PCI_DEVICE(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_XILLYBUS)},32	{ /* End: all zeroes */ }33};34 35static int xilly_probe(struct pci_dev *pdev,36		       const struct pci_device_id *ent)37{38	struct xilly_endpoint *endpoint;39	int rc;40 41	endpoint = xillybus_init_endpoint(&pdev->dev);42 43	if (!endpoint)44		return -ENOMEM;45 46	pci_set_drvdata(pdev, endpoint);47 48	endpoint->owner = THIS_MODULE;49 50	rc = pcim_enable_device(pdev);51	if (rc) {52		dev_err(endpoint->dev,53			"pcim_enable_device() failed. Aborting.\n");54		return rc;55	}56 57	/* L0s has caused packet drops. No power saving, thank you. */58 59	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);60 61	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {62		dev_err(endpoint->dev,63			"Incorrect BAR configuration. Aborting.\n");64		return -ENODEV;65	}66 67	rc = pcim_iomap_regions(pdev, 0x01, xillyname);68	if (rc) {69		dev_err(endpoint->dev,70			"pcim_iomap_regions() failed. Aborting.\n");71		return rc;72	}73 74	endpoint->registers = pcim_iomap_table(pdev)[0];75 76	pci_set_master(pdev);77 78	/* Set up a single MSI interrupt */79	if (pci_enable_msi(pdev)) {80		dev_err(endpoint->dev,81			"Failed to enable MSI interrupts. Aborting.\n");82		return -ENODEV;83	}84	rc = devm_request_irq(&pdev->dev, pdev->irq, xillybus_isr, 0,85			      xillyname, endpoint);86	if (rc) {87		dev_err(endpoint->dev,88			"Failed to register MSI handler. Aborting.\n");89		return -ENODEV;90	}91 92	/*93	 * Some (old and buggy?) hardware drops 64-bit addressed PCIe packets,94	 * even when the PCIe driver claims that a 64-bit mask is OK. On the95	 * other hand, on some architectures, 64-bit addressing is mandatory.96	 * So go for the 64-bit mask only when failing is the other option.97	 */98 99	if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {100		endpoint->dma_using_dac = 0;101	} else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {102		endpoint->dma_using_dac = 1;103	} else {104		dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");105		return -ENODEV;106	}107 108	return xillybus_endpoint_discovery(endpoint);109}110 111static void xilly_remove(struct pci_dev *pdev)112{113	struct xilly_endpoint *endpoint = pci_get_drvdata(pdev);114 115	xillybus_endpoint_remove(endpoint);116}117 118MODULE_DEVICE_TABLE(pci, xillyids);119 120static struct pci_driver xillybus_driver = {121	.name = xillyname,122	.id_table = xillyids,123	.probe = xilly_probe,124	.remove = xilly_remove,125};126 127module_pci_driver(xillybus_driver);128