OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [kernel/] [irq/] [autoprobe.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/kernel/irq/autoprobe.c
3
 *
4
 * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
5
 *
6
 * This file contains the interrupt probing code and driver APIs.
7
 */
8
 
9
#include <linux/irq.h>
10
#include <linux/module.h>
11
#include <linux/interrupt.h>
12
#include <linux/delay.h>
13
 
14
#include "internals.h"
15
 
16
/*
17
 * Autodetection depends on the fact that any interrupt that
18
 * comes in on to an unassigned handler will get stuck with
19
 * "IRQ_WAITING" cleared and the interrupt disabled.
20
 */
21
static DEFINE_MUTEX(probing_active);
22
 
23
/**
24
 *      probe_irq_on    - begin an interrupt autodetect
25
 *
26
 *      Commence probing for an interrupt. The interrupts are scanned
27
 *      and a mask of potential interrupt lines is returned.
28
 *
29
 */
30
unsigned long probe_irq_on(void)
31
{
32
        struct irq_desc *desc;
33
        unsigned long mask;
34
        unsigned int i;
35
 
36
        mutex_lock(&probing_active);
37
        /*
38
         * something may have generated an irq long ago and we want to
39
         * flush such a longstanding irq before considering it as spurious.
40
         */
41
        for (i = NR_IRQS-1; i > 0; i--) {
42
                desc = irq_desc + i;
43
 
44
                spin_lock_irq(&desc->lock);
45
                if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
46
                        /*
47
                         * An old-style architecture might still have
48
                         * the handle_bad_irq handler there:
49
                         */
50
                        compat_irq_chip_set_default_handler(desc);
51
 
52
                        /*
53
                         * Some chips need to know about probing in
54
                         * progress:
55
                         */
56
                        if (desc->chip->set_type)
57
                                desc->chip->set_type(i, IRQ_TYPE_PROBE);
58
                        desc->chip->startup(i);
59
                }
60
                spin_unlock_irq(&desc->lock);
61
        }
62
 
63
        /* Wait for longstanding interrupts to trigger. */
64
        msleep(20);
65
 
66
        /*
67
         * enable any unassigned irqs
68
         * (we must startup again here because if a longstanding irq
69
         * happened in the previous stage, it may have masked itself)
70
         */
71
        for (i = NR_IRQS-1; i > 0; i--) {
72
                desc = irq_desc + i;
73
 
74
                spin_lock_irq(&desc->lock);
75
                if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
76
                        desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
77
                        if (desc->chip->startup(i))
78
                                desc->status |= IRQ_PENDING;
79
                }
80
                spin_unlock_irq(&desc->lock);
81
        }
82
 
83
        /*
84
         * Wait for spurious interrupts to trigger
85
         */
86
        msleep(100);
87
 
88
        /*
89
         * Now filter out any obviously spurious interrupts
90
         */
91
        mask = 0;
92
        for (i = 0; i < NR_IRQS; i++) {
93
                unsigned int status;
94
 
95
                desc = irq_desc + i;
96
                spin_lock_irq(&desc->lock);
97
                status = desc->status;
98
 
99
                if (status & IRQ_AUTODETECT) {
100
                        /* It triggered already - consider it spurious. */
101
                        if (!(status & IRQ_WAITING)) {
102
                                desc->status = status & ~IRQ_AUTODETECT;
103
                                desc->chip->shutdown(i);
104
                        } else
105
                                if (i < 32)
106
                                        mask |= 1 << i;
107
                }
108
                spin_unlock_irq(&desc->lock);
109
        }
110
 
111
        return mask;
112
}
113
EXPORT_SYMBOL(probe_irq_on);
114
 
115
/**
116
 *      probe_irq_mask - scan a bitmap of interrupt lines
117
 *      @val:   mask of interrupts to consider
118
 *
119
 *      Scan the interrupt lines and return a bitmap of active
120
 *      autodetect interrupts. The interrupt probe logic state
121
 *      is then returned to its previous value.
122
 *
123
 *      Note: we need to scan all the irq's even though we will
124
 *      only return autodetect irq numbers - just so that we reset
125
 *      them all to a known state.
126
 */
127
unsigned int probe_irq_mask(unsigned long val)
128
{
129
        unsigned int mask;
130
        int i;
131
 
132
        mask = 0;
133
        for (i = 0; i < NR_IRQS; i++) {
134
                struct irq_desc *desc = irq_desc + i;
135
                unsigned int status;
136
 
137
                spin_lock_irq(&desc->lock);
138
                status = desc->status;
139
 
140
                if (status & IRQ_AUTODETECT) {
141
                        if (i < 16 && !(status & IRQ_WAITING))
142
                                mask |= 1 << i;
143
 
144
                        desc->status = status & ~IRQ_AUTODETECT;
145
                        desc->chip->shutdown(i);
146
                }
147
                spin_unlock_irq(&desc->lock);
148
        }
149
        mutex_unlock(&probing_active);
150
 
151
        return mask & val;
152
}
153
EXPORT_SYMBOL(probe_irq_mask);
154
 
155
/**
156
 *      probe_irq_off   - end an interrupt autodetect
157
 *      @val: mask of potential interrupts (unused)
158
 *
159
 *      Scans the unused interrupt lines and returns the line which
160
 *      appears to have triggered the interrupt. If no interrupt was
161
 *      found then zero is returned. If more than one interrupt is
162
 *      found then minus the first candidate is returned to indicate
163
 *      their is doubt.
164
 *
165
 *      The interrupt probe logic state is returned to its previous
166
 *      value.
167
 *
168
 *      BUGS: When used in a module (which arguably shouldn't happen)
169
 *      nothing prevents two IRQ probe callers from overlapping. The
170
 *      results of this are non-optimal.
171
 */
172
int probe_irq_off(unsigned long val)
173
{
174
        int i, irq_found = 0, nr_irqs = 0;
175
 
176
        for (i = 0; i < NR_IRQS; i++) {
177
                struct irq_desc *desc = irq_desc + i;
178
                unsigned int status;
179
 
180
                spin_lock_irq(&desc->lock);
181
                status = desc->status;
182
 
183
                if (status & IRQ_AUTODETECT) {
184
                        if (!(status & IRQ_WAITING)) {
185
                                if (!nr_irqs)
186
                                        irq_found = i;
187
                                nr_irqs++;
188
                        }
189
                        desc->status = status & ~IRQ_AUTODETECT;
190
                        desc->chip->shutdown(i);
191
                }
192
                spin_unlock_irq(&desc->lock);
193
        }
194
        mutex_unlock(&probing_active);
195
 
196
        if (nr_irqs > 1)
197
                irq_found = -irq_found;
198
 
199
        return irq_found;
200
}
201
EXPORT_SYMBOL(probe_irq_off);
202
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.