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 
ssid_show(struct device * dev,struct device_attribute * attr,char * buf)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 
ddna_show(struct device * dev,struct device_attribute * attr,char * buf)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 
card_id_show(struct device * dev,struct device_attribute * attr,char * buf)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 
hw_rev_show(struct device * dev,struct device_attribute * attr,char * buf)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 
build_show(struct device * dev,struct device_attribute * attr,char * buf)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 
build_date_show(struct device * dev,struct device_attribute * attr,char * buf)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 
build_time_show(struct device * dev,struct device_attribute * attr,char * buf)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 
cpld_reg_show(struct device * dev,struct device_attribute * attr,char * buf)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 
cpld_reconfigure(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 	long wr_val;
114 	int rv;
115 
116 	rv = kstrtol(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 
irq_mask_reg_show(struct device * dev,struct device_attribute * attr,char * buf)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 
irq_active_reg_show(struct device * dev,struct device_attribute * attr,char * buf)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 
pcie_error_count_reg_show(struct device * dev,struct device_attribute * attr,char * buf)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 
core_table_offset_show(struct device * dev,struct device_attribute * attr,char * buf)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 
core_table_length_show(struct device * dev,struct device_attribute * attr,char * buf)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 
wait_and_read_ssid(struct kp2000_device * pcard)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 
read_system_regs(struct kp2000_device * pcard)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 
kp2000_irq_handler(int irq,void * dev_id)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 
kp2000_pcie_probe(struct pci_dev * pdev,const struct pci_device_id * id)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 	int rv;
302 	unsigned long reg_bar_phys_addr;
303 	unsigned long reg_bar_phys_len;
304 	unsigned long dma_bar_phys_addr;
305 	unsigned long dma_bar_phys_len;
306 	u16 regval;
307 
308 	pcard = kzalloc(sizeof(*pcard), GFP_KERNEL);
309 	if (!pcard)
310 		return -ENOMEM;
311 	dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n",
312 		pcard);
313 
314 	err = ida_simple_get(&card_num_ida, 1, INT_MAX, GFP_KERNEL);
315 	if (err < 0) {
316 		dev_err(&pdev->dev, "probe: failed to get card number (%d)\n",
317 			err);
318 		goto err_free_pcard;
319 	}
320 	pcard->card_num = err;
321 	scnprintf(pcard->name, 16, "kpcard%u", pcard->card_num);
322 
323 	mutex_init(&pcard->sem);
324 	mutex_lock(&pcard->sem);
325 
326 	pcard->pdev = pdev;
327 	pci_set_drvdata(pdev, pcard);
328 
329 	err = pci_enable_device(pcard->pdev);
330 	if (err) {
331 		dev_err(&pcard->pdev->dev,
332 			"probe: failed to enable PCIE2000 PCIe device (%d)\n",
333 			err);
334 		goto err_remove_ida;
335 	}
336 
337 	/* Setup the Register BAR */
338 	reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR);
339 	reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR);
340 
341 	pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE);
342 	if (!pcard->regs_bar_base) {
343 		dev_err(&pcard->pdev->dev,
344 			"probe: REG_BAR could not remap memory to virtual space\n");
345 		err = -ENODEV;
346 		goto err_disable_device;
347 	}
348 	dev_dbg(&pcard->pdev->dev,
349 		"probe: REG_BAR virt hardware address start [%p]\n",
350 		pcard->regs_bar_base);
351 
352 	err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000);
353 	if (err) {
354 		dev_err(&pcard->pdev->dev,
355 			"probe: failed to acquire PCI region (%d)\n",
356 			err);
357 		err = -ENODEV;
358 		goto err_unmap_regs;
359 	}
360 
361 	pcard->regs_base_resource.start = reg_bar_phys_addr;
362 	pcard->regs_base_resource.end   = reg_bar_phys_addr +
363 					  reg_bar_phys_len - 1;
364 	pcard->regs_base_resource.flags = IORESOURCE_MEM;
365 
366 	/* Setup the DMA BAR */
367 	dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR);
368 	dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR);
369 
370 	pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr,
371 					      dma_bar_phys_len);
372 	if (!pcard->dma_bar_base) {
373 		dev_err(&pcard->pdev->dev,
374 			"probe: DMA_BAR could not remap memory to virtual space\n");
375 		err = -ENODEV;
376 		goto err_release_regs;
377 	}
378 	dev_dbg(&pcard->pdev->dev,
379 		"probe: DMA_BAR virt hardware address start [%p]\n",
380 		pcard->dma_bar_base);
381 
382 	pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET;
383 
384 	err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie");
385 	if (err) {
386 		dev_err(&pcard->pdev->dev,
387 			"probe: failed to acquire PCI region (%d)\n", err);
388 		err = -ENODEV;
389 		goto err_unmap_dma;
390 	}
391 
392 	pcard->dma_base_resource.start = dma_bar_phys_addr;
393 	pcard->dma_base_resource.end   = dma_bar_phys_addr +
394 					 dma_bar_phys_len - 1;
395 	pcard->dma_base_resource.flags = IORESOURCE_MEM;
396 
397 	/* Read System Regs */
398 	pcard->sysinfo_regs_base = pcard->regs_bar_base;
399 	err = read_system_regs(pcard);
400 	if (err)
401 		goto err_release_dma;
402 
403 	// Disable all "user" interrupts because they're not used yet.
404 	writeq(0xFFFFFFFFFFFFFFFFUL,
405 	       pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
406 
407 	// let the card master PCIe
408 	pci_set_master(pcard->pdev);
409 
410 	// enable IO and mem if not already done
411 	pci_read_config_word(pcard->pdev, PCI_COMMAND, &regval);
412 	regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
413 	pci_write_config_word(pcard->pdev, PCI_COMMAND, regval);
414 
415 	// Clear relaxed ordering bit
416 	pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
417 					   PCI_EXP_DEVCTL_RELAX_EN, 0);
418 
419 	// Set Max_Payload_Size and Max_Read_Request_Size
420 	regval = (0x0) << 5; // Max_Payload_Size = 128 B
421 	pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
422 					   PCI_EXP_DEVCTL_PAYLOAD, regval);
423 	regval = (0x0) << 12; // Max_Read_Request_Size = 128 B
424 	pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
425 					   PCI_EXP_DEVCTL_READRQ, regval);
426 
427 	// Enable error reporting for: Correctable Errors, Non-Fatal Errors,
428 	// Fatal Errors, Unsupported Requests
429 	pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0,
430 					   PCI_EXP_DEVCTL_CERE |
431 					   PCI_EXP_DEVCTL_NFERE |
432 					   PCI_EXP_DEVCTL_FERE |
433 					   PCI_EXP_DEVCTL_URRE);
434 
435 	err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64));
436 	if (err) {
437 		dev_err(&pcard->pdev->dev,
438 			"CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64));
439 		goto err_release_dma;
440 	}
441 	dev_dbg(&pcard->pdev->dev,
442 		"Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard)));
443 
444 	err = pci_enable_msi(pcard->pdev);
445 	if (err < 0)
446 		goto err_release_dma;
447 
448 	rv = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED,
449 			 pcard->name, pcard);
450 	if (rv) {
451 		dev_err(&pcard->pdev->dev,
452 			"%s: failed to request_irq: %d\n", __func__, rv);
453 		goto err_disable_msi;
454 	}
455 
456 	err = sysfs_create_files(&pdev->dev.kobj, kp_attr_list);
457 	if (err) {
458 		dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err);
459 		goto err_free_irq;
460 	}
461 
462 	err = kp2000_probe_cores(pcard);
463 	if (err)
464 		goto err_remove_sysfs;
465 
466 	/* Enable IRQs in HW */
467 	writel(KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE,
468 	       pcard->dma_common_regs);
469 
470 	mutex_unlock(&pcard->sem);
471 	return 0;
472 
473 err_remove_sysfs:
474 	sysfs_remove_files(&pdev->dev.kobj, kp_attr_list);
475 err_free_irq:
476 	free_irq(pcard->pdev->irq, pcard);
477 err_disable_msi:
478 	pci_disable_msi(pcard->pdev);
479 err_release_dma:
480 	pci_release_region(pdev, DMA_BAR);
481 err_unmap_dma:
482 	iounmap(pcard->dma_bar_base);
483 err_release_regs:
484 	pci_release_region(pdev, REG_BAR);
485 err_unmap_regs:
486 	iounmap(pcard->regs_bar_base);
487 err_disable_device:
488 	pci_disable_device(pcard->pdev);
489 err_remove_ida:
490 	mutex_unlock(&pcard->sem);
491 	ida_simple_remove(&card_num_ida, pcard->card_num);
492 err_free_pcard:
493 	kfree(pcard);
494 	return err;
495 }
496 
kp2000_pcie_remove(struct pci_dev * pdev)497 static void kp2000_pcie_remove(struct pci_dev *pdev)
498 {
499 	struct kp2000_device *pcard = pci_get_drvdata(pdev);
500 
501 	if (!pcard)
502 		return;
503 
504 	mutex_lock(&pcard->sem);
505 	kp2000_remove_cores(pcard);
506 	mfd_remove_devices(PCARD_TO_DEV(pcard));
507 	sysfs_remove_files(&pdev->dev.kobj, kp_attr_list);
508 	free_irq(pcard->pdev->irq, pcard);
509 	pci_disable_msi(pcard->pdev);
510 	if (pcard->dma_bar_base) {
511 		iounmap(pcard->dma_bar_base);
512 		pci_release_region(pdev, DMA_BAR);
513 		pcard->dma_bar_base = NULL;
514 	}
515 	if (pcard->regs_bar_base) {
516 		iounmap(pcard->regs_bar_base);
517 		pci_release_region(pdev, REG_BAR);
518 		pcard->regs_bar_base = NULL;
519 	}
520 	pci_disable_device(pcard->pdev);
521 	pci_set_drvdata(pdev, NULL);
522 	mutex_unlock(&pcard->sem);
523 	ida_simple_remove(&card_num_ida, pcard->card_num);
524 	kfree(pcard);
525 }
526 
527 struct class *kpc_uio_class;
528 ATTRIBUTE_GROUPS(kpc_uio_class);
529 
530 static const struct pci_device_id kp2000_pci_device_ids[] = {
531 	{ PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) },
532 	{ PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) },
533 	{ 0, }
534 };
535 MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids);
536 
537 static struct pci_driver kp2000_driver_inst = {
538 	.name =		"kp2000_pcie",
539 	.id_table =	kp2000_pci_device_ids,
540 	.probe =	kp2000_pcie_probe,
541 	.remove =	kp2000_pcie_remove,
542 };
543 
kp2000_pcie_init(void)544 static int __init kp2000_pcie_init(void)
545 {
546 	kpc_uio_class = class_create(THIS_MODULE, "kpc_uio");
547 	if (IS_ERR(kpc_uio_class))
548 		return PTR_ERR(kpc_uio_class);
549 
550 	kpc_uio_class->dev_groups = kpc_uio_class_groups;
551 	return pci_register_driver(&kp2000_driver_inst);
552 }
553 module_init(kp2000_pcie_init);
554 
kp2000_pcie_exit(void)555 static void __exit kp2000_pcie_exit(void)
556 {
557 	pci_unregister_driver(&kp2000_driver_inst);
558 	class_destroy(kpc_uio_class);
559 	ida_destroy(&card_num_ida);
560 }
561 module_exit(kp2000_pcie_exit);
562 
563 MODULE_LICENSE("GPL");
564 MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com");
565 MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi");
566