diff options
Diffstat (limited to 'drivers/staging/kpc2000/kpc2000/core.c')
-rw-r--r-- | drivers/staging/kpc2000/kpc2000/core.c | 565 |
1 files changed, 0 insertions, 565 deletions
diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c deleted file mode 100644 index 6462a3059fb0..000000000000 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ /dev/null @@ -1,565 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -#include <linux/kernel.h> -#include <linux/idr.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/export.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/errno.h> -#include <linux/cdev.h> -#include <linux/rwsem.h> -#include <linux/uaccess.h> -#include <linux/io.h> -#include <linux/mfd/core.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/device.h> -#include <linux/sched.h> -#include <linux/jiffies.h> -#include "pcie.h" -#include "uapi.h" - -static DEFINE_IDA(card_num_ida); - -/******************************************************* - * SysFS Attributes - ******************************************************/ - -static ssize_t ssid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%016llx\n", pcard->ssid); -} -static DEVICE_ATTR_RO(ssid); - -static ssize_t ddna_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%016llx\n", pcard->ddna); -} -static DEVICE_ATTR_RO(ddna); - -static ssize_t card_id_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->card_id); -} -static DEVICE_ATTR_RO(card_id); - -static ssize_t hw_rev_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->hardware_revision); -} -static DEVICE_ATTR_RO(hw_rev); - -static ssize_t build_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->build_version); -} -static DEVICE_ATTR_RO(build); - -static ssize_t build_date_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->build_datestamp); -} -static DEVICE_ATTR_RO(build_date); - -static ssize_t build_time_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->build_timestamp); -} -static DEVICE_ATTR_RO(build_time); - -static ssize_t cpld_reg_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(cpld_reg); - -static ssize_t cpld_reconfigure(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - unsigned long wr_val; - int rv; - - rv = kstrtoul(buf, 0, &wr_val); - if (rv < 0) - return rv; - if (wr_val > 7) - return -EINVAL; - - wr_val = wr_val << 8; - wr_val |= 0x1; // Set the "Configure Go" bit - writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG); - return count; -} - -static DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure); - -static ssize_t irq_mask_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(irq_mask_reg); - -static ssize_t irq_active_reg_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(irq_active_reg); - -static ssize_t pcie_error_count_reg_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - u64 val; - - val = readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT); - return sprintf(buf, "%016llx\n", val); -} -static DEVICE_ATTR_RO(pcie_error_count_reg); - -static ssize_t core_table_offset_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->core_table_offset); -} -static DEVICE_ATTR_RO(core_table_offset); - -static ssize_t core_table_length_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kp2000_device *pcard = dev_get_drvdata(dev); - - return sprintf(buf, "%08x\n", pcard->core_table_length); -} -static DEVICE_ATTR_RO(core_table_length); - -static const struct attribute *kp_attr_list[] = { - &dev_attr_ssid.attr, - &dev_attr_ddna.attr, - &dev_attr_card_id.attr, - &dev_attr_hw_rev.attr, - &dev_attr_build.attr, - &dev_attr_build_date.attr, - &dev_attr_build_time.attr, - &dev_attr_cpld_reg.attr, - &dev_attr_cpld_reconfigure.attr, - &dev_attr_irq_mask_reg.attr, - &dev_attr_irq_active_reg.attr, - &dev_attr_pcie_error_count_reg.attr, - &dev_attr_core_table_offset.attr, - &dev_attr_core_table_length.attr, - NULL, -}; - -/******************************************************* - * Functions - ******************************************************/ - -static void wait_and_read_ssid(struct kp2000_device *pcard) -{ - u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - unsigned long timeout; - - if (read_val & 0x8000000000000000UL) { - pcard->ssid = read_val; - return; - } - - timeout = jiffies + (HZ * 2); - do { - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - if (read_val & 0x8000000000000000UL) { - pcard->ssid = read_val; - return; - } - cpu_relax(); - //schedule(); - } while (time_before(jiffies, timeout)); - - dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n"); - - // Timed out waiting for the SSID to show up, stick all zeros in the - // value - pcard->ssid = 0; -} - -static int read_system_regs(struct kp2000_device *pcard) -{ - u64 read_val; - - read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER); - if (read_val != KP2000_MAGIC_VALUE) { - dev_err(&pcard->pdev->dev, - "Invalid magic! Got: 0x%016llx Want: 0x%016llx\n", - read_val, KP2000_MAGIC_VALUE); - return -EILSEQ; - } - - read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD); - pcard->card_id = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->build_version = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); - pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->build_timestamp = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); - pcard->core_table_length = (read_val & 0xFFFFFFFF00000000UL) >> 32; - pcard->core_table_offset = (read_val & 0x00000000FFFFFFFFUL) >> 0; - - wait_and_read_ssid(pcard); - - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID); - pcard->core_table_rev = (read_val & 0x0000000000000F00) >> 8; - pcard->hardware_revision = (read_val & 0x000000000000001F); - - read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA); - pcard->ddna = read_val; - - dev_info(&pcard->pdev->dev, - "system_regs: %08x %08x %08x %08x %02x %d %d %016llx %016llx\n", - pcard->card_id, - pcard->build_version, - pcard->build_datestamp, - pcard->build_timestamp, - pcard->hardware_revision, - pcard->core_table_rev, - pcard->core_table_length, - pcard->ssid, - pcard->ddna); - - if (pcard->core_table_rev > 1) { - dev_err(&pcard->pdev->dev, - "core table entry revision is higher than we can deal with, cannot continue with this card!\n"); - return 1; - } - - return 0; -} - -static irqreturn_t kp2000_irq_handler(int irq, void *dev_id) -{ - struct kp2000_device *pcard = dev_id; - - writel(KPC_DMA_CARD_IRQ_ENABLE | - KPC_DMA_CARD_USER_INTERRUPT_MODE | - KPC_DMA_CARD_USER_INTERRUPT_ACTIVE, - pcard->dma_common_regs); - return IRQ_HANDLED; -} - -static int kp2000_pcie_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int err = 0; - struct kp2000_device *pcard; - unsigned long reg_bar_phys_addr; - unsigned long reg_bar_phys_len; - unsigned long dma_bar_phys_addr; - unsigned long dma_bar_phys_len; - u16 regval; - - pcard = kzalloc(sizeof(*pcard), GFP_KERNEL); - if (!pcard) - return -ENOMEM; - dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n", - pcard); - - err = ida_simple_get(&card_num_ida, 1, INT_MAX, GFP_KERNEL); - if (err < 0) { - dev_err(&pdev->dev, "probe: failed to get card number (%d)\n", - err); - goto err_free_pcard; - } - pcard->card_num = err; - scnprintf(pcard->name, 16, "kpcard%u", pcard->card_num); - - mutex_init(&pcard->sem); - mutex_lock(&pcard->sem); - - pcard->pdev = pdev; - pci_set_drvdata(pdev, pcard); - - err = pci_enable_device(pcard->pdev); - if (err) { - dev_err(&pcard->pdev->dev, - "probe: failed to enable PCIE2000 PCIe device (%d)\n", - err); - goto err_remove_ida; - } - - /* Setup the Register BAR */ - reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR); - reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR); - - pcard->regs_bar_base = ioremap(reg_bar_phys_addr, PAGE_SIZE); - if (!pcard->regs_bar_base) { - dev_err(&pcard->pdev->dev, - "probe: REG_BAR could not remap memory to virtual space\n"); - err = -ENODEV; - goto err_disable_device; - } - dev_dbg(&pcard->pdev->dev, - "probe: REG_BAR virt hardware address start [%p]\n", - pcard->regs_bar_base); - - err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000); - if (err) { - dev_err(&pcard->pdev->dev, - "probe: failed to acquire PCI region (%d)\n", - err); - err = -ENODEV; - goto err_unmap_regs; - } - - pcard->regs_base_resource.start = reg_bar_phys_addr; - pcard->regs_base_resource.end = reg_bar_phys_addr + - reg_bar_phys_len - 1; - pcard->regs_base_resource.flags = IORESOURCE_MEM; - - /* Setup the DMA BAR */ - dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR); - dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR); - - pcard->dma_bar_base = ioremap(dma_bar_phys_addr, - dma_bar_phys_len); - if (!pcard->dma_bar_base) { - dev_err(&pcard->pdev->dev, - "probe: DMA_BAR could not remap memory to virtual space\n"); - err = -ENODEV; - goto err_release_regs; - } - dev_dbg(&pcard->pdev->dev, - "probe: DMA_BAR virt hardware address start [%p]\n", - pcard->dma_bar_base); - - pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET; - - err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie"); - if (err) { - dev_err(&pcard->pdev->dev, - "probe: failed to acquire PCI region (%d)\n", err); - err = -ENODEV; - goto err_unmap_dma; - } - - pcard->dma_base_resource.start = dma_bar_phys_addr; - pcard->dma_base_resource.end = dma_bar_phys_addr + - dma_bar_phys_len - 1; - pcard->dma_base_resource.flags = IORESOURCE_MEM; - - /* Read System Regs */ - pcard->sysinfo_regs_base = pcard->regs_bar_base; - err = read_system_regs(pcard); - if (err) - goto err_release_dma; - - // Disable all "user" interrupts because they're not used yet. - writeq(0xFFFFFFFFFFFFFFFFUL, - pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); - - // let the card master PCIe - pci_set_master(pcard->pdev); - - // enable IO and mem if not already done - pci_read_config_word(pcard->pdev, PCI_COMMAND, ®val); - regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(pcard->pdev, PCI_COMMAND, regval); - - // Clear relaxed ordering bit - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_RELAX_EN, 0); - - // Set Max_Payload_Size and Max_Read_Request_Size - regval = (0x0) << 5; // Max_Payload_Size = 128 B - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_PAYLOAD, regval); - regval = (0x0) << 12; // Max_Read_Request_Size = 128 B - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, regval); - - // Enable error reporting for: Correctable Errors, Non-Fatal Errors, - // Fatal Errors, Unsupported Requests - pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0, - PCI_EXP_DEVCTL_CERE | - PCI_EXP_DEVCTL_NFERE | - PCI_EXP_DEVCTL_FERE | - PCI_EXP_DEVCTL_URRE); - - err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64)); - if (err) { - dev_err(&pcard->pdev->dev, - "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64)); - goto err_release_dma; - } - dev_dbg(&pcard->pdev->dev, - "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard))); - - err = pci_enable_msi(pcard->pdev); - if (err < 0) - goto err_release_dma; - - err = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED, - pcard->name, pcard); - if (err) { - dev_err(&pcard->pdev->dev, - "%s: failed to request_irq: %d\n", __func__, err); - goto err_disable_msi; - } - - err = sysfs_create_files(&pdev->dev.kobj, kp_attr_list); - if (err) { - dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err); - goto err_free_irq; - } - - err = kp2000_probe_cores(pcard); - if (err) - goto err_remove_sysfs; - - /* Enable IRQs in HW */ - writel(KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE, - pcard->dma_common_regs); - - mutex_unlock(&pcard->sem); - return 0; - -err_remove_sysfs: - sysfs_remove_files(&pdev->dev.kobj, kp_attr_list); -err_free_irq: - free_irq(pcard->pdev->irq, pcard); -err_disable_msi: - pci_disable_msi(pcard->pdev); -err_release_dma: - pci_release_region(pdev, DMA_BAR); -err_unmap_dma: - iounmap(pcard->dma_bar_base); -err_release_regs: - pci_release_region(pdev, REG_BAR); -err_unmap_regs: - iounmap(pcard->regs_bar_base); -err_disable_device: - pci_disable_device(pcard->pdev); -err_remove_ida: - mutex_unlock(&pcard->sem); - ida_simple_remove(&card_num_ida, pcard->card_num); -err_free_pcard: - kfree(pcard); - return err; -} - -static void kp2000_pcie_remove(struct pci_dev *pdev) -{ - struct kp2000_device *pcard = pci_get_drvdata(pdev); - - if (!pcard) - return; - - mutex_lock(&pcard->sem); - kp2000_remove_cores(pcard); - mfd_remove_devices(PCARD_TO_DEV(pcard)); - sysfs_remove_files(&pdev->dev.kobj, kp_attr_list); - free_irq(pcard->pdev->irq, pcard); - pci_disable_msi(pcard->pdev); - if (pcard->dma_bar_base) { - iounmap(pcard->dma_bar_base); - pci_release_region(pdev, DMA_BAR); - pcard->dma_bar_base = NULL; - } - if (pcard->regs_bar_base) { - iounmap(pcard->regs_bar_base); - pci_release_region(pdev, REG_BAR); - pcard->regs_bar_base = NULL; - } - pci_disable_device(pcard->pdev); - pci_set_drvdata(pdev, NULL); - mutex_unlock(&pcard->sem); - ida_simple_remove(&card_num_ida, pcard->card_num); - kfree(pcard); -} - -struct class *kpc_uio_class; -ATTRIBUTE_GROUPS(kpc_uio_class); - -static const struct pci_device_id kp2000_pci_device_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) }, - { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids); - -static struct pci_driver kp2000_driver_inst = { - .name = "kp2000_pcie", - .id_table = kp2000_pci_device_ids, - .probe = kp2000_pcie_probe, - .remove = kp2000_pcie_remove, -}; - -static int __init kp2000_pcie_init(void) -{ - kpc_uio_class = class_create(THIS_MODULE, "kpc_uio"); - if (IS_ERR(kpc_uio_class)) - return PTR_ERR(kpc_uio_class); - - kpc_uio_class->dev_groups = kpc_uio_class_groups; - return pci_register_driver(&kp2000_driver_inst); -} -module_init(kp2000_pcie_init); - -static void __exit kp2000_pcie_exit(void) -{ - pci_unregister_driver(&kp2000_driver_inst); - class_destroy(kpc_uio_class); - ida_destroy(&card_num_ida); -} -module_exit(kp2000_pcie_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com"); -MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi"); |