Staging: meilhaus: Remove long-deprecated SA_* interrupt macros.
[pandora-kernel.git] / drivers / staging / meilhaus / me4600_ext_irq.c
1 /**
2  * @file me4600_ext_irq.c
3  *
4  * @brief ME-4000 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/interrupt.h>
40 #include <linux/io.h>
41 #include <linux/types.h>
42 #include <linux/version.h>
43
44 #include "medefines.h"
45 #include "meinternal.h"
46 #include "meerror.h"
47
48 #include "medebug.h"
49 #include "meids.h"
50 #include "me4600_reg.h"
51 #include "me4600_ai_reg.h"
52 #include "me4600_ext_irq_reg.h"
53 #include "me4600_ext_irq.h"
54
55 /*
56  * Defines
57  */
58
59 /*
60  * Functions
61  */
62
63 static int me4600_ext_irq_io_irq_start(me_subdevice_t *subdevice,
64                                        struct file *filep,
65                                        int channel,
66                                        int irq_source,
67                                        int irq_edge, int irq_arg, int flags)
68 {
69         me4600_ext_irq_subdevice_t *instance;
70         int err = ME_ERRNO_SUCCESS;
71         unsigned long cpu_flags;
72         uint32_t tmp;
73
74         PDEBUG("executed.\n");
75
76         instance = (me4600_ext_irq_subdevice_t *) subdevice;
77
78         if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
79                 PERROR("Invalid flag specified.\n");
80                 return ME_ERRNO_INVALID_FLAGS;
81         }
82
83         if ((irq_edge != ME_IRQ_EDGE_RISING)
84             && (irq_edge != ME_IRQ_EDGE_FALLING)
85             && (irq_edge != ME_IRQ_EDGE_ANY)
86             ) {
87                 PERROR("Invalid irq edge specified.\n");
88                 return ME_ERRNO_INVALID_IRQ_EDGE;
89         }
90
91         if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
92                 PERROR("Invalid irq source specified.\n");
93                 return ME_ERRNO_INVALID_IRQ_SOURCE;
94         }
95
96         if (channel) {
97                 PERROR("Invalid channel specified.\n");
98                 return ME_ERRNO_INVALID_CHANNEL;
99         }
100
101         ME_SUBDEVICE_ENTER;
102
103         spin_lock(&instance->subdevice_lock);
104         tmp = 0x0;              //inl(instance->ext_irq_config_reg);
105
106         if (irq_edge == ME_IRQ_EDGE_RISING) {
107                 //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK;
108                 //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_RISING;
109         } else if (irq_edge == ME_IRQ_EDGE_FALLING) {
110                 //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK;
111                 //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_FALLING;
112                 tmp = ME4600_EXT_IRQ_CONFIG_MASK_FALLING;
113         } else if (irq_edge == ME_IRQ_EDGE_ANY) {
114                 //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK;
115                 //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_ANY;
116                 tmp = ME4600_EXT_IRQ_CONFIG_MASK_ANY;
117         }
118
119         outl(tmp, instance->ext_irq_config_reg);
120         PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n",
121                    instance->reg_base,
122                    instance->ext_irq_config_reg - instance->reg_base, tmp);
123
124         spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
125         tmp = inl(instance->ctrl_reg);
126         tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
127         tmp |= ME4600_AI_CTRL_BIT_EX_IRQ;
128         outl(tmp, instance->ctrl_reg);
129         spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
130         instance->rised = 0;
131         spin_unlock(&instance->subdevice_lock);
132
133         ME_SUBDEVICE_EXIT;
134
135         return err;
136 }
137
138 static int me4600_ext_irq_io_irq_wait(me_subdevice_t *subdevice,
139                                       struct file *filep,
140                                       int channel,
141                                       int *irq_count,
142                                       int *value, int time_out, int flags)
143 {
144         me4600_ext_irq_subdevice_t *instance;
145         int err = ME_ERRNO_SUCCESS;
146         long t = 0;
147         unsigned long cpu_flags;
148
149         PDEBUG("executed.\n");
150
151         instance = (me4600_ext_irq_subdevice_t *) subdevice;
152
153         if (flags) {
154                 PERROR("Invalid flag specified.\n");
155                 return ME_ERRNO_INVALID_FLAGS;
156         }
157
158         if (channel) {
159                 PERROR("Invalid channel specified.\n");
160                 return ME_ERRNO_INVALID_CHANNEL;
161         }
162
163         if (time_out < 0) {
164                 PERROR("Invalid time_out specified.\n");
165                 return ME_ERRNO_INVALID_TIMEOUT;
166         }
167
168         if (time_out) {
169                 t = (time_out * HZ) / 1000;
170
171                 if (t == 0)
172                         t = 1;
173         }
174
175         ME_SUBDEVICE_ENTER;
176
177         if (instance->rised <= 0) {
178                 instance->rised = 0;
179                 if (time_out) {
180                         t = wait_event_interruptible_timeout(instance->
181                                                              wait_queue,
182                                                              (instance->rised !=
183                                                               0), t);
184
185                         if (t == 0) {
186                                 PERROR
187                                     ("Wait on external interrupt timed out.\n");
188                                 err = ME_ERRNO_TIMEOUT;
189                         }
190                 } else {
191                         wait_event_interruptible(instance->wait_queue,
192                                                  (instance->rised != 0));
193                 }
194
195                 if (instance->rised < 0) {
196                         PERROR("Wait on interrupt aborted by user.\n");
197                         err = ME_ERRNO_CANCELLED;
198                 }
199         }
200
201         if (signal_pending(current)) {
202                 PERROR("Wait on external interrupt aborted by signal.\n");
203                 err = ME_ERRNO_SIGNAL;
204         }
205
206         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
207         instance->rised = 0;
208         *irq_count = instance->count;
209         *value = instance->value;
210         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
211
212         ME_SUBDEVICE_EXIT;
213
214         return err;
215 }
216
217 static int me4600_ext_irq_io_irq_stop(me_subdevice_t *subdevice,
218                                       struct file *filep,
219                                       int channel, int flags)
220 {
221         me4600_ext_irq_subdevice_t *instance;
222         int err = ME_ERRNO_SUCCESS;
223         unsigned long cpu_flags;
224         uint32_t tmp;
225
226         PDEBUG("executed.\n");
227
228         instance = (me4600_ext_irq_subdevice_t *) subdevice;
229
230         if (flags) {
231                 PERROR("Invalid flag specified.\n");
232                 return ME_ERRNO_INVALID_FLAGS;
233         }
234
235         if (channel) {
236                 PERROR("Invalid channel specified.\n");
237                 return ME_ERRNO_INVALID_CHANNEL;
238         }
239
240         ME_SUBDEVICE_ENTER;
241
242         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
243         spin_lock(instance->ctrl_reg_lock);
244         tmp = inl(instance->ctrl_reg);
245         tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
246         outl(tmp, instance->ctrl_reg);
247         PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
248                    instance->ctrl_reg - instance->reg_base, tmp);
249         spin_unlock(instance->ctrl_reg_lock);
250         instance->rised = -1;
251         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
252         wake_up_interruptible_all(&instance->wait_queue);
253
254         ME_SUBDEVICE_EXIT;
255
256         return err;
257 }
258
259 static int me4600_ext_irq_io_reset_subdevice(me_subdevice_t *subdevice,
260                                              struct file *filep, int flags)
261 {
262         me4600_ext_irq_subdevice_t *instance;
263         unsigned long cpu_flags;
264         uint32_t tmp;
265
266         PDEBUG("executed.\n");
267
268         instance = (me4600_ext_irq_subdevice_t *) subdevice;
269
270         if (flags) {
271                 PERROR("Invalid flag specified.\n");
272                 return ME_ERRNO_INVALID_FLAGS;
273         }
274
275         ME_SUBDEVICE_ENTER;
276
277         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
278         spin_lock(instance->ctrl_reg_lock);
279         tmp = inl(instance->ctrl_reg);
280         tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
281         outl(tmp, instance->ctrl_reg);
282         PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
283                    instance->ctrl_reg - instance->reg_base, tmp);
284         spin_unlock(instance->ctrl_reg_lock);
285         instance->rised = -1;
286         instance->count = 0;
287         outl(ME4600_EXT_IRQ_CONFIG_MASK_ANY, instance->ext_irq_config_reg);
288         PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n",
289                    instance->reg_base,
290                    instance->ext_irq_config_reg - instance->reg_base,
291                    ME4600_EXT_IRQ_CONFIG_MASK_ANY);
292         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
293         wake_up_interruptible_all(&instance->wait_queue);
294
295         ME_SUBDEVICE_EXIT;
296
297         return ME_ERRNO_SUCCESS;
298 }
299
300 static void me4600_ext_irq_destructor(struct me_subdevice *subdevice)
301 {
302         me4600_ext_irq_subdevice_t *instance;
303
304         PDEBUG("executed.\n");
305         instance = (me4600_ext_irq_subdevice_t *) subdevice;
306         me_subdevice_deinit(&instance->base);
307         free_irq(instance->irq, instance);
308         kfree(instance);
309 }
310
311 static int me4600_ext_irq_query_number_channels(me_subdevice_t *subdevice,
312                                                 int *number)
313 {
314         PDEBUG("executed.\n");
315         *number = 1;
316         return ME_ERRNO_SUCCESS;
317 }
318
319 static int me4600_ext_irq_query_subdevice_type(me_subdevice_t *subdevice,
320                                                int *type, int *subtype)
321 {
322         PDEBUG("executed.\n");
323         *type = ME_TYPE_EXT_IRQ;
324         *subtype = ME_SUBTYPE_SINGLE;
325         return ME_ERRNO_SUCCESS;
326 }
327
328 static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t *subdevice,
329                                                int *caps)
330 {
331         PDEBUG("executed.\n");
332         *caps =
333             ME_CAPS_EXT_IRQ_EDGE_RISING | ME_CAPS_EXT_IRQ_EDGE_FALLING |
334             ME_CAPS_EXT_IRQ_EDGE_ANY;
335         return ME_ERRNO_SUCCESS;
336 }
337
338 static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id)
339 {
340         me4600_ext_irq_subdevice_t *instance;
341         uint32_t ctrl;
342         uint32_t irq_status;
343
344         instance = (me4600_ext_irq_subdevice_t *) dev_id;
345
346         if (irq != instance->irq) {
347                 PERROR("Incorrect interrupt num: %d.\n", irq);
348                 return IRQ_NONE;
349         }
350
351         irq_status = inl(instance->irq_status_reg);
352         if (!(irq_status & ME4600_IRQ_STATUS_BIT_EX)) {
353                 PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n",
354                       jiffies, __func__, irq_status);
355                 return IRQ_NONE;
356         }
357
358         PDEBUG("executed.\n");
359
360         spin_lock(&instance->subdevice_lock);
361         instance->rised = 1;
362         instance->value = inl(instance->ext_irq_value_reg);
363         instance->count++;
364
365         spin_lock(instance->ctrl_reg_lock);
366         ctrl = inl(instance->ctrl_reg);
367         ctrl |= ME4600_AI_CTRL_BIT_EX_IRQ_RESET;
368         outl(ctrl, instance->ctrl_reg);
369         PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
370                    instance->ctrl_reg - instance->reg_base, ctrl);
371         ctrl &= ~ME4600_AI_CTRL_BIT_EX_IRQ_RESET;
372         outl(ctrl, instance->ctrl_reg);
373         PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
374                    instance->ctrl_reg - instance->reg_base, ctrl);
375         spin_unlock(instance->ctrl_reg_lock);
376
377         spin_unlock(&instance->subdevice_lock);
378         wake_up_interruptible_all(&instance->wait_queue);
379
380         return IRQ_HANDLED;
381 }
382
383 me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base,
384                                                        int irq,
385                                                        spinlock_t *
386                                                        ctrl_reg_lock)
387 {
388         me4600_ext_irq_subdevice_t *subdevice;
389         int err;
390
391         PDEBUG("executed.\n");
392
393         /* Allocate memory for subdevice instance */
394         subdevice = kmalloc(sizeof(me4600_ext_irq_subdevice_t), GFP_KERNEL);
395
396         if (!subdevice) {
397                 PERROR("Cannot get memory for subdevice instance.\n");
398                 return NULL;
399         }
400
401         memset(subdevice, 0, sizeof(me4600_ext_irq_subdevice_t));
402
403         /* Initialize subdevice base class */
404         err = me_subdevice_init(&subdevice->base);
405
406         if (err) {
407                 PERROR("Cannot initialize subdevice base class instance.\n");
408                 kfree(subdevice);
409                 return NULL;
410         }
411         // Initialize spin locks.
412         spin_lock_init(&subdevice->subdevice_lock);
413
414         subdevice->ctrl_reg_lock = ctrl_reg_lock;
415
416         /* Initialize wait queue */
417         init_waitqueue_head(&subdevice->wait_queue);
418
419         /* Register interrupt */
420         subdevice->irq = irq;
421
422         if (request_irq(subdevice->irq, me4600_ext_irq_isr,
423                         IRQF_DISABLED | IRQF_SHARED,
424                         ME4600_NAME, subdevice)) {
425                 PERROR("Cannot register interrupt.\n");
426                 kfree(subdevice);
427                 return NULL;
428         }
429         PINFO("Registered irq=%d.\n", subdevice->irq);
430
431         /* Initialize registers */
432         subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG;
433         subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG;
434         subdevice->ext_irq_config_reg = reg_base + ME4600_EXT_IRQ_CONFIG_REG;
435         subdevice->ext_irq_value_reg = reg_base + ME4600_EXT_IRQ_VALUE_REG;
436 #ifdef MEDEBUG_DEBUG_REG
437         subdevice->reg_base = reg_base;
438 #endif
439
440         /* Override base class methods. */
441         subdevice->base.me_subdevice_destructor = me4600_ext_irq_destructor;
442         subdevice->base.me_subdevice_io_reset_subdevice =
443             me4600_ext_irq_io_reset_subdevice;
444         subdevice->base.me_subdevice_io_irq_start = me4600_ext_irq_io_irq_start;
445         subdevice->base.me_subdevice_io_irq_wait = me4600_ext_irq_io_irq_wait;
446         subdevice->base.me_subdevice_io_irq_stop = me4600_ext_irq_io_irq_stop;
447         subdevice->base.me_subdevice_query_number_channels =
448             me4600_ext_irq_query_number_channels;
449         subdevice->base.me_subdevice_query_subdevice_type =
450             me4600_ext_irq_query_subdevice_type;
451         subdevice->base.me_subdevice_query_subdevice_caps =
452             me4600_ext_irq_query_subdevice_caps;
453
454         subdevice->rised = 0;
455         subdevice->count = 0;
456
457         return subdevice;
458 }