1 /* uio_ehci_pci - UIO driver for PCI EHCI devices */
2 /* This only implements MMIO access (no interrupts). */
3 /* SPDX-License-Identifier: GPL-2.0-only */
4
5 #include <linux/device.h>
6 #include <linux/module.h>
7 #include <linux/pci.h>
8 #include <linux/uio_driver.h>
9
10 #define DRIVER_VERSION "0.0.1"
11 #define DRIVER_AUTHOR "Nico Huber <[email protected]>"
12 #define DRIVER_DESC "UIO driver for PCI EHCI devices"
13 #define DRIVER_TAG "uio_ehci_pci"
14
probe(struct pci_dev * const pci_dev,const struct pci_device_id * const did)15 static int probe(struct pci_dev *const pci_dev,
16 const struct pci_device_id *const did)
17 {
18 struct uio_info *info;
19 int ret;
20
21 ret = pci_enable_device(pci_dev);
22 if (ret)
23 goto return_;
24
25 ret = pci_request_regions(pci_dev, DRIVER_TAG);
26 if (ret)
27 goto return_disable;
28
29 info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
30 if (!info) {
31 ret = -ENOMEM;
32 goto return_release;
33 }
34
35 info->name = DRIVER_TAG;
36 info->version = DRIVER_VERSION;
37
38 info->mem[0].name = "EHCI MMIO area";
39 info->mem[0].addr = pci_resource_start(pci_dev, 0);
40 if (!info->mem[0].addr) {
41 ret = -ENODEV;
42 goto return_free;
43 }
44 info->mem[0].size = pci_resource_len(pci_dev, 0);
45 info->mem[0].memtype = UIO_MEM_PHYS;
46
47 ret = uio_register_device(&pci_dev->dev, info);
48 if (ret)
49 goto return_free;
50 pci_set_drvdata(pci_dev, info);
51
52 return 0;
53 return_free:
54 kfree(info);
55 return_release:
56 pci_release_regions(pci_dev);
57 return_disable:
58 pci_disable_device(pci_dev);
59 return_:
60 return ret;
61 }
62
remove(struct pci_dev * const pci_dev)63 static void remove(struct pci_dev *const pci_dev)
64 {
65 struct uio_info *const info = pci_get_drvdata(pci_dev);
66
67 uio_unregister_device(info);
68 kfree(info);
69 pci_release_regions(pci_dev);
70 pci_disable_device(pci_dev);
71 }
72
73 static DEFINE_PCI_DEVICE_TABLE(ehci_pci_ids) = {
74 { PCI_DEVICE(0x8086, 0x27cc) },
75 { 0, }
76 };
77
78 static struct pci_driver uio_ehci_pci_driver = {
79 .name = DRIVER_TAG,
80 .id_table = ehci_pci_ids,
81 .probe = probe,
82 .remove = remove,
83 };
84
85 module_pci_driver(uio_ehci_pci_driver);
86 MODULE_VERSION(DRIVER_VERSION);
87 MODULE_LICENSE("GPL v2");
88 MODULE_AUTHOR(DRIVER_AUTHOR);
89 MODULE_DESCRIPTION(DRIVER_DESC);
90