4 * @brief ME-8100 digital input 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/module.h>
37 #include <linux/slab.h>
38 #include <linux/spinlock.h>
40 #include <linux/types.h>
41 #include <linux/interrupt.h>
42 #include <linux/version.h>
44 #include "medefines.h"
49 #include "meplx_reg.h"
50 #include "me8100_reg.h"
51 #include "me8100_di_reg.h"
52 #include "me8100_di.h"
62 static int me8100_di_io_reset_subdevice(struct me_subdevice
*subdevice
,
63 struct file
*filep
, int flags
)
65 me8100_di_subdevice_t
*instance
;
67 unsigned long cpu_flags
;
69 PDEBUG("executed.\n");
71 instance
= (me8100_di_subdevice_t
*) subdevice
;
74 PERROR("Invalid flag specified.\n");
75 return ME_ERRNO_INVALID_FLAGS
;
80 spin_lock_irqsave(&instance
->subdevice_lock
, cpu_flags
);
81 spin_lock(instance
->ctrl_reg_lock
);
82 ctrl
= inw(instance
->ctrl_reg
);
83 ctrl
&= ~(ME8100_DIO_CTRL_BIT_INTB_1
| ME8100_DIO_CTRL_BIT_INTB_0
);
84 outw(ctrl
, instance
->ctrl_reg
);
85 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance
->reg_base
,
86 instance
->ctrl_reg
- instance
->reg_base
, ctrl
);
87 spin_unlock(instance
->ctrl_reg_lock
);
89 outw(0, instance
->mask_reg
);
90 PDEBUG_REG("mask_reg outw(0x%lX+0x%lX)=0x%x\n", instance
->reg_base
,
91 instance
->mask_reg
- instance
->reg_base
, 0);
92 outw(0, instance
->pattern_reg
);
93 PDEBUG_REG("pattern_reg outw(0x%lX+0x%lX)=0x%x\n", instance
->reg_base
,
94 instance
->pattern_reg
- instance
->reg_base
, 0);
96 instance
->irq_count
= 0;
97 instance
->filtering_flag
= 0;
98 spin_unlock_irqrestore(&instance
->subdevice_lock
, cpu_flags
);
100 outl(PLX_INTCSR_LOCAL_INT1_EN
|
101 PLX_INTCSR_LOCAL_INT1_POL
|
102 PLX_INTCSR_LOCAL_INT2_EN
|
103 PLX_INTCSR_LOCAL_INT2_POL
|
104 PLX_INTCSR_PCI_INT_EN
, instance
->irq_status_reg
);
105 PDEBUG_REG("plx:irq_status_reg outl(0x%lX)=0x%x\n",
106 instance
->irq_status_reg
,
107 PLX_INTCSR_LOCAL_INT1_EN
| PLX_INTCSR_LOCAL_INT1_POL
|
108 PLX_INTCSR_LOCAL_INT2_EN
| PLX_INTCSR_LOCAL_INT2_POL
|
109 PLX_INTCSR_PCI_INT_EN
);
111 wake_up_interruptible_all(&instance
->wait_queue
);
114 return ME_ERRNO_SUCCESS
;
117 static int me8100_di_io_irq_start(me_subdevice_t
* subdevice
,
121 int irq_edge
, int irq_arg
, int flags
)
123 me8100_di_subdevice_t
*instance
;
124 int err
= ME_ERRNO_SUCCESS
;
126 unsigned long cpu_flags
;
128 PDEBUG("executed.\n");
130 instance
= (me8100_di_subdevice_t
*) subdevice
;
132 if (irq_source
== ME_IRQ_SOURCE_DIO_PATTERN
) {
134 ~(ME_IO_IRQ_START_PATTERN_FILTERING
|
135 ME_IO_IRQ_START_DIO_WORD
)) {
136 PERROR("Invalid flag specified.\n");
137 return ME_ERRNO_INVALID_FLAGS
;
140 if (irq_edge
!= ME_IRQ_EDGE_NOT_USED
) {
141 PERROR("Invalid irq edge specified.\n");
142 return ME_ERRNO_INVALID_IRQ_EDGE
;
144 } else if (irq_source
== ME_IRQ_SOURCE_DIO_MASK
) {
146 ~(ME_IO_IRQ_START_EXTENDED_STATUS
|
147 ME_IO_IRQ_START_DIO_WORD
)) {
148 PERROR("Invalid flag specified.\n");
149 return ME_ERRNO_INVALID_FLAGS
;
152 if (irq_edge
!= ME_IRQ_EDGE_ANY
) {
153 PERROR("Invalid irq edge specified.\n");
154 return ME_ERRNO_INVALID_IRQ_EDGE
;
157 if (!(irq_arg
& 0xFFFF)) {
158 PERROR("No mask specified.\n");
159 return ME_ERRNO_INVALID_IRQ_ARG
;
162 PERROR("Invalid irq source specified.\n");
163 return ME_ERRNO_INVALID_IRQ_SOURCE
;
167 PERROR("Invalid channel specified.\n");
168 return ME_ERRNO_INVALID_CHANNEL
;
173 spin_lock_irqsave(&instance
->subdevice_lock
, cpu_flags
);
174 if (irq_source
== ME_IRQ_SOURCE_DIO_PATTERN
) {
175 outw(irq_arg
, instance
->pattern_reg
);
176 instance
->compare_value
= irq_arg
;
177 instance
->filtering_flag
=
178 (flags
& ME_IO_IRQ_START_PATTERN_FILTERING
) ? 1 : 0;
180 if (irq_source
== ME_IRQ_SOURCE_DIO_MASK
) {
181 outw(irq_arg
, instance
->mask_reg
);
184 spin_lock(instance
->ctrl_reg_lock
);
185 ctrl
= inw(instance
->ctrl_reg
);
186 ctrl
|= ME8100_DIO_CTRL_BIT_INTB_0
;
187 if (irq_source
== ME_IRQ_SOURCE_DIO_PATTERN
) {
188 ctrl
&= ~ME8100_DIO_CTRL_BIT_INTB_1
;
191 if (irq_source
== ME_IRQ_SOURCE_DIO_MASK
) {
192 ctrl
|= ME8100_DIO_CTRL_BIT_INTB_1
;
194 outw(ctrl
, instance
->ctrl_reg
);
195 PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance
->reg_base
,
196 instance
->ctrl_reg
- instance
->reg_base
, ctrl
);
197 spin_unlock(instance
->ctrl_reg_lock
);
200 instance
->status_value
= 0;
201 instance
->status_value_edges
= 0;
202 instance
->line_value
= inw(instance
->port_reg
);
203 instance
->status_flag
= flags
& ME_IO_IRQ_START_EXTENDED_STATUS
;
204 spin_unlock_irqrestore(&instance
->subdevice_lock
, cpu_flags
);
211 static int me8100_di_io_irq_wait(me_subdevice_t
* subdevice
,
215 int *value
, int time_out
, int flags
)
217 me8100_di_subdevice_t
*instance
;
218 int err
= ME_ERRNO_SUCCESS
;
220 unsigned long cpu_flags
;
223 PDEBUG("executed.\n");
224 PDEVELOP("PID: %d.\n", current
->pid
);
226 instance
= (me8100_di_subdevice_t
*) subdevice
;
229 ~(ME_IO_IRQ_WAIT_NORMAL_STATUS
| ME_IO_IRQ_WAIT_EXTENDED_STATUS
)) {
230 PERROR("Invalid flag specified.\n");
231 return ME_ERRNO_INVALID_FLAGS
;
235 PERROR("Invalid channel specified.\n");
236 return ME_ERRNO_INVALID_CHANNEL
;
240 PERROR("Invalid time_out specified.\n");
241 return ME_ERRNO_INVALID_TIMEOUT
;
245 t
= (time_out
* HZ
) / 1000;
253 if (instance
->rised
<= 0) {
255 count
= instance
->irq_count
;
258 t
= wait_event_interruptible_timeout(instance
->
266 // t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t);
268 PERROR("Wait on interrupt timed out.\n");
269 err
= ME_ERRNO_TIMEOUT
;
272 wait_event_interruptible(instance
->wait_queue
,
273 ((count
!= instance
->irq_count
)
274 || (instance
->rised
< 0)));
275 // wait_event_interruptible(instance->wait_queue, (instance->rised != 0));
278 if (instance
->rised
< 0) {
279 PERROR("Wait on interrupt aborted by user.\n");
280 err
= ME_ERRNO_CANCELLED
;
284 if (signal_pending(current
)) {
285 PERROR("Wait on interrupt aborted by signal.\n");
286 err
= ME_ERRNO_SIGNAL
;
289 spin_lock_irqsave(&instance
->subdevice_lock
, cpu_flags
);
290 *irq_count
= instance
->irq_count
;
292 if (flags
& ME_IO_IRQ_WAIT_NORMAL_STATUS
) {
293 *value
= instance
->status_value
;
294 } else if (flags
& ME_IO_IRQ_WAIT_EXTENDED_STATUS
) {
295 *value
= instance
->status_value_edges
;
296 } else { // Use default
297 if (!instance
->status_flag
) {
298 *value
= instance
->status_value
;
300 *value
= instance
->status_value_edges
;
305 instance->status_value = 0;
306 instance->status_value_edges = 0;
311 spin_unlock_irqrestore(&instance
->subdevice_lock
, cpu_flags
);
318 static int me8100_di_io_irq_stop(me_subdevice_t
* subdevice
,
319 struct file
*filep
, int channel
, int flags
)
321 me8100_di_subdevice_t
*instance
;
323 unsigned long cpu_flags
;
325 PDEBUG("executed.\n");
327 instance
= (me8100_di_subdevice_t
*) subdevice
;
330 PERROR("Invalid flag specified.\n");
331 return ME_ERRNO_INVALID_FLAGS
;
335 PERROR("Invalid channel specified.\n");
336 return ME_ERRNO_INVALID_CHANNEL
;
341 spin_lock_irqsave(&instance
->subdevice_lock
, cpu_flags
);
342 spin_lock(instance
->ctrl_reg_lock
);
343 ctrl
= inw(instance
->ctrl_reg
);
344 ctrl
&= ~(ME8100_DIO_CTRL_BIT_INTB_1
| ME8100_DIO_CTRL_BIT_INTB_0
);
345 outw(ctrl
, instance
->ctrl_reg
);
346 PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance
->reg_base
,
347 instance
->ctrl_reg
- instance
->reg_base
, ctrl
);
348 spin_unlock(instance
->ctrl_reg_lock
);
349 instance
->rised
= -1;
350 instance
->status_value
= 0;
351 instance
->status_value_edges
= 0;
352 instance
->filtering_flag
= 0;
353 spin_unlock_irqrestore(&instance
->subdevice_lock
, cpu_flags
);
354 wake_up_interruptible_all(&instance
->wait_queue
);
358 return ME_ERRNO_SUCCESS
;
361 static int me8100_di_io_single_config(me_subdevice_t
* subdevice
,
367 int trig_type
, int trig_edge
, int flags
)
369 me8100_di_subdevice_t
*instance
;
370 int err
= ME_ERRNO_SUCCESS
;
372 PDEBUG("executed.\n");
374 instance
= (me8100_di_subdevice_t
*) subdevice
;
378 spin_lock(&instance
->subdevice_lock
);
381 case ME_IO_SINGLE_CONFIG_NO_FLAGS
:
382 case ME_IO_SINGLE_CONFIG_DIO_WORD
:
384 if (single_config
== ME_SINGLE_CONFIG_DIO_INPUT
) {
387 ("Invalid port configuration specified.\n");
388 err
= ME_ERRNO_INVALID_SINGLE_CONFIG
;
391 PERROR("Invalid channel number.\n");
392 err
= ME_ERRNO_INVALID_CHANNEL
;
397 PERROR("Invalid flags specified.\n");
398 err
= ME_ERRNO_INVALID_FLAGS
;
401 spin_unlock(&instance
->subdevice_lock
);
408 static int me8100_di_io_single_read(me_subdevice_t
* subdevice
,
411 int *value
, int time_out
, int flags
)
413 me8100_di_subdevice_t
*instance
;
414 int err
= ME_ERRNO_SUCCESS
;
416 PDEBUG("executed.\n");
418 instance
= (me8100_di_subdevice_t
*) subdevice
;
422 spin_lock(&instance
->subdevice_lock
);
426 case ME_IO_SINGLE_TYPE_DIO_BIT
:
427 if ((channel
>= 0) && (channel
< 16)) {
428 *value
= inw(instance
->port_reg
) & (0x1 << channel
);
430 PERROR("Invalid bit number specified.\n");
431 err
= ME_ERRNO_INVALID_CHANNEL
;
435 case ME_IO_SINGLE_TYPE_DIO_BYTE
:
437 *value
= inw(instance
->port_reg
) & 0xFF;
438 } else if (channel
== 1) {
439 *value
= (inw(instance
->port_reg
) >> 8) & 0xFF;
441 PERROR("Invalid byte number specified.\n");
442 err
= ME_ERRNO_INVALID_CHANNEL
;
446 case ME_IO_SINGLE_NO_FLAGS
:
447 case ME_IO_SINGLE_TYPE_DIO_WORD
:
449 *value
= inw(instance
->port_reg
);
451 PERROR("Invalid word number specified.\n");
452 err
= ME_ERRNO_INVALID_CHANNEL
;
458 PERROR("Invalid flags specified.\n");
459 err
= ME_ERRNO_INVALID_FLAGS
;
462 spin_unlock(&instance
->subdevice_lock
);
469 static int me8100_di_query_number_channels(me_subdevice_t
* subdevice
,
472 PDEBUG("executed.\n");
474 return ME_ERRNO_SUCCESS
;
477 static int me8100_di_query_subdevice_type(me_subdevice_t
* subdevice
,
478 int *type
, int *subtype
)
480 PDEBUG("executed.\n");
482 *subtype
= ME_SUBTYPE_SINGLE
;
483 return ME_ERRNO_SUCCESS
;
486 static int me8100_di_query_subdevice_caps(me_subdevice_t
* subdevice
, int *caps
)
488 PDEBUG("executed.\n");
489 *caps
= ME_CAPS_DIO_BIT_PATTERN_IRQ
| ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY
;
490 return ME_ERRNO_SUCCESS
;
493 static void me8100_di_destructor(struct me_subdevice
*subdevice
)
495 me8100_di_subdevice_t
*instance
;
497 PDEBUG("executed.\n");
499 instance
= (me8100_di_subdevice_t
*) subdevice
;
501 free_irq(instance
->irq
, (void *)instance
);
502 me_subdevice_deinit(&instance
->base
);
506 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
507 static irqreturn_t
me8100_isr(int irq
, void *dev_id
)
509 static irqreturn_t
me8100_isr(int irq
, void *dev_id
, struct pt_regs
*regs
)
512 me8100_di_subdevice_t
*instance
;
516 uint16_t line_value
= 0;
518 uint32_t status_val
= 0;
520 PDEBUG("executed.\n");
522 instance
= (me8100_di_subdevice_t
*) dev_id
;
524 if (irq
!= instance
->irq
) {
525 PERROR("Incorrect interrupt num: %d.\n", irq
);
529 icsr
= inl(instance
->irq_status_reg
);
530 if (instance
->di_idx
== 0) {
533 (PLX_INTCSR_LOCAL_INT1_STATE
| PLX_INTCSR_PCI_INT_EN
|
534 PLX_INTCSR_LOCAL_INT1_EN
)) !=
535 (PLX_INTCSR_LOCAL_INT1_STATE
| PLX_INTCSR_PCI_INT_EN
|
536 PLX_INTCSR_LOCAL_INT1_EN
)) {
538 ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n",
539 jiffies
, __func__
, icsr
);
542 } else if (instance
->di_idx
== 1) {
544 (PLX_INTCSR_LOCAL_INT2_STATE
| PLX_INTCSR_PCI_INT_EN
|
545 PLX_INTCSR_LOCAL_INT2_EN
)) !=
546 (PLX_INTCSR_LOCAL_INT2_STATE
| PLX_INTCSR_PCI_INT_EN
|
547 PLX_INTCSR_LOCAL_INT2_EN
)) {
549 ("%ld Shared interrupt. %s(): idx=1 plx:irq_status_reg=0x%04X\n",
550 jiffies
, __func__
, icsr
);
554 PERROR("%s():Wrong interrupt idx=%d csr=0x%X.\n", __func__
,
555 instance
->di_idx
, icsr
);
559 PDEBUG("me8100_isr():Interrupt from idx=%d occured.\n",
561 spin_lock(&instance
->subdevice_lock
);
562 inw(instance
->irq_reset_reg
);
563 line_value
= inw(instance
->port_reg
);
565 irq_status
= instance
->line_value
^ line_value
;
567 // Make extended information.
568 status_val
|= (0x00FF & (~(uint16_t) instance
->line_value
& line_value
)) << 16; //Raise
569 status_val
|= (0x00FF & ((uint16_t) instance
->line_value
& ~line_value
)); //Fall
571 instance
->line_value
= line_value
;
573 if (instance
->rised
== 0) {
574 instance
->status_value
= irq_status
;
575 instance
->status_value_edges
= status_val
;
577 instance
->status_value
|= irq_status
;
578 instance
->status_value_edges
|= status_val
;
581 if (instance
->filtering_flag
) { // For compare mode only.
582 if (instance
->compare_value
== instance
->line_value
) {
584 instance
->irq_count
++;
588 instance
->irq_count
++;
591 spin_unlock(&instance
->subdevice_lock
);
592 wake_up_interruptible_all(&instance
->wait_queue
);
597 me8100_di_subdevice_t
*me8100_di_constructor(uint32_t me8100_reg_base
,
598 uint32_t plx_reg_base
,
601 spinlock_t
* ctrl_reg_lock
)
603 me8100_di_subdevice_t
*subdevice
;
606 PDEBUG("executed.\n");
608 /* Allocate memory for subdevice instance */
609 subdevice
= kmalloc(sizeof(me8100_di_subdevice_t
), GFP_KERNEL
);
612 PERROR("Cannot get memory for subdevice instance.\n");
616 memset(subdevice
, 0, sizeof(me8100_di_subdevice_t
));
618 /* Initialize subdevice base class */
619 err
= me_subdevice_init(&subdevice
->base
);
622 PERROR("Cannot initialize subdevice base class instance.\n");
626 // Initialize spin locks.
627 spin_lock_init(&subdevice
->subdevice_lock
);
629 subdevice
->ctrl_reg_lock
= ctrl_reg_lock
;
631 /* Save the subdevice index. */
632 subdevice
->di_idx
= di_idx
;
634 /* Initialize wait queue */
635 init_waitqueue_head(&subdevice
->wait_queue
);
637 /* Register interrupt service routine. */
638 subdevice
->irq
= irq
;
639 err
= request_irq(subdevice
->irq
, me8100_isr
,
641 IRQF_DISABLED
| IRQF_SHARED
,
643 SA_INTERRUPT
| SA_SHIRQ
,
645 ME8100_NAME
, (void *)subdevice
);
648 PERROR("Cannot initialize subdevice base class instance.\n");
652 PINFO("Registered irq=%d.\n", subdevice
->irq
);
654 /* Initialize the registers */
655 subdevice
->ctrl_reg
=
656 me8100_reg_base
+ ME8100_CTRL_REG_A
+ di_idx
* ME8100_REG_OFFSET
;
657 subdevice
->port_reg
=
658 me8100_reg_base
+ ME8100_DI_REG_A
+ di_idx
* ME8100_REG_OFFSET
;
659 subdevice
->mask_reg
=
660 me8100_reg_base
+ ME8100_MASK_REG_A
+ di_idx
* ME8100_REG_OFFSET
;
661 subdevice
->pattern_reg
=
662 me8100_reg_base
+ ME8100_PATTERN_REG_A
+ di_idx
* ME8100_REG_OFFSET
;
663 subdevice
->din_int_reg
=
664 me8100_reg_base
+ ME8100_INT_DI_REG_A
+ di_idx
* ME8100_REG_OFFSET
;
665 subdevice
->irq_reset_reg
=
666 me8100_reg_base
+ ME8100_RES_INT_REG_A
+ di_idx
* ME8100_REG_OFFSET
;
667 subdevice
->irq_status_reg
= plx_reg_base
+ PLX_INTCSR
;
668 #ifdef MEDEBUG_DEBUG_REG
669 subdevice
->reg_base
= me8100_reg_base
;
672 /* Overload base class methods. */
673 subdevice
->base
.me_subdevice_io_irq_start
= me8100_di_io_irq_start
;
674 subdevice
->base
.me_subdevice_io_irq_wait
= me8100_di_io_irq_wait
;
675 subdevice
->base
.me_subdevice_io_irq_stop
= me8100_di_io_irq_stop
;
676 subdevice
->base
.me_subdevice_io_reset_subdevice
=
677 me8100_di_io_reset_subdevice
;
678 subdevice
->base
.me_subdevice_io_single_config
=
679 me8100_di_io_single_config
;
680 subdevice
->base
.me_subdevice_io_single_read
= me8100_di_io_single_read
;
681 subdevice
->base
.me_subdevice_query_number_channels
=
682 me8100_di_query_number_channels
;
683 subdevice
->base
.me_subdevice_query_subdevice_type
=
684 me8100_di_query_subdevice_type
;
685 subdevice
->base
.me_subdevice_query_subdevice_caps
=
686 me8100_di_query_subdevice_caps
;
687 subdevice
->base
.me_subdevice_destructor
= me8100_di_destructor
;
689 subdevice
->rised
= 0;
690 subdevice
->irq_count
= 0;