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