]>
Commit | Line | Data |
---|---|---|
7d828062 TG |
1 | /* |
2 | * Library implementing the most common irq chip callback functions | |
3 | * | |
4 | * Copyright (C) 2011, Thomas Gleixner | |
5 | */ | |
6 | #include <linux/io.h> | |
7 | #include <linux/irq.h> | |
8 | #include <linux/slab.h> | |
9 | #include <linux/interrupt.h> | |
10 | #include <linux/kernel_stat.h> | |
11 | ||
12 | #include "internals.h" | |
13 | ||
14 | static inline struct irq_chip_regs *cur_regs(struct irq_data *d) | |
15 | { | |
16 | return &container_of(d->chip, struct irq_chip_type, chip)->regs; | |
17 | } | |
18 | ||
19 | /** | |
20 | * irq_gc_noop - NOOP function | |
21 | * @d: irq_data | |
22 | */ | |
23 | void irq_gc_noop(struct irq_data *d) | |
24 | { | |
25 | } | |
26 | ||
27 | /** | |
28 | * irq_gc_mask_disable_reg - Mask chip via disable register | |
29 | * @d: irq_data | |
30 | * | |
31 | * Chip has separate enable/disable registers instead of a single mask | |
32 | * register. | |
33 | */ | |
34 | void irq_gc_mask_disable_reg(struct irq_data *d) | |
35 | { | |
36 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
37 | u32 mask = 1 << (d->irq - gc->irq_base); | |
38 | ||
39 | irq_gc_lock(gc); | |
40 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable); | |
41 | gc->mask_cache &= ~mask; | |
42 | irq_gc_unlock(gc); | |
43 | } | |
44 | ||
45 | /** | |
46 | * irq_gc_mask_set_mask_bit - Mask chip via setting bit in mask register | |
47 | * @d: irq_data | |
48 | * | |
49 | * Chip has a single mask register. Values of this register are cached | |
50 | * and protected by gc->lock | |
51 | */ | |
52 | void irq_gc_mask_set_bit(struct irq_data *d) | |
53 | { | |
54 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
55 | u32 mask = 1 << (d->irq - gc->irq_base); | |
56 | ||
57 | irq_gc_lock(gc); | |
58 | gc->mask_cache |= mask; | |
59 | irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask); | |
60 | irq_gc_unlock(gc); | |
61 | } | |
62 | ||
63 | /** | |
64 | * irq_gc_mask_set_mask_bit - Mask chip via clearing bit in mask register | |
65 | * @d: irq_data | |
66 | * | |
67 | * Chip has a single mask register. Values of this register are cached | |
68 | * and protected by gc->lock | |
69 | */ | |
70 | void irq_gc_mask_clr_bit(struct irq_data *d) | |
71 | { | |
72 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
73 | u32 mask = 1 << (d->irq - gc->irq_base); | |
74 | ||
75 | irq_gc_lock(gc); | |
76 | gc->mask_cache &= ~mask; | |
77 | irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask); | |
78 | irq_gc_unlock(gc); | |
79 | } | |
80 | ||
81 | /** | |
82 | * irq_gc_unmask_enable_reg - Unmask chip via enable register | |
83 | * @d: irq_data | |
84 | * | |
85 | * Chip has separate enable/disable registers instead of a single mask | |
86 | * register. | |
87 | */ | |
88 | void irq_gc_unmask_enable_reg(struct irq_data *d) | |
89 | { | |
90 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
91 | u32 mask = 1 << (d->irq - gc->irq_base); | |
92 | ||
93 | irq_gc_lock(gc); | |
94 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable); | |
95 | gc->mask_cache |= mask; | |
96 | irq_gc_unlock(gc); | |
97 | } | |
98 | ||
99 | /** | |
100 | * irq_gc_ack - Ack pending interrupt | |
101 | * @d: irq_data | |
102 | */ | |
103 | void irq_gc_ack(struct irq_data *d) | |
104 | { | |
105 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
106 | u32 mask = 1 << (d->irq - gc->irq_base); | |
107 | ||
108 | irq_gc_lock(gc); | |
109 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | |
110 | irq_gc_unlock(gc); | |
111 | } | |
112 | ||
113 | /** | |
114 | * irq_gc_mask_disable_reg_and_ack- Mask and ack pending interrupt | |
115 | * @d: irq_data | |
116 | */ | |
117 | void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) | |
118 | { | |
119 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
120 | u32 mask = 1 << (d->irq - gc->irq_base); | |
121 | ||
122 | irq_gc_lock(gc); | |
123 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask); | |
124 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | |
125 | irq_gc_unlock(gc); | |
126 | } | |
127 | ||
128 | /** | |
129 | * irq_gc_eoi - EOI interrupt | |
130 | * @d: irq_data | |
131 | */ | |
132 | void irq_gc_eoi(struct irq_data *d) | |
133 | { | |
134 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
135 | u32 mask = 1 << (d->irq - gc->irq_base); | |
136 | ||
137 | irq_gc_lock(gc); | |
138 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi); | |
139 | irq_gc_unlock(gc); | |
140 | } | |
141 | ||
142 | /** | |
143 | * irq_gc_set_wake - Set/clr wake bit for an interrupt | |
144 | * @d: irq_data | |
145 | * | |
146 | * For chips where the wake from suspend functionality is not | |
147 | * configured in a separate register and the wakeup active state is | |
148 | * just stored in a bitmask. | |
149 | */ | |
150 | int irq_gc_set_wake(struct irq_data *d, unsigned int on) | |
151 | { | |
152 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
153 | u32 mask = 1 << (d->irq - gc->irq_base); | |
154 | ||
155 | if (!(mask & gc->wake_enabled)) | |
156 | return -EINVAL; | |
157 | ||
158 | irq_gc_lock(gc); | |
159 | if (on) | |
160 | gc->wake_active |= mask; | |
161 | else | |
162 | gc->wake_active &= ~mask; | |
163 | irq_gc_unlock(gc); | |
164 | return 0; | |
165 | } | |
166 | ||
167 | /** | |
168 | * irq_alloc_generic_chip - Allocate a generic chip and initialize it | |
169 | * @name: Name of the irq chip | |
170 | * @num_ct: Number of irq_chip_type instances associated with this | |
171 | * @irq_base: Interrupt base nr for this chip | |
172 | * @reg_base: Register base address (virtual) | |
173 | * @handler: Default flow handler associated with this chip | |
174 | * | |
175 | * Returns an initialized irq_chip_generic structure. The chip defaults | |
176 | * to the primary (index 0) irq_chip_type and @handler | |
177 | */ | |
178 | struct irq_chip_generic * | |
179 | irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base, | |
180 | void __iomem *reg_base, irq_flow_handler_t handler) | |
181 | { | |
182 | struct irq_chip_generic *gc; | |
183 | unsigned long sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type); | |
184 | ||
185 | gc = kzalloc(sz, GFP_KERNEL); | |
186 | if (gc) { | |
187 | raw_spin_lock_init(&gc->lock); | |
188 | gc->num_ct = num_ct; | |
189 | gc->irq_base = irq_base; | |
190 | gc->reg_base = reg_base; | |
191 | gc->chip_types->chip.name = name; | |
192 | gc->chip_types->handler = handler; | |
193 | } | |
194 | return gc; | |
195 | } | |
196 | ||
197 | /* | |
198 | * Separate lockdep class for interrupt chip which can nest irq_desc | |
199 | * lock. | |
200 | */ | |
201 | static struct lock_class_key irq_nested_lock_class; | |
202 | ||
203 | /** | |
204 | * irq_setup_generic_chip - Setup a range of interrupts with a generic chip | |
205 | * @gc: Generic irq chip holding all data | |
206 | * @msk: Bitmask holding the irqs to initialize relative to gc->irq_base | |
207 | * @flags: Flags for initialization | |
208 | * @clr: IRQ_* bits to clear | |
209 | * @set: IRQ_* bits to set | |
210 | * | |
211 | * Set up max. 32 interrupts starting from gc->irq_base. Note, this | |
212 | * initializes all interrupts to the primary irq_chip_type and its | |
213 | * associated handler. | |
214 | */ | |
215 | void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | |
216 | enum irq_gc_flags flags, unsigned int clr, | |
217 | unsigned int set) | |
218 | { | |
219 | struct irq_chip_type *ct = gc->chip_types; | |
220 | unsigned int i; | |
221 | ||
222 | /* Init mask cache ? */ | |
223 | if (flags & IRQ_GC_INIT_MASK_CACHE) | |
224 | gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); | |
225 | ||
226 | for (i = gc->irq_base; msk; msk >>= 1, i++) { | |
227 | if (!msk & 0x01) | |
228 | continue; | |
229 | ||
230 | if (flags & IRQ_GC_INIT_NESTED_LOCK) | |
231 | irq_set_lockdep_class(i, &irq_nested_lock_class); | |
232 | ||
233 | irq_set_chip_and_handler(i, &ct->chip, ct->handler); | |
234 | irq_set_chip_data(i, gc); | |
235 | irq_modify_status(i, clr, set); | |
236 | } | |
237 | gc->irq_cnt = i - gc->irq_base; | |
238 | } | |
239 | ||
240 | /** | |
241 | * irq_setup_alt_chip - Switch to alternative chip | |
242 | * @d: irq_data for this interrupt | |
243 | * @type Flow type to be initialized | |
244 | * | |
245 | * Only to be called from chip->irq_set_type() callbacks. | |
246 | */ | |
247 | int irq_setup_alt_chip(struct irq_data *d, unsigned int type) | |
248 | { | |
249 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
250 | struct irq_chip_type *ct = gc->chip_types; | |
251 | unsigned int i; | |
252 | ||
253 | for (i = 0; i < gc->num_ct; i++, ct++) { | |
254 | if (ct->type & type) { | |
255 | d->chip = &ct->chip; | |
256 | irq_data_to_desc(d)->handle_irq = ct->handler; | |
257 | return 0; | |
258 | } | |
259 | } | |
260 | return -EINVAL; | |
261 | } |