Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
generic-chip.c
Go to the documentation of this file.
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/export.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel_stat.h>
12 #include <linux/syscore_ops.h>
13 
14 #include "internals.h"
15 
16 static LIST_HEAD(gc_list);
17 static DEFINE_RAW_SPINLOCK(gc_lock);
18 
19 static inline struct irq_chip_regs *cur_regs(struct irq_data *d)
20 {
21  return &container_of(d->chip, struct irq_chip_type, chip)->regs;
22 }
23 
28 void irq_gc_noop(struct irq_data *d)
29 {
30 }
31 
40 {
41  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
42  u32 mask = 1 << (d->irq - gc->irq_base);
43 
44  irq_gc_lock(gc);
45  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable);
46  gc->mask_cache &= ~mask;
47  irq_gc_unlock(gc);
48 }
49 
58 {
59  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
60  u32 mask = 1 << (d->irq - gc->irq_base);
61 
62  irq_gc_lock(gc);
63  gc->mask_cache |= mask;
64  irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
65  irq_gc_unlock(gc);
66 }
67 
76 {
77  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
78  u32 mask = 1 << (d->irq - gc->irq_base);
79 
80  irq_gc_lock(gc);
81  gc->mask_cache &= ~mask;
82  irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask);
83  irq_gc_unlock(gc);
84 }
85 
94 {
95  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
96  u32 mask = 1 << (d->irq - gc->irq_base);
97 
98  irq_gc_lock(gc);
99  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable);
100  gc->mask_cache |= mask;
101  irq_gc_unlock(gc);
102 }
103 
109 {
110  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
111  u32 mask = 1 << (d->irq - gc->irq_base);
112 
113  irq_gc_lock(gc);
114  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
115  irq_gc_unlock(gc);
116 }
117 
123 {
124  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
125  u32 mask = ~(1 << (d->irq - gc->irq_base));
126 
127  irq_gc_lock(gc);
128  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
129  irq_gc_unlock(gc);
130 }
131 
137 {
138  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
139  u32 mask = 1 << (d->irq - gc->irq_base);
140 
141  irq_gc_lock(gc);
142  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask);
143  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack);
144  irq_gc_unlock(gc);
145 }
146 
151 void irq_gc_eoi(struct irq_data *d)
152 {
153  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
154  u32 mask = 1 << (d->irq - gc->irq_base);
155 
156  irq_gc_lock(gc);
157  irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi);
158  irq_gc_unlock(gc);
159 }
160 
169 int irq_gc_set_wake(struct irq_data *d, unsigned int on)
170 {
171  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
172  u32 mask = 1 << (d->irq - gc->irq_base);
173 
174  if (!(mask & gc->wake_enabled))
175  return -EINVAL;
176 
177  irq_gc_lock(gc);
178  if (on)
179  gc->wake_active |= mask;
180  else
181  gc->wake_active &= ~mask;
182  irq_gc_unlock(gc);
183  return 0;
184 }
185 
197 struct irq_chip_generic *
198 irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base,
199  void __iomem *reg_base, irq_flow_handler_t handler)
200 {
201  struct irq_chip_generic *gc;
202  unsigned long sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type);
203 
204  gc = kzalloc(sz, GFP_KERNEL);
205  if (gc) {
206  raw_spin_lock_init(&gc->lock);
207  gc->num_ct = num_ct;
208  gc->irq_base = irq_base;
209  gc->reg_base = reg_base;
210  gc->chip_types->chip.name = name;
211  gc->chip_types->handler = handler;
212  }
213  return gc;
214 }
216 
217 /*
218  * Separate lockdep class for interrupt chip which can nest irq_desc
219  * lock.
220  */
221 static struct lock_class_key irq_nested_lock_class;
222 
235 void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
236  enum irq_gc_flags flags, unsigned int clr,
237  unsigned int set)
238 {
239  struct irq_chip_type *ct = gc->chip_types;
240  unsigned int i;
241 
242  raw_spin_lock(&gc_lock);
243  list_add_tail(&gc->list, &gc_list);
244  raw_spin_unlock(&gc_lock);
245 
246  /* Init mask cache ? */
247  if (flags & IRQ_GC_INIT_MASK_CACHE)
248  gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
249 
250  for (i = gc->irq_base; msk; msk >>= 1, i++) {
251  if (!(msk & 0x01))
252  continue;
253 
254  if (flags & IRQ_GC_INIT_NESTED_LOCK)
255  irq_set_lockdep_class(i, &irq_nested_lock_class);
256 
257  irq_set_chip_and_handler(i, &ct->chip, ct->handler);
258  irq_set_chip_data(i, gc);
259  irq_modify_status(i, clr, set);
260  }
261  gc->irq_cnt = i - gc->irq_base;
262 }
264 
272 int irq_setup_alt_chip(struct irq_data *d, unsigned int type)
273 {
274  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
275  struct irq_chip_type *ct = gc->chip_types;
276  unsigned int i;
277 
278  for (i = 0; i < gc->num_ct; i++, ct++) {
279  if (ct->type & type) {
280  d->chip = &ct->chip;
281  irq_data_to_desc(d)->handle_irq = ct->handler;
282  return 0;
283  }
284  }
285  return -EINVAL;
286 }
288 
298 void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
299  unsigned int clr, unsigned int set)
300 {
301  unsigned int i = gc->irq_base;
302 
303  raw_spin_lock(&gc_lock);
304  list_del(&gc->list);
305  raw_spin_unlock(&gc_lock);
306 
307  for (; msk; msk >>= 1, i++) {
308  if (!(msk & 0x01))
309  continue;
310 
311  /* Remove handler first. That will mask the irq line */
312  irq_set_handler(i, NULL);
315  irq_modify_status(i, clr, set);
316  }
317 }
319 
320 #ifdef CONFIG_PM
321 static int irq_gc_suspend(void)
322 {
323  struct irq_chip_generic *gc;
324 
325  list_for_each_entry(gc, &gc_list, list) {
326  struct irq_chip_type *ct = gc->chip_types;
327 
328  if (ct->chip.irq_suspend)
329  ct->chip.irq_suspend(irq_get_irq_data(gc->irq_base));
330  }
331  return 0;
332 }
333 
334 static void irq_gc_resume(void)
335 {
336  struct irq_chip_generic *gc;
337 
338  list_for_each_entry(gc, &gc_list, list) {
339  struct irq_chip_type *ct = gc->chip_types;
340 
341  if (ct->chip.irq_resume)
342  ct->chip.irq_resume(irq_get_irq_data(gc->irq_base));
343  }
344 }
345 #else
346 #define irq_gc_suspend NULL
347 #define irq_gc_resume NULL
348 #endif
349 
350 static void irq_gc_shutdown(void)
351 {
352  struct irq_chip_generic *gc;
353 
354  list_for_each_entry(gc, &gc_list, list) {
355  struct irq_chip_type *ct = gc->chip_types;
356 
357  if (ct->chip.irq_pm_shutdown)
358  ct->chip.irq_pm_shutdown(irq_get_irq_data(gc->irq_base));
359  }
360 }
361 
362 static struct syscore_ops irq_gc_syscore_ops = {
363  .suspend = irq_gc_suspend,
364  .resume = irq_gc_resume,
365  .shutdown = irq_gc_shutdown,
366 };
367 
368 static int __init irq_gc_init_ops(void)
369 {
370  register_syscore_ops(&irq_gc_syscore_ops);
371  return 0;
372 }
373 device_initcall(irq_gc_init_ops);