Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 }
508 
  This page was automatically generated by the LXR engine.