1 // SPDX-License-Identifier: GPL-2.0
3 * UIO Hilscher CIF card driver
5 * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
6 * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
9 #include <linux/device.h>
10 #include <linux/module.h>
11 #include <linux/pci.h>
12 #include <linux/slab.h>
13 #include <linux/uio_driver.h>
17 #define PLX9030_INTCSR 0x4C
18 #define INTSCR_INT1_ENABLE 0x01
19 #define INTSCR_INT1_STATUS 0x04
20 #define INT1_ENABLED_AND_ACTIVE (INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
22 #define PCI_SUBVENDOR_ID_PEP 0x1518
23 #define CIF_SUBDEVICE_PROFIBUS 0x430
24 #define CIF_SUBDEVICE_DEVICENET 0x432
27 static irqreturn_t
hilscher_handler(int irq
, struct uio_info
*dev_info
)
29 void __iomem
*plx_intscr
= dev_info
->mem
[0].internal_addr
32 if ((ioread8(plx_intscr
) & INT1_ENABLED_AND_ACTIVE
)
33 != INT1_ENABLED_AND_ACTIVE
)
36 /* Disable interrupt */
37 iowrite8(ioread8(plx_intscr
) & ~INTSCR_INT1_ENABLE
, plx_intscr
);
41 static int hilscher_pci_probe(struct pci_dev
*dev
,
42 const struct pci_device_id
*id
)
44 struct uio_info
*info
;
46 info
= devm_kzalloc(&dev
->dev
, sizeof(struct uio_info
), GFP_KERNEL
);
50 if (pci_enable_device(dev
))
53 if (pci_request_regions(dev
, "hilscher"))
56 info
->mem
[0].addr
= pci_resource_start(dev
, 0);
57 if (!info
->mem
[0].addr
)
59 info
->mem
[0].internal_addr
= pci_ioremap_bar(dev
, 0);
60 if (!info
->mem
[0].internal_addr
)
63 info
->mem
[0].size
= pci_resource_len(dev
, 0);
64 info
->mem
[0].memtype
= UIO_MEM_PHYS
;
65 info
->mem
[1].addr
= pci_resource_start(dev
, 2);
66 info
->mem
[1].size
= pci_resource_len(dev
, 2);
67 info
->mem
[1].memtype
= UIO_MEM_PHYS
;
68 switch (id
->subdevice
) {
69 case CIF_SUBDEVICE_PROFIBUS
:
70 info
->name
= "CIF_Profibus";
72 case CIF_SUBDEVICE_DEVICENET
:
73 info
->name
= "CIF_Devicenet";
76 info
->name
= "CIF_???";
78 info
->version
= "0.0.1";
80 info
->irq_flags
= IRQF_SHARED
;
81 info
->handler
= hilscher_handler
;
83 if (uio_register_device(&dev
->dev
, info
))
86 pci_set_drvdata(dev
, info
);
90 iounmap(info
->mem
[0].internal_addr
);
92 pci_release_regions(dev
);
94 pci_disable_device(dev
);
98 static void hilscher_pci_remove(struct pci_dev
*dev
)
100 struct uio_info
*info
= pci_get_drvdata(dev
);
102 uio_unregister_device(info
);
103 pci_release_regions(dev
);
104 pci_disable_device(dev
);
105 iounmap(info
->mem
[0].internal_addr
);
108 static struct pci_device_id hilscher_pci_ids
[] = {
110 .vendor
= PCI_VENDOR_ID_PLX
,
111 .device
= PCI_DEVICE_ID_PLX_9030
,
112 .subvendor
= PCI_SUBVENDOR_ID_PEP
,
113 .subdevice
= CIF_SUBDEVICE_PROFIBUS
,
116 .vendor
= PCI_VENDOR_ID_PLX
,
117 .device
= PCI_DEVICE_ID_PLX_9030
,
118 .subvendor
= PCI_SUBVENDOR_ID_PEP
,
119 .subdevice
= CIF_SUBDEVICE_DEVICENET
,
124 static struct pci_driver hilscher_pci_driver
= {
126 .id_table
= hilscher_pci_ids
,
127 .probe
= hilscher_pci_probe
,
128 .remove
= hilscher_pci_remove
,
131 module_pci_driver(hilscher_pci_driver
);
132 MODULE_DEVICE_TABLE(pci
, hilscher_pci_ids
);
133 MODULE_LICENSE("GPL v2");
134 MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");