2 * @file me1400_ext_irq.c
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)
11 * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
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.
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.
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.
35 #include <linux/version.h>
36 #include <linux/module.h>
38 #include <linux/slab.h>
39 #include <linux/spinlock.h>
41 #include <linux/types.h>
42 #include <linux/interrupt.h>
44 #include "medefines.h"
45 #include "meinternal.h"
50 #include "me1400_ext_irq.h"
51 #include "me1400_ext_irq_reg.h"
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. */
63 static int me1400_ext_irq_io_irq_start(struct me_subdevice
*subdevice
,
67 int irq_edge
, int irq_arg
, int flags
)
69 me1400_ext_irq_subdevice_t
*instance
;
70 unsigned long cpu_flags
;
73 PDEBUG("executed.\n");
75 instance
= (me1400_ext_irq_subdevice_t
*) subdevice
;
77 if (flags
& ~ME_IO_IRQ_START_DIO_BIT
) {
78 PERROR("Invalid flag specified.\n");
79 return ME_ERRNO_INVALID_FLAGS
;
83 PERROR("Invalid channel.\n");
84 return ME_ERRNO_INVALID_CHANNEL
;
87 if (irq_source
!= ME_IRQ_SOURCE_DIO_LINE
) {
88 PERROR("Invalid irq source.\n");
89 return ME_ERRNO_INVALID_IRQ_SOURCE
;
92 if (irq_edge
!= ME_IRQ_EDGE_RISING
) {
93 PERROR("Invalid irq edge.\n");
94 return ME_ERRNO_INVALID_IRQ_EDGE
;
99 spin_lock_irqsave(&instance
->subdevice_lock
, cpu_flags
);
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);
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",
116 instance
->ctrl_reg
- instance
->reg_base
, tmp
);
120 outb(ME1400AB_EXT_IRQ_IRQ_EN
, instance
->ctrl_reg
);
121 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
123 instance
->ctrl_reg
- instance
->reg_base
,
124 ME1400AB_EXT_IRQ_IRQ_EN
);
127 spin_unlock(instance
->clk_src_reg_lock
);
129 spin_unlock_irqrestore(&instance
->subdevice_lock
, cpu_flags
);
133 return ME_ERRNO_SUCCESS
;
136 static int me1400_ext_irq_io_irq_wait(struct me_subdevice
*subdevice
,
140 int *value
, int time_out
, int flags
)
142 me1400_ext_irq_subdevice_t
*instance
;
143 unsigned long cpu_flags
;
145 int err
= ME_ERRNO_SUCCESS
;
147 PDEBUG("executed.\n");
149 instance
= (me1400_ext_irq_subdevice_t
*) subdevice
;
152 PERROR("Invalid flag specified.\n");
153 return ME_ERRNO_INVALID_FLAGS
;
157 PERROR("Invalid channel.\n");
158 return ME_ERRNO_INVALID_CHANNEL
;
162 PERROR("Invalid time out.\n");
163 return ME_ERRNO_INVALID_TIMEOUT
;
167 /* Convert to ticks */
168 t
= (time_out
* HZ
) / 1000;
176 if (instance
->rised
<= 0) {
179 t
= wait_event_interruptible_timeout(instance
->
185 PERROR("Wait on interrupt timed out.\n");
186 err
= ME_ERRNO_TIMEOUT
;
189 wait_event_interruptible(instance
->wait_queue
,
190 (instance
->rised
!= 0));
193 if (instance
->rised
< 0) {
194 PERROR("Wait on interrupt aborted by user.\n");
195 err
= ME_ERRNO_CANCELLED
;
199 if (signal_pending(current
)) {
200 PERROR("Wait on interrupt aborted by signal.\n");
201 err
= ME_ERRNO_SIGNAL
;
204 spin_lock_irqsave(&instance
->subdevice_lock
, cpu_flags
);
206 *irq_count
= instance
->n
;
208 spin_unlock_irqrestore(&instance
->subdevice_lock
, cpu_flags
);
215 static int me1400_ext_irq_io_irq_stop(struct me_subdevice
*subdevice
,
217 int channel
, int flags
)
219 me1400_ext_irq_subdevice_t
*instance
;
220 unsigned long cpu_flags
;
222 int err
= ME_ERRNO_SUCCESS
;
224 PDEBUG("executed.\n");
226 instance
= (me1400_ext_irq_subdevice_t
*) subdevice
;
229 PERROR("Invalid flag specified.\n");
230 return ME_ERRNO_INVALID_FLAGS
;
234 PERROR("Invalid channel.\n");
235 return ME_ERRNO_INVALID_CHANNEL
;
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);
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",
255 instance
->ctrl_reg
- instance
->reg_base
, tmp
);
260 outb(0x00, instance
->ctrl_reg
);
261 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
263 instance
->ctrl_reg
- instance
->reg_base
, 0x00);
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
);
276 static int me1400_ext_irq_io_reset_subdevice(struct me_subdevice
*subdevice
,
277 struct file
*filep
, int flags
)
279 me1400_ext_irq_subdevice_t
*instance
=
280 (me1400_ext_irq_subdevice_t
*) subdevice
;
282 PDEBUG("executed.\n");
285 PERROR("Invalid flag specified.\n");
286 return ME_ERRNO_INVALID_FLAGS
;
290 return me1400_ext_irq_io_irq_stop(subdevice
, filep
, 0, flags
);
293 static int me1400_ext_irq_query_number_channels(struct me_subdevice
*subdevice
,
296 PDEBUG("executed.\n");
297 *number
= ME1400_EXT_IRQ_NUMBER_CHANNELS
;
298 return ME_ERRNO_SUCCESS
;
301 static int me1400_ext_irq_query_subdevice_type(struct me_subdevice
*subdevice
,
302 int *type
, int *subtype
)
304 PDEBUG("executed.\n");
305 *type
= ME_TYPE_EXT_IRQ
;
306 *subtype
= ME_SUBTYPE_SINGLE
;
307 return ME_ERRNO_SUCCESS
;
310 static int me1400_ext_irq_query_subdevice_caps(struct me_subdevice
*subdevice
,
313 PDEBUG("executed.\n");
314 *caps
= ME_CAPS_EXT_IRQ_EDGE_RISING
;
315 return ME_ERRNO_SUCCESS
;
318 static int me1400_ext_irq_query_subdevice_caps_args(struct me_subdevice
320 int *args
, int count
)
322 PDEBUG("executed.\n");
323 return ME_ERRNO_NOT_SUPPORTED
;
326 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
327 static irqreturn_t
me1400_ext_irq_isr(int irq
, void *dev_id
)
329 static irqreturn_t
me1400_ext_irq_isr(int irq
, void *dev_id
,
330 struct pt_regs
*regs
)
333 me1400_ext_irq_subdevice_t
*instance
;
337 instance
= (me1400_ext_irq_subdevice_t
*) dev_id
;
339 if (irq
!= instance
->irq
) {
340 PERROR("Incorrect interrupt num: %d.\n", irq
);
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)))
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
);
356 inl(instance
->ctrl_reg
);
358 PDEBUG("executed.\n");
363 switch (instance
->device_id
) {
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",
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",
378 instance
->ctrl_reg
- instance
->reg_base
, tmp
);
379 spin_unlock(instance
->clk_src_reg_lock
);
384 outb(0, instance
->ctrl_reg
);
385 PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
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",
391 instance
->ctrl_reg
- instance
->reg_base
,
392 ME1400AB_EXT_IRQ_IRQ_EN
);
396 spin_unlock(&instance
->subdevice_lock
);
397 wake_up_interruptible_all(&instance
->wait_queue
);
402 static void me1400_ext_irq_destructor(struct me_subdevice
*subdevice
)
404 me1400_ext_irq_subdevice_t
*instance
;
407 PDEBUG("executed.\n");
409 instance
= (me1400_ext_irq_subdevice_t
*) subdevice
;
411 // Disable IRQ on PLX
414 plx_intcs_reg
) & (~(PLX_LOCAL_INT1_EN
| PLX_LOCAL_INT1_POL
|
416 outb(tmp
, instance
->plx_intcs_reg
);
417 PDEBUG_REG("ctrl_reg outb(plx:0x%lX)=0x%x\n", instance
->plx_intcs_reg
,
420 free_irq(instance
->irq
, (void *)instance
);
421 me_subdevice_deinit(&instance
->base
);
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
,
432 me1400_ext_irq_subdevice_t
*subdevice
;
436 PDEBUG("executed.\n");
438 /* Allocate memory for subdevice instance */
439 subdevice
= kmalloc(sizeof(me1400_ext_irq_subdevice_t
), GFP_KERNEL
);
442 PERROR("Cannot get memory for 1400_ext_irq instance.\n");
446 memset(subdevice
, 0, sizeof(me1400_ext_irq_subdevice_t
));
448 /* Initialize subdevice base class */
449 err
= me_subdevice_init(&subdevice
->base
);
452 PERROR("Cannot initialize subdevice base class instance.\n");
456 // Initialize spin locks.
457 spin_lock_init(&subdevice
->subdevice_lock
);
458 subdevice
->clk_src_reg_lock
= clk_src_reg_lock
;
460 /* Initialize wait queue */
461 init_waitqueue_head(&subdevice
->wait_queue
);
463 subdevice
->irq
= irq
;
465 err
= request_irq(irq
, me1400_ext_irq_isr
,
467 IRQF_DISABLED
| IRQF_SHARED
,
469 SA_INTERRUPT
| SA_SHIRQ
,
471 ME1400_NAME
, (void *)subdevice
);
474 PERROR("Can't get irq.\n");
475 me_subdevice_deinit(&subdevice
->base
);
479 PINFO("Registered irq=%d.\n", subdevice
->irq
);
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
;
491 plx_intcs_reg
) | (PLX_LOCAL_INT1_EN
| PLX_LOCAL_INT1_POL
|
493 outb(tmp
, subdevice
->plx_intcs_reg
);
494 PDEBUG_REG("ctrl_reg outb(Pplx:0x%lX)=0x%x\n", subdevice
->plx_intcs_reg
,
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
;
513 subdevice
->rised
= 0;