root/drivers/staging/kpc2000/kpc2000/core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssid_show
  2. ddna_show
  3. card_id_show
  4. hw_rev_show
  5. build_show
  6. build_date_show
  7. build_time_show
  8. cpld_reg_show
  9. cpld_reconfigure
  10. irq_mask_reg_show
  11. irq_active_reg_show
  12. pcie_error_count_reg_show
  13. core_table_offset_show
  14. core_table_length_show
  15. wait_and_read_ssid
  16. read_system_regs
  17. kp2000_irq_handler
  18. kp2000_pcie_probe
  19. kp2000_pcie_remove
  20. kp2000_pcie_init
  21. kp2000_pcie_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 #include <linux/kernel.h>
   3 #include <linux/idr.h>
   4 #include <linux/init.h>
   5 #include <linux/module.h>
   6 #include <linux/pci.h>
   7 #include <linux/types.h>
   8 #include <linux/export.h>
   9 #include <linux/slab.h>
  10 #include <linux/fs.h>
  11 #include <linux/errno.h>
  12 #include <linux/cdev.h>
  13 #include <linux/rwsem.h>
  14 #include <linux/uaccess.h>
  15 #include <linux/io.h>
  16 #include <linux/mfd/core.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/ioport.h>
  19 #include <linux/io-64-nonatomic-lo-hi.h>
  20 #include <linux/interrupt.h>
  21 #include <linux/workqueue.h>
  22 #include <linux/device.h>
  23 #include <linux/sched.h>
  24 #include <linux/jiffies.h>
  25 #include "pcie.h"
  26 #include "uapi.h"
  27 
  28 static DEFINE_IDA(card_num_ida);
  29 
  30 /*******************************************************
  31  * SysFS Attributes
  32  ******************************************************/
  33 
  34 static ssize_t ssid_show(struct device *dev, struct device_attribute *attr,
  35                          char *buf)
  36 {
  37         struct kp2000_device *pcard = dev_get_drvdata(dev);
  38 
  39         return sprintf(buf, "%016llx\n", pcard->ssid);
  40 }
  41 static DEVICE_ATTR_RO(ssid);
  42 
  43 static ssize_t ddna_show(struct device *dev, struct device_attribute *attr,
  44                          char *buf)
  45 {
  46         struct kp2000_device *pcard = dev_get_drvdata(dev);
  47 
  48         return sprintf(buf, "%016llx\n", pcard->ddna);
  49 }
  50 static DEVICE_ATTR_RO(ddna);
  51 
  52 static ssize_t card_id_show(struct device *dev, struct device_attribute *attr,
  53                             char *buf)
  54 {
  55         struct kp2000_device *pcard = dev_get_drvdata(dev);
  56 
  57         return sprintf(buf, "%08x\n", pcard->card_id);
  58 }
  59 static DEVICE_ATTR_RO(card_id);
  60 
  61 static ssize_t hw_rev_show(struct device *dev, struct device_attribute *attr,
  62                            char *buf)
  63 {
  64         struct kp2000_device *pcard = dev_get_drvdata(dev);
  65 
  66         return sprintf(buf, "%08x\n", pcard->hardware_revision);
  67 }
  68 static DEVICE_ATTR_RO(hw_rev);
  69 
  70 static ssize_t build_show(struct device *dev, struct device_attribute *attr,
  71                           char *buf)
  72 {
  73         struct kp2000_device *pcard = dev_get_drvdata(dev);
  74 
  75         return sprintf(buf, "%08x\n", pcard->build_version);
  76 }
  77 static DEVICE_ATTR_RO(build);
  78 
  79 static ssize_t build_date_show(struct device *dev,
  80                                struct device_attribute *attr, char *buf)
  81 {
  82         struct kp2000_device *pcard = dev_get_drvdata(dev);
  83 
  84         return sprintf(buf, "%08x\n", pcard->build_datestamp);
  85 }
  86 static DEVICE_ATTR_RO(build_date);
  87 
  88 static ssize_t build_time_show(struct device *dev,
  89                                struct device_attribute *attr, char *buf)
  90 {
  91         struct kp2000_device *pcard = dev_get_drvdata(dev);
  92 
  93         return sprintf(buf, "%08x\n", pcard->build_timestamp);
  94 }
  95 static DEVICE_ATTR_RO(build_time);
  96 
  97 static ssize_t cpld_reg_show(struct device *dev, struct device_attribute *attr,
  98                              char *buf)
  99 {
 100         struct kp2000_device *pcard = dev_get_drvdata(dev);
 101         u64 val;
 102 
 103         val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
 104         return sprintf(buf, "%016llx\n", val);
 105 }
 106 static DEVICE_ATTR_RO(cpld_reg);
 107 
 108 static ssize_t cpld_reconfigure(struct device *dev,
 109                                 struct device_attribute *attr,
 110                                 const char *buf, size_t count)
 111 {
 112         struct kp2000_device *pcard = dev_get_drvdata(dev);
 113         unsigned long wr_val;
 114         int rv;
 115 
 116         rv = kstrtoul(buf, 0, &wr_val);
 117         if (rv < 0)
 118                 return rv;
 119         if (wr_val > 7)
 120                 return -EINVAL;
 121 
 122         wr_val = wr_val << 8;
 123         wr_val |= 0x1; // Set the "Configure Go" bit
 124         writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
 125         return count;
 126 }
 127 static DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure);
 128 
 129 static ssize_t irq_mask_reg_show(struct device *dev,
 130                                  struct device_attribute *attr, char *buf)
 131 {
 132         struct kp2000_device *pcard = dev_get_drvdata(dev);
 133         u64 val;
 134 
 135         val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
 136         return sprintf(buf, "%016llx\n", val);
 137 }
 138 static DEVICE_ATTR_RO(irq_mask_reg);
 139 
 140 static ssize_t irq_active_reg_show(struct device *dev,
 141                                    struct device_attribute *attr, char *buf)
 142 {
 143         struct kp2000_device *pcard = dev_get_drvdata(dev);
 144         u64 val;
 145 
 146         val = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE);
 147         return sprintf(buf, "%016llx\n", val);
 148 }
 149 static DEVICE_ATTR_RO(irq_active_reg);
 150 
 151 static ssize_t pcie_error_count_reg_show(struct device *dev,
 152                                          struct device_attribute *attr,
 153                                          char *buf)
 154 {
 155         struct kp2000_device *pcard = dev_get_drvdata(dev);
 156         u64 val;
 157 
 158         val = readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT);
 159         return sprintf(buf, "%016llx\n", val);
 160 }
 161 static DEVICE_ATTR_RO(pcie_error_count_reg);
 162 
 163 static ssize_t core_table_offset_show(struct device *dev,
 164                                       struct device_attribute *attr, char *buf)
 165 {
 166         struct kp2000_device *pcard = dev_get_drvdata(dev);
 167 
 168         return sprintf(buf, "%08x\n", pcard->core_table_offset);
 169 }
 170 static DEVICE_ATTR_RO(core_table_offset);
 171 
 172 static ssize_t core_table_length_show(struct device *dev,
 173                                       struct device_attribute *attr, char *buf)
 174 {
 175         struct kp2000_device *pcard = dev_get_drvdata(dev);
 176 
 177         return sprintf(buf, "%08x\n", pcard->core_table_length);
 178 }
 179 static DEVICE_ATTR_RO(core_table_length);
 180 
 181 static const struct attribute *kp_attr_list[] = {
 182         &dev_attr_ssid.attr,
 183         &dev_attr_ddna.attr,
 184         &dev_attr_card_id.attr,
 185         &dev_attr_hw_rev.attr,
 186         &dev_attr_build.attr,
 187         &dev_attr_build_date.attr,
 188         &dev_attr_build_time.attr,
 189         &dev_attr_cpld_reg.attr,
 190         &dev_attr_cpld_reconfigure.attr,
 191         &dev_attr_irq_mask_reg.attr,
 192         &dev_attr_irq_active_reg.attr,
 193         &dev_attr_pcie_error_count_reg.attr,
 194         &dev_attr_core_table_offset.attr,
 195         &dev_attr_core_table_length.attr,
 196         NULL,
 197 };
 198 
 199 /*******************************************************
 200  * Functions
 201  ******************************************************/
 202 
 203 static void wait_and_read_ssid(struct kp2000_device *pcard)
 204 {
 205         u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID);
 206         unsigned long timeout;
 207 
 208         if (read_val & 0x8000000000000000UL) {
 209                 pcard->ssid = read_val;
 210                 return;
 211         }
 212 
 213         timeout = jiffies + (HZ * 2);
 214         do {
 215                 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID);
 216                 if (read_val & 0x8000000000000000UL) {
 217                         pcard->ssid = read_val;
 218                         return;
 219                 }
 220                 cpu_relax();
 221                 //schedule();
 222         } while (time_before(jiffies, timeout));
 223 
 224         dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n");
 225 
 226         // Timed out waiting for the SSID to show up, stick all zeros in the
 227         // value
 228         pcard->ssid = 0;
 229 }
 230 
 231 static int  read_system_regs(struct kp2000_device *pcard)
 232 {
 233         u64 read_val;
 234 
 235         read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER);
 236         if (read_val != KP2000_MAGIC_VALUE) {
 237                 dev_err(&pcard->pdev->dev,
 238                         "Invalid magic!  Got: 0x%016llx  Want: 0x%016llx\n",
 239                         read_val, KP2000_MAGIC_VALUE);
 240                 return -EILSEQ;
 241         }
 242 
 243         read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD);
 244         pcard->card_id = (read_val & 0xFFFFFFFF00000000UL) >> 32;
 245         pcard->build_version = (read_val & 0x00000000FFFFFFFFUL) >> 0;
 246 
 247         read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS);
 248         pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000UL) >> 32;
 249         pcard->build_timestamp = (read_val & 0x00000000FFFFFFFFUL) >> 0;
 250 
 251         read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET);
 252         pcard->core_table_length = (read_val & 0xFFFFFFFF00000000UL) >> 32;
 253         pcard->core_table_offset = (read_val & 0x00000000FFFFFFFFUL) >> 0;
 254 
 255         wait_and_read_ssid(pcard);
 256 
 257         read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID);
 258         pcard->core_table_rev    = (read_val & 0x0000000000000F00) >> 8;
 259         pcard->hardware_revision = (read_val & 0x000000000000001F);
 260 
 261         read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA);
 262         pcard->ddna = read_val;
 263 
 264         dev_info(&pcard->pdev->dev,
 265                  "system_regs: %08x %08x %08x %08x  %02x  %d %d  %016llx  %016llx\n",
 266                  pcard->card_id,
 267                  pcard->build_version,
 268                  pcard->build_datestamp,
 269                  pcard->build_timestamp,
 270                  pcard->hardware_revision,
 271                  pcard->core_table_rev,
 272                  pcard->core_table_length,
 273                  pcard->ssid,
 274                  pcard->ddna);
 275 
 276         if (pcard->core_table_rev > 1) {
 277                 dev_err(&pcard->pdev->dev,
 278                         "core table entry revision is higher than we can deal with, cannot continue with this card!\n");
 279                 return 1;
 280         }
 281 
 282         return 0;
 283 }
 284 
 285 static irqreturn_t kp2000_irq_handler(int irq, void *dev_id)
 286 {
 287         struct kp2000_device *pcard = dev_id;
 288 
 289         writel(KPC_DMA_CARD_IRQ_ENABLE |
 290                KPC_DMA_CARD_USER_INTERRUPT_MODE |
 291                KPC_DMA_CARD_USER_INTERRUPT_ACTIVE,
 292                pcard->dma_common_regs);
 293         return IRQ_HANDLED;
 294 }
 295 
 296 static int kp2000_pcie_probe(struct pci_dev *pdev,
 297                              const struct pci_device_id *id)
 298 {
 299         int err = 0;
 300         struct kp2000_device *pcard;
 301         unsigned long reg_bar_phys_addr;
 302         unsigned long reg_bar_phys_len;
 303         unsigned long dma_bar_phys_addr;
 304         unsigned long dma_bar_phys_len;
 305         u16 regval;
 306 
 307         pcard = kzalloc(sizeof(*pcard), GFP_KERNEL);
 308         if (!pcard)
 309                 return -ENOMEM;
 310         dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n",
 311                 pcard);
 312 
 313         err = ida_simple_get(&card_num_ida, 1, INT_MAX, GFP_KERNEL);
 314         if (err < 0) {
 315                 dev_err(&pdev->dev, "probe: failed to get card number (%d)\n",
 316                         err);
 317                 goto err_free_pcard;
 318         }
 319         pcard->card_num = err;
 320         scnprintf(pcard->name, 16, "kpcard%u", pcard->card_num);
 321 
 322         mutex_init(&pcard->sem);
 323         mutex_lock(&pcard->sem);
 324 
 325         pcard->pdev = pdev;
 326         pci_set_drvdata(pdev, pcard);
 327 
 328         err = pci_enable_device(pcard->pdev);
 329         if (err) {
 330                 dev_err(&pcard->pdev->dev,
 331                         "probe: failed to enable PCIE2000 PCIe device (%d)\n",
 332                         err);
 333                 goto err_remove_ida;
 334         }
 335 
 336         /* Setup the Register BAR */
 337         reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR);
 338         reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR);
 339 
 340         pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE);
 341         if (!pcard->regs_bar_base) {
 342                 dev_err(&pcard->pdev->dev,
 343                         "probe: REG_BAR could not remap memory to virtual space\n");
 344                 err = -ENODEV;
 345                 goto err_disable_device;
 346         }
 347         dev_dbg(&pcard->pdev->dev,
 348                 "probe: REG_BAR virt hardware address start [%p]\n",
 349                 pcard->regs_bar_base);
 350 
 351         err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000);
 352         if (err) {
 353                 dev_err(&pcard->pdev->dev,
 354                         "probe: failed to acquire PCI region (%d)\n",
 355                         err);
 356                 err = -ENODEV;
 357                 goto err_unmap_regs;
 358         }
 359 
 360         pcard->regs_base_resource.start = reg_bar_phys_addr;
 361         pcard->regs_base_resource.end   = reg_bar_phys_addr +
 362                                           reg_bar_phys_len - 1;
 363         pcard->regs_base_resource.flags = IORESOURCE_MEM;
 364 
 365         /* Setup the DMA BAR */
 366         dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR);
 367         dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR);
 368 
 369         pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr,
 370                                               dma_bar_phys_len);
 371         if (!pcard->dma_bar_base) {
 372                 dev_err(&pcard->pdev->dev,
 373                         "probe: DMA_BAR could not remap memory to virtual space\n");
 374                 err = -ENODEV;
 375                 goto err_release_regs;
 376         }
 377         dev_dbg(&pcard->pdev->dev,
 378                 "probe: DMA_BAR virt hardware address start [%p]\n",
 379                 pcard->dma_bar_base);
 380 
 381         pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET;
 382 
 383         err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie");
 384         if (err) {
 385                 dev_err(&pcard->pdev->dev,
 386                         "probe: failed to acquire PCI region (%d)\n", err);
 387                 err = -ENODEV;
 388                 goto err_unmap_dma;
 389         }
 390 
 391         pcard->dma_base_resource.start = dma_bar_phys_addr;
 392         pcard->dma_base_resource.end   = dma_bar_phys_addr +
 393                                          dma_bar_phys_len - 1;
 394         pcard->dma_base_resource.flags = IORESOURCE_MEM;
 395 
 396         /* Read System Regs */
 397         pcard->sysinfo_regs_base = pcard->regs_bar_base;
 398         err = read_system_regs(pcard);
 399         if (err)
 400                 goto err_release_dma;
 401 
 402         // Disable all "user" interrupts because they're not used yet.
 403         writeq(0xFFFFFFFFFFFFFFFFUL,
 404                pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
 405 
 406         // let the card master PCIe
 407         pci_set_master(pcard->pdev);
 408 
 409         // enable IO and mem if not already done
 410         pci_read_config_word(pcard->pdev, PCI_COMMAND, &regval);
 411         regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 412         pci_write_config_word(pcard->pdev, PCI_COMMAND, regval);
 413 
 414         // Clear relaxed ordering bit
 415         pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
 416                                            PCI_EXP_DEVCTL_RELAX_EN, 0);
 417 
 418         // Set Max_Payload_Size and Max_Read_Request_Size
 419         regval = (0x0) << 5; // Max_Payload_Size = 128 B
 420         pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
 421                                            PCI_EXP_DEVCTL_PAYLOAD, regval);
 422         regval = (0x0) << 12; // Max_Read_Request_Size = 128 B
 423         pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
 424                                            PCI_EXP_DEVCTL_READRQ, regval);
 425 
 426         // Enable error reporting for: Correctable Errors, Non-Fatal Errors,
 427         // Fatal Errors, Unsupported Requests
 428         pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0,
 429                                            PCI_EXP_DEVCTL_CERE |
 430                                            PCI_EXP_DEVCTL_NFERE |
 431                                            PCI_EXP_DEVCTL_FERE |
 432                                            PCI_EXP_DEVCTL_URRE);
 433 
 434         err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64));
 435         if (err) {
 436                 dev_err(&pcard->pdev->dev,
 437                         "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64));
 438                 goto err_release_dma;
 439         }
 440         dev_dbg(&pcard->pdev->dev,
 441                 "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard)));
 442 
 443         err = pci_enable_msi(pcard->pdev);
 444         if (err < 0)
 445                 goto err_release_dma;
 446 
 447         err = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED,
 448                           pcard->name, pcard);
 449         if (err) {
 450                 dev_err(&pcard->pdev->dev,
 451                         "%s: failed to request_irq: %d\n", __func__, err);
 452                 goto err_disable_msi;
 453         }
 454 
 455         err = sysfs_create_files(&pdev->dev.kobj, kp_attr_list);
 456         if (err) {
 457                 dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err);
 458                 goto err_free_irq;
 459         }
 460 
 461         err = kp2000_probe_cores(pcard);
 462         if (err)
 463                 goto err_remove_sysfs;
 464 
 465         /* Enable IRQs in HW */
 466         writel(KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE,
 467                pcard->dma_common_regs);
 468 
 469         mutex_unlock(&pcard->sem);
 470         return 0;
 471 
 472 err_remove_sysfs:
 473         sysfs_remove_files(&pdev->dev.kobj, kp_attr_list);
 474 err_free_irq:
 475         free_irq(pcard->pdev->irq, pcard);
 476 err_disable_msi:
 477         pci_disable_msi(pcard->pdev);
 478 err_release_dma:
 479         pci_release_region(pdev, DMA_BAR);
 480 err_unmap_dma:
 481         iounmap(pcard->dma_bar_base);
 482 err_release_regs:
 483         pci_release_region(pdev, REG_BAR);
 484 err_unmap_regs:
 485         iounmap(pcard->regs_bar_base);
 486 err_disable_device:
 487         pci_disable_device(pcard->pdev);
 488 err_remove_ida:
 489         mutex_unlock(&pcard->sem);
 490         ida_simple_remove(&card_num_ida, pcard->card_num);
 491 err_free_pcard:
 492         kfree(pcard);
 493         return err;
 494 }
 495 
 496 static void kp2000_pcie_remove(struct pci_dev *pdev)
 497 {
 498         struct kp2000_device *pcard = pci_get_drvdata(pdev);
 499 
 500         if (!pcard)
 501                 return;
 502 
 503         mutex_lock(&pcard->sem);
 504         kp2000_remove_cores(pcard);
 505         mfd_remove_devices(PCARD_TO_DEV(pcard));
 506         sysfs_remove_files(&pdev->dev.kobj, kp_attr_list);
 507         free_irq(pcard->pdev->irq, pcard);
 508         pci_disable_msi(pcard->pdev);
 509         if (pcard->dma_bar_base) {
 510                 iounmap(pcard->dma_bar_base);
 511                 pci_release_region(pdev, DMA_BAR);
 512                 pcard->dma_bar_base = NULL;
 513         }
 514         if (pcard->regs_bar_base) {
 515                 iounmap(pcard->regs_bar_base);
 516                 pci_release_region(pdev, REG_BAR);
 517                 pcard->regs_bar_base = NULL;
 518         }
 519         pci_disable_device(pcard->pdev);
 520         pci_set_drvdata(pdev, NULL);
 521         mutex_unlock(&pcard->sem);
 522         ida_simple_remove(&card_num_ida, pcard->card_num);
 523         kfree(pcard);
 524 }
 525 
 526 struct class *kpc_uio_class;
 527 ATTRIBUTE_GROUPS(kpc_uio_class);
 528 
 529 static const struct pci_device_id kp2000_pci_device_ids[] = {
 530         { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) },
 531         { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) },
 532         { 0, }
 533 };
 534 MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids);
 535 
 536 static struct pci_driver kp2000_driver_inst = {
 537         .name =         "kp2000_pcie",
 538         .id_table =     kp2000_pci_device_ids,
 539         .probe =        kp2000_pcie_probe,
 540         .remove =       kp2000_pcie_remove,
 541 };
 542 
 543 static int __init kp2000_pcie_init(void)
 544 {
 545         kpc_uio_class = class_create(THIS_MODULE, "kpc_uio");
 546         if (IS_ERR(kpc_uio_class))
 547                 return PTR_ERR(kpc_uio_class);
 548 
 549         kpc_uio_class->dev_groups = kpc_uio_class_groups;
 550         return pci_register_driver(&kp2000_driver_inst);
 551 }
 552 module_init(kp2000_pcie_init);
 553 
 554 static void __exit kp2000_pcie_exit(void)
 555 {
 556         pci_unregister_driver(&kp2000_driver_inst);
 557         class_destroy(kpc_uio_class);
 558         ida_destroy(&card_num_ida);
 559 }
 560 module_exit(kp2000_pcie_exit);
 561 
 562 MODULE_LICENSE("GPL");
 563 MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com");
 564 MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi");

/* [<][>][^][v][top][bottom][index][help] */