staging: comedi: adl_pci9111: fix incorrect irq passed to request_irq()
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / drivers / addi-data / addi_common.c
1 /**
2 @verbatim
3
4 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6         ADDI-DATA GmbH
7         Dieselstrasse 3
8         D-77833 Ottersweier
9         Tel: +19(0)7223/9493-0
10         Fax: +49(0)7223/9493-92
11         http://www.addi-data.com
12         info@addi-data.com
13
14 This program is free software; you can redistribute it and/or modify it under
15 the terms of the GNU General Public License as published by the Free Software
16 Foundation; either version 2 of the License, or (at your option) any later
17 version.
18
19 This program is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 PARTICULAR PURPOSE. See the GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License along with
24 this program; if not, write to the Free Software Foundation, Inc.,
25 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26
27 You should also find the complete GPL in the COPYING file accompanying this
28 source code.
29
30 @endverbatim
31 */
32 /*
33
34   +-----------------------------------------------------------------------+
35   | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
36   +-----------------------------------------------------------------------+
37   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
38   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
39   +-----------------------------------------------------------------------+
40   | Project   : ADDI DATA         | Compiler : GCC                        |
41   | Modulname : addi_common.c     | Version  : 2.96                       |
42   +-------------------------------+---------------------------------------+
43   | Author    :           | Date     :                                    |
44   +-----------------------------------------------------------------------+
45   | Description : ADDI COMMON Main Module                                 |
46   +-----------------------------------------------------------------------+
47 */
48
49 #ifndef COMEDI_SUBD_TTLIO
50 #define COMEDI_SUBD_TTLIO   11  /* Digital Input Output But TTL */
51 #endif
52
53 static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev,
54                                      struct comedi_subdevice *s,
55                                      struct comedi_insn *insn,
56                                      unsigned int *data)
57 {
58         const struct addi_board *this_board = comedi_board(dev);
59         struct addi_private *devpriv = dev->private;
60         unsigned short w_Address = CR_CHAN(insn->chanspec);
61         unsigned short w_Data;
62
63         w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
64                 this_board->pc_EepromChip, 2 * w_Address);
65         data[0] = w_Data;
66
67         return insn->n;
68 }
69
70 static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
71 {
72         struct comedi_device *dev = d;
73         const struct addi_board *this_board = comedi_board(dev);
74
75         this_board->interrupt(irq, d);
76         return IRQ_RETVAL(1);
77 }
78
79 static int i_ADDI_Reset(struct comedi_device *dev)
80 {
81         const struct addi_board *this_board = comedi_board(dev);
82
83         this_board->reset(dev);
84         return 0;
85 }
86
87 static int addi_auto_attach(struct comedi_device *dev,
88                                       unsigned long context_unused)
89 {
90         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
91         const struct addi_board *this_board = comedi_board(dev);
92         struct addi_private *devpriv;
93         struct comedi_subdevice *s;
94         int ret, n_subdevices;
95         unsigned int dw_Dummy;
96
97         dev->board_name = this_board->pc_DriverName;
98
99         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
100         if (!devpriv)
101                 return -ENOMEM;
102         dev->private = devpriv;
103
104         ret = comedi_pci_enable(dev);
105         if (ret)
106                 return ret;
107
108         if (!this_board->pc_EepromChip ||
109             strcmp(this_board->pc_EepromChip, ADDIDATA_9054)) {
110                 /* board does not have an eeprom or is not ADDIDATA_9054 */
111                 if (this_board->i_IorangeBase1)
112                         dev->iobase = pci_resource_start(pcidev, 1);
113                 else
114                         dev->iobase = pci_resource_start(pcidev, 0);
115
116                 devpriv->iobase = dev->iobase;
117                 devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
118                 devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
119         } else {
120                 /* board has an ADDIDATA_9054 eeprom */
121                 dev->iobase = pci_resource_start(pcidev, 2);
122                 devpriv->iobase = pci_resource_start(pcidev, 2);
123                 devpriv->dw_AiBase = pci_ioremap_bar(pcidev, 3);
124         }
125         devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
126
127         /* Initialize parameters that can be overridden in EEPROM */
128         devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel;
129         devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel;
130         devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata;
131         devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata;
132         devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel;
133         devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel;
134         devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata;
135         devpriv->s_EeParameters.i_Dma = this_board->i_Dma;
136         devpriv->s_EeParameters.i_Timer = this_board->i_Timer;
137         devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
138                 this_board->ui_MinAcquisitiontimeNs;
139         devpriv->s_EeParameters.ui_MinDelaytimeNs =
140                 this_board->ui_MinDelaytimeNs;
141
142         /* ## */
143
144         if (pcidev->irq > 0) {
145                 ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
146                                   dev->board_name, dev);
147                 if (ret == 0)
148                         dev->irq = pcidev->irq;
149         }
150
151         /*  Read eepeom and fill addi_board Structure */
152
153         if (this_board->i_PCIEeprom) {
154                 if (!(strcmp(this_board->pc_EepromChip, "S5920"))) {
155                         /*  Set 3 wait stait */
156                         if (!(strcmp(dev->board_name, "apci035")))
157                                 outl(0x80808082, devpriv->i_IobaseAmcc + 0x60);
158                         else
159                                 outl(0x83838383, devpriv->i_IobaseAmcc + 0x60);
160
161                         /*  Enable the interrupt for the controller */
162                         dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38);
163                         outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38);
164                 }
165                 addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0));
166         }
167
168         n_subdevices = 7;
169         ret = comedi_alloc_subdevices(dev, n_subdevices);
170         if (ret)
171                 return ret;
172
173         /*  Allocate and Initialise AI Subdevice Structures */
174         s = &dev->subdevices[0];
175         if ((devpriv->s_EeParameters.i_NbrAiChannel)
176                 || (this_board->i_NbrAiChannelDiff)) {
177                 dev->read_subdev = s;
178                 s->type = COMEDI_SUBD_AI;
179                 s->subdev_flags =
180                         SDF_READABLE | SDF_COMMON | SDF_GROUND
181                         | SDF_DIFF;
182                 if (devpriv->s_EeParameters.i_NbrAiChannel) {
183                         s->n_chan =
184                                 devpriv->s_EeParameters.i_NbrAiChannel;
185                         devpriv->b_SingelDiff = 0;
186                 } else {
187                         s->n_chan = this_board->i_NbrAiChannelDiff;
188                         devpriv->b_SingelDiff = 1;
189                 }
190                 s->maxdata = devpriv->s_EeParameters.i_AiMaxdata;
191                 s->len_chanlist = this_board->i_AiChannelList;
192                 s->range_table = this_board->pr_AiRangelist;
193
194                 /* Set the initialisation flag */
195                 devpriv->b_AiInitialisation = 1;
196
197                 s->insn_config = this_board->ai_config;
198                 s->insn_read = this_board->ai_read;
199                 s->insn_write = this_board->ai_write;
200                 s->insn_bits = this_board->ai_bits;
201                 s->do_cmdtest = this_board->ai_cmdtest;
202                 s->do_cmd = this_board->ai_cmd;
203                 s->cancel = this_board->ai_cancel;
204
205         } else {
206                 s->type = COMEDI_SUBD_UNUSED;
207         }
208
209         /*  Allocate and Initialise AO Subdevice Structures */
210         s = &dev->subdevices[1];
211         if (devpriv->s_EeParameters.i_NbrAoChannel) {
212                 s->type = COMEDI_SUBD_AO;
213                 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
214                 s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
215                 s->maxdata = devpriv->s_EeParameters.i_AoMaxdata;
216                 s->len_chanlist =
217                         devpriv->s_EeParameters.i_NbrAoChannel;
218                 s->range_table = this_board->pr_AoRangelist;
219                 s->insn_config = this_board->ao_config;
220                 s->insn_write = this_board->ao_write;
221         } else {
222                 s->type = COMEDI_SUBD_UNUSED;
223         }
224         /*  Allocate and Initialise DI Subdevice Structures */
225         s = &dev->subdevices[2];
226         if (devpriv->s_EeParameters.i_NbrDiChannel) {
227                 s->type = COMEDI_SUBD_DI;
228                 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
229                 s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel;
230                 s->maxdata = 1;
231                 s->len_chanlist =
232                         devpriv->s_EeParameters.i_NbrDiChannel;
233                 s->range_table = &range_digital;
234                 s->io_bits = 0; /* all bits input */
235                 s->insn_config = this_board->di_config;
236                 s->insn_read = this_board->di_read;
237                 s->insn_write = this_board->di_write;
238                 s->insn_bits = this_board->di_bits;
239         } else {
240                 s->type = COMEDI_SUBD_UNUSED;
241         }
242         /*  Allocate and Initialise DO Subdevice Structures */
243         s = &dev->subdevices[3];
244         if (devpriv->s_EeParameters.i_NbrDoChannel) {
245                 s->type = COMEDI_SUBD_DO;
246                 s->subdev_flags =
247                         SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
248                 s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel;
249                 s->maxdata = devpriv->s_EeParameters.i_DoMaxdata;
250                 s->len_chanlist =
251                         devpriv->s_EeParameters.i_NbrDoChannel;
252                 s->range_table = &range_digital;
253                 s->io_bits = 0xf;       /* all bits output */
254
255                 /* insn_config - for digital output memory */
256                 s->insn_config = this_board->do_config;
257                 s->insn_write = this_board->do_write;
258                 s->insn_bits = this_board->do_bits;
259                 s->insn_read = this_board->do_read;
260         } else {
261                 s->type = COMEDI_SUBD_UNUSED;
262         }
263
264         /*  Allocate and Initialise Timer Subdevice Structures */
265         s = &dev->subdevices[4];
266         if (devpriv->s_EeParameters.i_Timer) {
267                 s->type = COMEDI_SUBD_TIMER;
268                 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
269                 s->n_chan = 1;
270                 s->maxdata = 0;
271                 s->len_chanlist = 1;
272                 s->range_table = &range_digital;
273
274                 s->insn_write = this_board->timer_write;
275                 s->insn_read = this_board->timer_read;
276                 s->insn_config = this_board->timer_config;
277                 s->insn_bits = this_board->timer_bits;
278         } else {
279                 s->type = COMEDI_SUBD_UNUSED;
280         }
281
282         /*  Allocate and Initialise TTL */
283         s = &dev->subdevices[5];
284         if (this_board->i_NbrTTLChannel) {
285                 s->type = COMEDI_SUBD_TTLIO;
286                 s->subdev_flags =
287                         SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON;
288                 s->n_chan = this_board->i_NbrTTLChannel;
289                 s->maxdata = 1;
290                 s->io_bits = 0; /* all bits input */
291                 s->len_chanlist = this_board->i_NbrTTLChannel;
292                 s->range_table = &range_digital;
293                 s->insn_config = this_board->ttl_config;
294                 s->insn_bits = this_board->ttl_bits;
295                 s->insn_read = this_board->ttl_read;
296                 s->insn_write = this_board->ttl_write;
297         } else {
298                 s->type = COMEDI_SUBD_UNUSED;
299         }
300
301         /* EEPROM */
302         s = &dev->subdevices[6];
303         if (this_board->i_PCIEeprom) {
304                 s->type = COMEDI_SUBD_MEMORY;
305                 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
306                 s->n_chan = 256;
307                 s->maxdata = 0xffff;
308                 s->insn_read = i_ADDIDATA_InsnReadEeprom;
309         } else {
310                 s->type = COMEDI_SUBD_UNUSED;
311         }
312
313         i_ADDI_Reset(dev);
314         return 0;
315 }
316
317 static void i_ADDI_Detach(struct comedi_device *dev)
318 {
319         struct addi_private *devpriv = dev->private;
320
321         if (devpriv) {
322                 if (dev->iobase)
323                         i_ADDI_Reset(dev);
324                 if (dev->irq)
325                         free_irq(dev->irq, dev);
326                 if (devpriv->dw_AiBase)
327                         iounmap(devpriv->dw_AiBase);
328         }
329         comedi_pci_disable(dev);
330 }