Blame view

drivers/uio/uio_cif.c 3.49 KB
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
1
2
3
  /*
   * UIO Hilscher CIF card driver
   *
318af55dd   Hans J. Koch   uio: Change mail ...
4
   * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
5
6
7
8
9
10
11
12
13
   * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
   *
   * Licensed under GPL version 2 only.
   *
   */
  
  #include <linux/device.h>
  #include <linux/module.h>
  #include <linux/pci.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
14
  #include <linux/slab.h>
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
15
16
17
  #include <linux/uio_driver.h>
  
  #include <asm/io.h>
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  #define PLX9030_INTCSR		0x4C
  #define INTSCR_INT1_ENABLE	0x01
  #define INTSCR_INT1_STATUS	0x04
  #define INT1_ENABLED_AND_ACTIVE	(INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
  
  #define PCI_SUBVENDOR_ID_PEP	0x1518
  #define CIF_SUBDEVICE_PROFIBUS	0x430
  #define CIF_SUBDEVICE_DEVICENET	0x432
  
  
  static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
  {
  	void __iomem *plx_intscr = dev_info->mem[0].internal_addr
  					+ PLX9030_INTCSR;
  
  	if ((ioread8(plx_intscr) & INT1_ENABLED_AND_ACTIVE)
  	    != INT1_ENABLED_AND_ACTIVE)
  		return IRQ_NONE;
  
  	/* Disable interrupt */
  	iowrite8(ioread8(plx_intscr) & ~INTSCR_INT1_ENABLE, plx_intscr);
  	return IRQ_HANDLED;
  }
  
  static int __devinit hilscher_pci_probe(struct pci_dev *dev,
  					const struct pci_device_id *id)
  {
  	struct uio_info *info;
  
  	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
  	if (!info)
  		return -ENOMEM;
  
  	if (pci_enable_device(dev))
  		goto out_free;
  
  	if (pci_request_regions(dev, "hilscher"))
  		goto out_disable;
  
  	info->mem[0].addr = pci_resource_start(dev, 0);
  	if (!info->mem[0].addr)
  		goto out_release;
7898aa5c3   Arjan van de Ven   UIO: use pci_iore...
60
  	info->mem[0].internal_addr = pci_ioremap_bar(dev, 0);
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  	if (!info->mem[0].internal_addr)
  		goto out_release;
  
  	info->mem[0].size = pci_resource_len(dev, 0);
  	info->mem[0].memtype = UIO_MEM_PHYS;
  	info->mem[1].addr = pci_resource_start(dev, 2);
  	info->mem[1].size = pci_resource_len(dev, 2);
  	info->mem[1].memtype = UIO_MEM_PHYS;
  	switch (id->subdevice) {
  		case CIF_SUBDEVICE_PROFIBUS:
  			info->name = "CIF_Profibus";
  			break;
  		case CIF_SUBDEVICE_DEVICENET:
  			info->name = "CIF_Devicenet";
  			break;
  		default:
  			info->name = "CIF_???";
  	}
  	info->version = "0.0.1";
  	info->irq = dev->irq;
14ec53948   Hans J. Koch   uio: Remove IRQF_...
81
  	info->irq_flags = IRQF_SHARED;
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	info->handler = hilscher_handler;
  
  	if (uio_register_device(&dev->dev, info))
  		goto out_unmap;
  
  	pci_set_drvdata(dev, info);
  
  	return 0;
  out_unmap:
  	iounmap(info->mem[0].internal_addr);
  out_release:
  	pci_release_regions(dev);
  out_disable:
  	pci_disable_device(dev);
  out_free:
  	kfree (info);
  	return -ENODEV;
  }
  
  static void hilscher_pci_remove(struct pci_dev *dev)
  {
  	struct uio_info *info = pci_get_drvdata(dev);
  
  	uio_unregister_device(info);
  	pci_release_regions(dev);
  	pci_disable_device(dev);
  	pci_set_drvdata(dev, NULL);
  	iounmap(info->mem[0].internal_addr);
  
  	kfree (info);
  }
0732460b3   Denis Cheng   uio: mark pci_dev...
113
  static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  	{
  		.vendor =	PCI_VENDOR_ID_PLX,
  		.device =	PCI_DEVICE_ID_PLX_9030,
  		.subvendor =	PCI_SUBVENDOR_ID_PEP,
  		.subdevice =	CIF_SUBDEVICE_PROFIBUS,
  	},
  	{
  		.vendor =	PCI_VENDOR_ID_PLX,
  		.device =	PCI_DEVICE_ID_PLX_9030,
  		.subvendor =	PCI_SUBVENDOR_ID_PEP,
  		.subdevice =	CIF_SUBDEVICE_DEVICENET,
  	},
  	{ 0, }
  };
  
  static struct pci_driver hilscher_pci_driver = {
  	.name = "hilscher",
  	.id_table = hilscher_pci_ids,
  	.probe = hilscher_pci_probe,
  	.remove = hilscher_pci_remove,
  };
  
  static int __init hilscher_init_module(void)
  {
  	return pci_register_driver(&hilscher_pci_driver);
  }
  
  static void __exit hilscher_exit_module(void)
  {
  	pci_unregister_driver(&hilscher_pci_driver);
  }
  
  module_init(hilscher_init_module);
  module_exit(hilscher_exit_module);
912335c43   Hans J. Koch   UIO: fix specific...
148
  MODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
bc4c4f45a   Hans-Jürgen Koch   UIO: Hilscher CIF...
149
150
  MODULE_LICENSE("GPL v2");
  MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");