Merge branch 'for-2.6.31' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / meilhaus / me1400_ext_irq.c
1 /**
2  * @file me1400_ext_irq.c
3  *
4  * @brief ME-1400 external interrupt subdevice instance.
5  * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
6  * @author Guenter Gebhardt
7  * @author Krzysztof Gantzke    (k.gantzke@meilhaus.de)
8  */
9
10 /*
11  * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
12  *
13  * This file is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27
28 #ifndef __KERNEL__
29 #  define __KERNEL__
30 #endif
31
32 /*
33  * Includes
34  */
35 #include <linux/module.h>
36
37 #include <linux/slab.h>
38 #include <linux/spinlock.h>
39 #include <linux/io.h>
40 #include <linux/types.h>
41 #include <linux/interrupt.h>
42
43 #include "medefines.h"
44 #include "meinternal.h"
45 #include "meerror.h"
46 #include "medebug.h"
47 #include "meids.h"
48
49 #include "me1400_ext_irq.h"
50 #include "me1400_ext_irq_reg.h"
51
52 /*
53  * Defines
54  */
55 #define ME1400_EXT_IRQ_MAGIC_NUMBER     0x1401  /**< The magic number of the class structure. */
56 #define ME1400_EXT_IRQ_NUMBER_CHANNELS 1        /**< One channel per counter. */
57
58 /*
59  * Functions
60  */
61
62 static int me1400_ext_irq_io_irq_start(struct me_subdevice *subdevice,
63                                        struct file *filep,
64                                        int channel,
65                                        int irq_source,
66                                        int irq_edge, int irq_arg, int flags)
67 {
68         me1400_ext_irq_subdevice_t *instance;
69         unsigned long cpu_flags;
70         uint8_t tmp;
71
72         PDEBUG("executed.\n");
73
74         instance = (me1400_ext_irq_subdevice_t *) subdevice;
75
76         if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
77                 PERROR("Invalid flag specified.\n");
78                 return ME_ERRNO_INVALID_FLAGS;
79         }
80
81         if (channel) {
82                 PERROR("Invalid channel.\n");
83                 return ME_ERRNO_INVALID_CHANNEL;
84         }
85
86         if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
87                 PERROR("Invalid irq source.\n");
88                 return ME_ERRNO_INVALID_IRQ_SOURCE;
89         }
90
91         if (irq_edge != ME_IRQ_EDGE_RISING) {
92                 PERROR("Invalid irq edge.\n");
93                 return ME_ERRNO_INVALID_IRQ_EDGE;
94         }
95
96         ME_SUBDEVICE_ENTER;
97
98         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
99
100         spin_lock(instance->clk_src_reg_lock);
101 //                      // Enable IRQ on PLX
102 //                      tmp = inb(instance->plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN);
103 //                      outb(tmp, instance->plx_intcs_reg);
104 //                      PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp);
105
106         // Enable IRQ
107         switch (instance->device_id) {
108         case PCI_DEVICE_ID_MEILHAUS_ME140C:
109         case PCI_DEVICE_ID_MEILHAUS_ME140D:
110                 tmp = inb(instance->ctrl_reg);
111                 tmp |= ME1400CD_EXT_IRQ_CLK_EN;
112                 outb(tmp, instance->ctrl_reg);
113                 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
114                            instance->reg_base,
115                            instance->ctrl_reg - instance->reg_base, tmp);
116                 break;
117
118         default:
119                 outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg);
120                 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
121                            instance->reg_base,
122                            instance->ctrl_reg - instance->reg_base,
123                            ME1400AB_EXT_IRQ_IRQ_EN);
124                 break;
125         }
126         spin_unlock(instance->clk_src_reg_lock);
127         instance->rised = 0;
128         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
129
130         ME_SUBDEVICE_EXIT;
131
132         return ME_ERRNO_SUCCESS;
133 }
134
135 static int me1400_ext_irq_io_irq_wait(struct me_subdevice *subdevice,
136                                       struct file *filep,
137                                       int channel,
138                                       int *irq_count,
139                                       int *value, int time_out, int flags)
140 {
141         me1400_ext_irq_subdevice_t *instance;
142         unsigned long cpu_flags;
143         long t = 0;
144         int err = ME_ERRNO_SUCCESS;
145
146         PDEBUG("executed.\n");
147
148         instance = (me1400_ext_irq_subdevice_t *) subdevice;
149
150         if (flags) {
151                 PERROR("Invalid flag specified.\n");
152                 return ME_ERRNO_INVALID_FLAGS;
153         }
154
155         if (channel) {
156                 PERROR("Invalid channel.\n");
157                 return ME_ERRNO_INVALID_CHANNEL;
158         }
159
160         if (time_out < 0) {
161                 PERROR("Invalid time out.\n");
162                 return ME_ERRNO_INVALID_TIMEOUT;
163         }
164
165         if (time_out) {
166                 /* Convert to ticks */
167                 t = (time_out * HZ) / 1000;
168
169                 if (t == 0)
170                         t = 1;
171         }
172
173         ME_SUBDEVICE_ENTER;
174
175         if (instance->rised <= 0) {
176                 instance->rised = 0;
177                 if (time_out) {
178                         t = wait_event_interruptible_timeout(instance->
179                                                              wait_queue,
180                                                              (instance->rised !=
181                                                               0), t);
182
183                         if (t == 0) {
184                                 PERROR("Wait on interrupt timed out.\n");
185                                 err = ME_ERRNO_TIMEOUT;
186                         }
187                 } else {
188                         wait_event_interruptible(instance->wait_queue,
189                                                  (instance->rised != 0));
190                 }
191
192                 if (instance->rised < 0) {
193                         PERROR("Wait on interrupt aborted by user.\n");
194                         err = ME_ERRNO_CANCELLED;
195                 }
196         }
197
198         if (signal_pending(current)) {
199                 PERROR("Wait on interrupt aborted by signal.\n");
200                 err = ME_ERRNO_SIGNAL;
201         }
202
203         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
204         instance->rised = 0;
205         *irq_count = instance->n;
206         *value = 1;
207         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
208
209         ME_SUBDEVICE_EXIT;
210
211         return err;
212 }
213
214 static int me1400_ext_irq_io_irq_stop(struct me_subdevice *subdevice,
215                                       struct file *filep,
216                                       int channel, int flags)
217 {
218         me1400_ext_irq_subdevice_t *instance;
219         unsigned long cpu_flags;
220         uint8_t tmp;
221         int err = ME_ERRNO_SUCCESS;
222
223         PDEBUG("executed.\n");
224
225         instance = (me1400_ext_irq_subdevice_t *) subdevice;
226
227         if (flags) {
228                 PERROR("Invalid flag specified.\n");
229                 return ME_ERRNO_INVALID_FLAGS;
230         }
231
232         if (channel) {
233                 PERROR("Invalid channel.\n");
234                 return ME_ERRNO_INVALID_CHANNEL;
235         }
236
237         ME_SUBDEVICE_ENTER;
238
239         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
240         spin_lock(instance->clk_src_reg_lock);
241 //                      // Disable IRQ on PLX
242 //                      tmp = inb(instance->plx_intcs_reg) & ( ~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN));
243 //                      outb(tmp, instance->plx_intcs_reg);
244 //                      PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp);
245
246         switch (instance->device_id) {
247         case PCI_DEVICE_ID_MEILHAUS_ME140C:
248         case PCI_DEVICE_ID_MEILHAUS_ME140D:
249                 tmp = inb(instance->ctrl_reg);
250                 tmp &= ~ME1400CD_EXT_IRQ_CLK_EN;
251                 outb(tmp, instance->ctrl_reg);
252                 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
253                            instance->reg_base,
254                            instance->ctrl_reg - instance->reg_base, tmp);
255
256                 break;
257
258         default:
259                 outb(0x00, instance->ctrl_reg);
260                 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
261                            instance->reg_base,
262                            instance->ctrl_reg - instance->reg_base, 0x00);
263                 break;
264         }
265         spin_unlock(instance->clk_src_reg_lock);
266         instance->rised = -1;
267         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
268         wake_up_interruptible_all(&instance->wait_queue);
269
270         ME_SUBDEVICE_EXIT;
271
272         return err;
273 }
274
275 static int me1400_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice,
276                                              struct file *filep, int flags)
277 {
278         me1400_ext_irq_subdevice_t *instance =
279             (me1400_ext_irq_subdevice_t *) subdevice;
280
281         PDEBUG("executed.\n");
282
283         if (flags) {
284                 PERROR("Invalid flag specified.\n");
285                 return ME_ERRNO_INVALID_FLAGS;
286         }
287
288         instance->n = 0;
289         return me1400_ext_irq_io_irq_stop(subdevice, filep, 0, flags);
290 }
291
292 static int me1400_ext_irq_query_number_channels(struct me_subdevice *subdevice,
293                                                 int *number)
294 {
295         PDEBUG("executed.\n");
296         *number = ME1400_EXT_IRQ_NUMBER_CHANNELS;
297         return ME_ERRNO_SUCCESS;
298 }
299
300 static int me1400_ext_irq_query_subdevice_type(struct me_subdevice *subdevice,
301                                                int *type, int *subtype)
302 {
303         PDEBUG("executed.\n");
304         *type = ME_TYPE_EXT_IRQ;
305         *subtype = ME_SUBTYPE_SINGLE;
306         return ME_ERRNO_SUCCESS;
307 }
308
309 static int me1400_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice,
310                                                int *caps)
311 {
312         PDEBUG("executed.\n");
313         *caps = ME_CAPS_EXT_IRQ_EDGE_RISING;
314         return ME_ERRNO_SUCCESS;
315 }
316
317 static int me1400_ext_irq_query_subdevice_caps_args(struct me_subdevice
318                                                     *subdevice, int cap,
319                                                     int *args, int count)
320 {
321         PDEBUG("executed.\n");
322         return ME_ERRNO_NOT_SUPPORTED;
323 }
324
325 static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id)
326 {
327         me1400_ext_irq_subdevice_t *instance;
328         uint32_t status;
329         uint8_t tmp;
330
331         instance = (me1400_ext_irq_subdevice_t *) dev_id;
332
333         if (irq != instance->irq) {
334                 PERROR("Incorrect interrupt num: %d.\n", irq);
335                 return IRQ_NONE;
336         }
337
338         spin_lock(&instance->subdevice_lock);
339         status = inl(instance->plx_intcs_reg);
340 //              if (!((status & PLX_LOCAL_INT1_STATE) && (status & PLX_LOCAL_INT1_EN) && (status & PLX_PCI_INT_EN)))
341         if ((status &
342              (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) !=
343             (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) {
344                 spin_unlock(&instance->subdevice_lock);
345                 PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n",
346                       jiffies, __func__, status);
347                 return IRQ_NONE;
348         }
349
350         inl(instance->ctrl_reg);
351
352         PDEBUG("executed.\n");
353
354         instance->n++;
355         instance->rised = 1;
356
357         switch (instance->device_id) {
358
359         case PCI_DEVICE_ID_MEILHAUS_ME140C:
360         case PCI_DEVICE_ID_MEILHAUS_ME140D:
361                 spin_lock(instance->clk_src_reg_lock);
362                 tmp = inb(instance->ctrl_reg);
363                 tmp &= ~ME1400CD_EXT_IRQ_CLK_EN;
364                 outb(tmp, instance->ctrl_reg);
365                 PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
366                            instance->reg_base,
367                            instance->ctrl_reg - instance->reg_base, tmp);
368                 tmp |= ME1400CD_EXT_IRQ_CLK_EN;
369                 outb(tmp, instance->ctrl_reg);
370                 PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
371                            instance->reg_base,
372                            instance->ctrl_reg - instance->reg_base, tmp);
373                 spin_unlock(instance->clk_src_reg_lock);
374
375                 break;
376
377         default:
378                 outb(0, instance->ctrl_reg);
379                 PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
380                            instance->reg_base,
381                            instance->ctrl_reg - instance->reg_base, 0);
382                 outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg);
383                 PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
384                            instance->reg_base,
385                            instance->ctrl_reg - instance->reg_base,
386                            ME1400AB_EXT_IRQ_IRQ_EN);
387                 break;
388         }
389
390         spin_unlock(&instance->subdevice_lock);
391         wake_up_interruptible_all(&instance->wait_queue);
392
393         return IRQ_HANDLED;
394 }
395
396 static void me1400_ext_irq_destructor(struct me_subdevice *subdevice)
397 {
398         me1400_ext_irq_subdevice_t *instance;
399         uint8_t tmp;
400
401         PDEBUG("executed.\n");
402
403         instance = (me1400_ext_irq_subdevice_t *) subdevice;
404
405         // Disable IRQ on PLX
406         tmp =
407             inb(instance->
408                 plx_intcs_reg) & (~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL |
409                                     PLX_PCI_INT_EN));
410         outb(tmp, instance->plx_intcs_reg);
411         PDEBUG_REG("ctrl_reg outb(plx:0x%lX)=0x%x\n", instance->plx_intcs_reg,
412                    tmp);
413
414         free_irq(instance->irq, (void *)instance);
415         me_subdevice_deinit(&instance->base);
416         kfree(instance);
417 }
418
419 me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id,
420                                                        uint32_t plx_reg_base,
421                                                        uint32_t me1400_reg_base,
422                                                        spinlock_t *
423                                                        clk_src_reg_lock,
424                                                        int irq)
425 {
426         me1400_ext_irq_subdevice_t *subdevice;
427         int err;
428         uint8_t tmp;
429
430         PDEBUG("executed.\n");
431
432         /* Allocate memory for subdevice instance */
433         subdevice = kmalloc(sizeof(me1400_ext_irq_subdevice_t), GFP_KERNEL);
434
435         if (!subdevice) {
436                 PERROR("Cannot get memory for 1400_ext_irq instance.\n");
437                 return NULL;
438         }
439
440         memset(subdevice, 0, sizeof(me1400_ext_irq_subdevice_t));
441
442         /* Initialize subdevice base class */
443         err = me_subdevice_init(&subdevice->base);
444
445         if (err) {
446                 PERROR("Cannot initialize subdevice base class instance.\n");
447                 kfree(subdevice);
448                 return NULL;
449         }
450         // Initialize spin locks.
451         spin_lock_init(&subdevice->subdevice_lock);
452         subdevice->clk_src_reg_lock = clk_src_reg_lock;
453
454         /* Initialize wait queue */
455         init_waitqueue_head(&subdevice->wait_queue);
456
457         subdevice->irq = irq;
458
459         err = request_irq(irq, me1400_ext_irq_isr,
460                           IRQF_DISABLED | IRQF_SHARED,
461                           ME1400_NAME, (void *)subdevice);
462
463         if (err) {
464                 PERROR("Can't get irq.\n");
465                 me_subdevice_deinit(&subdevice->base);
466                 kfree(subdevice);
467                 return NULL;
468         }
469         PINFO("Registered irq=%d.\n", subdevice->irq);
470
471         /* Initialize registers */
472         subdevice->plx_intcs_reg = plx_reg_base + PLX_INTCSR_REG;
473         subdevice->ctrl_reg = me1400_reg_base + ME1400AB_EXT_IRQ_CTRL_REG;
474 #ifdef MEDEBUG_DEBUG_REG
475         subdevice->reg_base = me1400_reg_base;
476 #endif
477
478         // Enable IRQ on PLX
479         tmp =
480             inb(subdevice->
481                 plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL |
482                                   PLX_PCI_INT_EN);
483         outb(tmp, subdevice->plx_intcs_reg);
484         PDEBUG_REG("ctrl_reg outb(Pplx:0x%lX)=0x%x\n", subdevice->plx_intcs_reg,
485                    tmp);
486
487         /* Initialize the subdevice methods */
488         subdevice->base.me_subdevice_io_irq_start = me1400_ext_irq_io_irq_start;
489         subdevice->base.me_subdevice_io_irq_wait = me1400_ext_irq_io_irq_wait;
490         subdevice->base.me_subdevice_io_irq_stop = me1400_ext_irq_io_irq_stop;
491         subdevice->base.me_subdevice_io_reset_subdevice =
492             me1400_ext_irq_io_reset_subdevice;
493         subdevice->base.me_subdevice_query_number_channels =
494             me1400_ext_irq_query_number_channels;
495         subdevice->base.me_subdevice_query_subdevice_type =
496             me1400_ext_irq_query_subdevice_type;
497         subdevice->base.me_subdevice_query_subdevice_caps =
498             me1400_ext_irq_query_subdevice_caps;
499         subdevice->base.me_subdevice_query_subdevice_caps_args =
500             me1400_ext_irq_query_subdevice_caps_args;
501         subdevice->base.me_subdevice_destructor = me1400_ext_irq_destructor;
502
503         subdevice->rised = 0;
504         subdevice->n = 0;
505
506         return subdevice;
507 }