1a6377d90SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27051924fSEli Billauer /*
37051924fSEli Billauer * linux/drivers/misc/xillybus_pcie.c
47051924fSEli Billauer *
57051924fSEli Billauer * Copyright 2011 Xillybus Ltd, http://xillybus.com
67051924fSEli Billauer *
77051924fSEli Billauer * Driver for the Xillybus FPGA/host framework using PCI Express.
87051924fSEli Billauer */
97051924fSEli Billauer
107051924fSEli Billauer #include <linux/module.h>
117051924fSEli Billauer #include <linux/pci.h>
127051924fSEli Billauer #include <linux/slab.h>
137051924fSEli Billauer #include "xillybus.h"
147051924fSEli Billauer
157051924fSEli Billauer MODULE_DESCRIPTION("Xillybus driver for PCIe");
167051924fSEli Billauer MODULE_AUTHOR("Eli Billauer, Xillybus Ltd.");
177051924fSEli Billauer MODULE_ALIAS("xillybus_pcie");
187051924fSEli Billauer MODULE_LICENSE("GPL v2");
197051924fSEli Billauer
207051924fSEli Billauer #define PCI_DEVICE_ID_XILLYBUS 0xebeb
217051924fSEli Billauer
227051924fSEli Billauer #define PCI_VENDOR_ID_ACTEL 0x11aa
237051924fSEli Billauer #define PCI_VENDOR_ID_LATTICE 0x1204
247051924fSEli Billauer
257051924fSEli Billauer static const char xillyname[] = "xillybus_pcie";
267051924fSEli Billauer
277051924fSEli Billauer static const struct pci_device_id xillyids[] = {
287051924fSEli Billauer {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)},
297051924fSEli Billauer {PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)},
307051924fSEli Billauer {PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)},
317051924fSEli Billauer {PCI_DEVICE(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_XILLYBUS)},
327051924fSEli Billauer { /* End: all zeroes */ }
337051924fSEli Billauer };
347051924fSEli Billauer
xilly_probe(struct pci_dev * pdev,const struct pci_device_id * ent)357051924fSEli Billauer static int xilly_probe(struct pci_dev *pdev,
367051924fSEli Billauer const struct pci_device_id *ent)
377051924fSEli Billauer {
387051924fSEli Billauer struct xilly_endpoint *endpoint;
397051924fSEli Billauer int rc;
407051924fSEli Billauer
41*c31bbc14SEli Billauer endpoint = xillybus_init_endpoint(&pdev->dev);
427051924fSEli Billauer
437051924fSEli Billauer if (!endpoint)
447051924fSEli Billauer return -ENOMEM;
457051924fSEli Billauer
467051924fSEli Billauer pci_set_drvdata(pdev, endpoint);
477051924fSEli Billauer
48*c31bbc14SEli Billauer endpoint->owner = THIS_MODULE;
49*c31bbc14SEli Billauer
507051924fSEli Billauer rc = pcim_enable_device(pdev);
517051924fSEli Billauer if (rc) {
527051924fSEli Billauer dev_err(endpoint->dev,
537051924fSEli Billauer "pcim_enable_device() failed. Aborting.\n");
547051924fSEli Billauer return rc;
557051924fSEli Billauer }
567051924fSEli Billauer
577051924fSEli Billauer /* L0s has caused packet drops. No power saving, thank you. */
587051924fSEli Billauer
597051924fSEli Billauer pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
607051924fSEli Billauer
617051924fSEli Billauer if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
627051924fSEli Billauer dev_err(endpoint->dev,
637051924fSEli Billauer "Incorrect BAR configuration. Aborting.\n");
647051924fSEli Billauer return -ENODEV;
657051924fSEli Billauer }
667051924fSEli Billauer
677051924fSEli Billauer rc = pcim_iomap_regions(pdev, 0x01, xillyname);
687051924fSEli Billauer if (rc) {
697051924fSEli Billauer dev_err(endpoint->dev,
707051924fSEli Billauer "pcim_iomap_regions() failed. Aborting.\n");
717051924fSEli Billauer return rc;
727051924fSEli Billauer }
737051924fSEli Billauer
747051924fSEli Billauer endpoint->registers = pcim_iomap_table(pdev)[0];
757051924fSEli Billauer
767051924fSEli Billauer pci_set_master(pdev);
777051924fSEli Billauer
787051924fSEli Billauer /* Set up a single MSI interrupt */
797051924fSEli Billauer if (pci_enable_msi(pdev)) {
807051924fSEli Billauer dev_err(endpoint->dev,
817051924fSEli Billauer "Failed to enable MSI interrupts. Aborting.\n");
827051924fSEli Billauer return -ENODEV;
837051924fSEli Billauer }
847051924fSEli Billauer rc = devm_request_irq(&pdev->dev, pdev->irq, xillybus_isr, 0,
857051924fSEli Billauer xillyname, endpoint);
867051924fSEli Billauer if (rc) {
877051924fSEli Billauer dev_err(endpoint->dev,
887051924fSEli Billauer "Failed to register MSI handler. Aborting.\n");
897051924fSEli Billauer return -ENODEV;
907051924fSEli Billauer }
917051924fSEli Billauer
927051924fSEli Billauer /*
936497a875SEli Billauer * Some (old and buggy?) hardware drops 64-bit addressed PCIe packets,
946497a875SEli Billauer * even when the PCIe driver claims that a 64-bit mask is OK. On the
956497a875SEli Billauer * other hand, on some architectures, 64-bit addressing is mandatory.
966497a875SEli Billauer * So go for the 64-bit mask only when failing is the other option.
977051924fSEli Billauer */
987051924fSEli Billauer
99b46f7d33SChristophe JAILLET if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
1007051924fSEli Billauer endpoint->dma_using_dac = 0;
101b46f7d33SChristophe JAILLET } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
1026497a875SEli Billauer endpoint->dma_using_dac = 1;
1037051924fSEli Billauer } else {
1047051924fSEli Billauer dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");
1057051924fSEli Billauer return -ENODEV;
1067051924fSEli Billauer }
1077051924fSEli Billauer
1087051924fSEli Billauer return xillybus_endpoint_discovery(endpoint);
1097051924fSEli Billauer }
1107051924fSEli Billauer
xilly_remove(struct pci_dev * pdev)1117051924fSEli Billauer static void xilly_remove(struct pci_dev *pdev)
1127051924fSEli Billauer {
1137051924fSEli Billauer struct xilly_endpoint *endpoint = pci_get_drvdata(pdev);
1147051924fSEli Billauer
1157051924fSEli Billauer xillybus_endpoint_remove(endpoint);
1167051924fSEli Billauer }
1177051924fSEli Billauer
1187051924fSEli Billauer MODULE_DEVICE_TABLE(pci, xillyids);
1197051924fSEli Billauer
1207051924fSEli Billauer static struct pci_driver xillybus_driver = {
1217051924fSEli Billauer .name = xillyname,
1227051924fSEli Billauer .id_table = xillyids,
1237051924fSEli Billauer .probe = xilly_probe,
1247051924fSEli Billauer .remove = xilly_remove,
1257051924fSEli Billauer };
1267051924fSEli Billauer
1277051924fSEli Billauer module_pci_driver(xillybus_driver);
128