1bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch/*
2bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch * UIO Hilscher CIF card driver
3bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch *
4318af55ddd38bdaaa2b57f5c3bd394f3ce3a2610Hans J. Koch * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
5bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
6bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch *
7bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch * Licensed under GPL version 2 only.
8bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch *
9bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch */
10bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
11bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#include <linux/device.h>
12bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#include <linux/module.h>
13bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#include <linux/pci.h>
145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
15bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#include <linux/uio_driver.h>
16bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
17bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#include <asm/io.h>
18bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
19bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define PLX9030_INTCSR		0x4C
20bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define INTSCR_INT1_ENABLE	0x01
21bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define INTSCR_INT1_STATUS	0x04
22bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define INT1_ENABLED_AND_ACTIVE	(INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
23bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
24bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define PCI_SUBVENDOR_ID_PEP	0x1518
25bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define CIF_SUBDEVICE_PROFIBUS	0x430
26bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch#define CIF_SUBDEVICE_DEVICENET	0x432
27bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
28bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
29bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochstatic irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
30bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch{
31bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	void __iomem *plx_intscr = dev_info->mem[0].internal_addr
32bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch					+ PLX9030_INTCSR;
33bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
34bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if ((ioread8(plx_intscr) & INT1_ENABLED_AND_ACTIVE)
35bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	    != INT1_ENABLED_AND_ACTIVE)
36bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		return IRQ_NONE;
37bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
38bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	/* Disable interrupt */
39bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	iowrite8(ioread8(plx_intscr) & ~INTSCR_INT1_ENABLE, plx_intscr);
40bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	return IRQ_HANDLED;
41bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch}
42bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
43b17b75bb524c6c0dfa5ee4a33591b8a7dcc034d2Bill Pembertonstatic int hilscher_pci_probe(struct pci_dev *dev,
44bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch					const struct pci_device_id *id)
45bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch{
46bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	struct uio_info *info;
47bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
48bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
49bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if (!info)
50bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		return -ENOMEM;
51bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
52bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if (pci_enable_device(dev))
53bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		goto out_free;
54bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
55bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if (pci_request_regions(dev, "hilscher"))
56bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		goto out_disable;
57bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
58bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->mem[0].addr = pci_resource_start(dev, 0);
59bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if (!info->mem[0].addr)
60bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		goto out_release;
617898aa5c39d159684dad15bab1150b8e77c7aed6Arjan van de Ven	info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
62bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if (!info->mem[0].internal_addr)
63bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		goto out_release;
64bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
65bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->mem[0].size = pci_resource_len(dev, 0);
66bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->mem[0].memtype = UIO_MEM_PHYS;
67bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->mem[1].addr = pci_resource_start(dev, 2);
68bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->mem[1].size = pci_resource_len(dev, 2);
69bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->mem[1].memtype = UIO_MEM_PHYS;
70bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	switch (id->subdevice) {
71bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		case CIF_SUBDEVICE_PROFIBUS:
72bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch			info->name = "CIF_Profibus";
73bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch			break;
74bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		case CIF_SUBDEVICE_DEVICENET:
75bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch			info->name = "CIF_Devicenet";
76bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch			break;
77bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		default:
78bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch			info->name = "CIF_???";
79bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	}
80bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->version = "0.0.1";
81bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->irq = dev->irq;
8214ec5394827eea8df7bbf14775c52fc48fc97a40Hans J. Koch	info->irq_flags = IRQF_SHARED;
83bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	info->handler = hilscher_handler;
84bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
85bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	if (uio_register_device(&dev->dev, info))
86bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		goto out_unmap;
87bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
88bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	pci_set_drvdata(dev, info);
89bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
90bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	return 0;
91bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochout_unmap:
92bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	iounmap(info->mem[0].internal_addr);
93bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochout_release:
94bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	pci_release_regions(dev);
95bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochout_disable:
96bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	pci_disable_device(dev);
97bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochout_free:
98bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	kfree (info);
99bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	return -ENODEV;
100bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch}
101bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
102bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochstatic void hilscher_pci_remove(struct pci_dev *dev)
103bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch{
104bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	struct uio_info *info = pci_get_drvdata(dev);
105bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
106bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	uio_unregister_device(info);
107bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	pci_release_regions(dev);
108bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	pci_disable_device(dev);
109bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	iounmap(info->mem[0].internal_addr);
110bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
111bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	kfree (info);
112bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch}
113bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
114d46f743822ee6e890a6e7971e089a020e6c0000aBill Pembertonstatic struct pci_device_id hilscher_pci_ids[] = {
115bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	{
116bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.vendor =	PCI_VENDOR_ID_PLX,
117bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.device =	PCI_DEVICE_ID_PLX_9030,
118bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.subvendor =	PCI_SUBVENDOR_ID_PEP,
119bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.subdevice =	CIF_SUBDEVICE_PROFIBUS,
120bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	},
121bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	{
122bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.vendor =	PCI_VENDOR_ID_PLX,
123bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.device =	PCI_DEVICE_ID_PLX_9030,
124bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.subvendor =	PCI_SUBVENDOR_ID_PEP,
125bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch		.subdevice =	CIF_SUBDEVICE_DEVICENET,
126bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	},
127bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	{ 0, }
128bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch};
129bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
130bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Kochstatic struct pci_driver hilscher_pci_driver = {
131bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	.name = "hilscher",
132bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	.id_table = hilscher_pci_ids,
133bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	.probe = hilscher_pci_probe,
134bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch	.remove = hilscher_pci_remove,
135bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch};
136bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen Koch
137ced9017a4fc7ecf35a9c0c0bd8e46d14876b9fd1Peter Huewemodule_pci_driver(hilscher_pci_driver);
138912335c43bb10d124471bf063a85e132aa814214Hans J. KochMODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
139bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen KochMODULE_LICENSE("GPL v2");
140bc4c4f45acbe1f1528d654b0b1793f25c175bf8fHans-Jürgen KochMODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
141