1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#ifndef __KERNEL__
29# define __KERNEL__
30#endif
31
32
33
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
55
56#define ME1400_EXT_IRQ_MAGIC_NUMBER 0x1401
57#define ME1400_EXT_IRQ_NUMBER_CHANNELS 1
58
59
60
61
62
63static 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
103
104
105
106
107
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
136static 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
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
215static 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
243
244
245
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
276static 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
293static 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
301static 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
310static 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
318static 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)
327static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id)
328#else
329static 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
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, __func__, 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
402static 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
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
425me1400_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
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
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
457 spin_lock_init(&subdevice->subdevice_lock);
458 subdevice->clk_src_reg_lock = clk_src_reg_lock;
459
460
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
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
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
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}
518