Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ipu_irq.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008
3  * Guennadi Liakhovetski, DENX Software Engineering, <[email protected]>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #include <linux/init.h>
11 #include <linux/err.h>
12 #include <linux/spinlock.h>
13 #include <linux/delay.h>
14 #include <linux/clk.h>
15 #include <linux/irq.h>
16 #include <linux/io.h>
17 #include <linux/module.h>
18 
19 #include <mach/ipu.h>
20 
21 #include "ipu_intern.h"
22 
23 /*
24  * Register read / write - shall be inlined by the compiler
25  */
26 static u32 ipu_read_reg(struct ipu *ipu, unsigned long reg)
27 {
28  return __raw_readl(ipu->reg_ipu + reg);
29 }
30 
31 static void ipu_write_reg(struct ipu *ipu, u32 value, unsigned long reg)
32 {
33  __raw_writel(value, ipu->reg_ipu + reg);
34 }
35 
36 
37 /*
38  * IPU IRQ chip driver
39  */
40 
41 #define IPU_IRQ_NR_FN_BANKS 3
42 #define IPU_IRQ_NR_ERR_BANKS 2
43 #define IPU_IRQ_NR_BANKS (IPU_IRQ_NR_FN_BANKS + IPU_IRQ_NR_ERR_BANKS)
44 
45 struct ipu_irq_bank {
46  unsigned int control;
47  unsigned int status;
49  struct ipu *ipu;
50 };
51 
52 static struct ipu_irq_bank irq_bank[IPU_IRQ_NR_BANKS] = {
53  /* 3 groups of functional interrupts */
54  {
55  .control = IPU_INT_CTRL_1,
56  .status = IPU_INT_STAT_1,
57  }, {
58  .control = IPU_INT_CTRL_2,
59  .status = IPU_INT_STAT_2,
60  }, {
61  .control = IPU_INT_CTRL_3,
62  .status = IPU_INT_STAT_3,
63  },
64  /* 2 groups of error interrupts */
65  {
66  .control = IPU_INT_CTRL_4,
67  .status = IPU_INT_STAT_4,
68  }, {
69  .control = IPU_INT_CTRL_5,
70  .status = IPU_INT_STAT_5,
71  },
72 };
73 
74 struct ipu_irq_map {
75  unsigned int irq;
76  int source;
77  struct ipu_irq_bank *bank;
78  struct ipu *ipu;
79 };
80 
81 static struct ipu_irq_map irq_map[CONFIG_MX3_IPU_IRQS];
82 /* Protects allocations from the above array of maps */
83 static DEFINE_MUTEX(map_lock);
84 /* Protects register accesses and individual mappings */
85 static DEFINE_RAW_SPINLOCK(bank_lock);
86 
87 static struct ipu_irq_map *src2map(unsigned int src)
88 {
89  int i;
90 
91  for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++)
92  if (irq_map[i].source == src)
93  return irq_map + i;
94 
95  return NULL;
96 }
97 
98 static void ipu_irq_unmask(struct irq_data *d)
99 {
100  struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
101  struct ipu_irq_bank *bank;
102  uint32_t reg;
103  unsigned long lock_flags;
104 
105  raw_spin_lock_irqsave(&bank_lock, lock_flags);
106 
107  bank = map->bank;
108  if (!bank) {
109  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
110  pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
111  return;
112  }
113 
114  reg = ipu_read_reg(bank->ipu, bank->control);
115  reg |= (1UL << (map->source & 31));
116  ipu_write_reg(bank->ipu, reg, bank->control);
117 
118  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
119 }
120 
121 static void ipu_irq_mask(struct irq_data *d)
122 {
123  struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
124  struct ipu_irq_bank *bank;
125  uint32_t reg;
126  unsigned long lock_flags;
127 
128  raw_spin_lock_irqsave(&bank_lock, lock_flags);
129 
130  bank = map->bank;
131  if (!bank) {
132  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
133  pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
134  return;
135  }
136 
137  reg = ipu_read_reg(bank->ipu, bank->control);
138  reg &= ~(1UL << (map->source & 31));
139  ipu_write_reg(bank->ipu, reg, bank->control);
140 
141  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
142 }
143 
144 static void ipu_irq_ack(struct irq_data *d)
145 {
146  struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
147  struct ipu_irq_bank *bank;
148  unsigned long lock_flags;
149 
150  raw_spin_lock_irqsave(&bank_lock, lock_flags);
151 
152  bank = map->bank;
153  if (!bank) {
154  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
155  pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
156  return;
157  }
158 
159  ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
160  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
161 }
162 
169 bool ipu_irq_status(unsigned int irq)
170 {
171  struct ipu_irq_map *map = irq_get_chip_data(irq);
172  struct ipu_irq_bank *bank;
173  unsigned long lock_flags;
174  bool ret;
175 
176  raw_spin_lock_irqsave(&bank_lock, lock_flags);
177  bank = map->bank;
178  ret = bank && ipu_read_reg(bank->ipu, bank->status) &
179  (1UL << (map->source & 31));
180  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
181 
182  return ret;
183 }
184 
198 int ipu_irq_map(unsigned int source)
199 {
200  int i, ret = -ENOMEM;
201  struct ipu_irq_map *map;
202 
203  might_sleep();
204 
205  mutex_lock(&map_lock);
206  map = src2map(source);
207  if (map) {
208  pr_err("IPU: Source %u already mapped to IRQ %u\n", source, map->irq);
209  ret = -EBUSY;
210  goto out;
211  }
212 
213  for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
214  if (irq_map[i].source < 0) {
215  unsigned long lock_flags;
216 
217  raw_spin_lock_irqsave(&bank_lock, lock_flags);
218  irq_map[i].source = source;
219  irq_map[i].bank = irq_bank + source / 32;
220  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
221 
222  ret = irq_map[i].irq;
223  pr_debug("IPU: mapped source %u to IRQ %u\n",
224  source, ret);
225  break;
226  }
227  }
228 out:
229  mutex_unlock(&map_lock);
230 
231  if (ret < 0)
232  pr_err("IPU: couldn't map source %u: %d\n", source, ret);
233 
234  return ret;
235 }
236 
242 int ipu_irq_unmap(unsigned int source)
243 {
244  int i, ret = -EINVAL;
245 
246  might_sleep();
247 
248  mutex_lock(&map_lock);
249  for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
250  if (irq_map[i].source == source) {
251  unsigned long lock_flags;
252 
253  pr_debug("IPU: unmapped source %u from IRQ %u\n",
254  source, irq_map[i].irq);
255 
256  raw_spin_lock_irqsave(&bank_lock, lock_flags);
257  irq_map[i].source = -EINVAL;
258  irq_map[i].bank = NULL;
259  raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
260 
261  ret = 0;
262  break;
263  }
264  }
265  mutex_unlock(&map_lock);
266 
267  return ret;
268 }
269 
270 /* Chained IRQ handler for IPU error interrupt */
271 static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
272 {
273  struct ipu *ipu = irq_get_handler_data(irq);
274  u32 status;
275  int i, line;
276 
277  for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
278  struct ipu_irq_bank *bank = irq_bank + i;
279 
280  raw_spin_lock(&bank_lock);
281  status = ipu_read_reg(ipu, bank->status);
282  /*
283  * Don't think we have to clear all interrupts here, they will
284  * be acked by ->handle_irq() (handle_level_irq). However, we
285  * might want to clear unhandled interrupts after the loop...
286  */
287  status &= ipu_read_reg(ipu, bank->control);
288  raw_spin_unlock(&bank_lock);
289  while ((line = ffs(status))) {
290  struct ipu_irq_map *map;
291 
292  line--;
293  status &= ~(1UL << line);
294 
295  raw_spin_lock(&bank_lock);
296  map = src2map(32 * i + line);
297  if (map)
298  irq = map->irq;
299  raw_spin_unlock(&bank_lock);
300 
301  if (!map) {
302  pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
303  line, i);
304  continue;
305  }
306  generic_handle_irq(irq);
307  }
308  }
309 }
310 
311 /* Chained IRQ handler for IPU function interrupt */
312 static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
313 {
314  struct ipu *ipu = irq_desc_get_handler_data(desc);
315  u32 status;
316  int i, line;
317 
318  for (i = 0; i < IPU_IRQ_NR_FN_BANKS; i++) {
319  struct ipu_irq_bank *bank = irq_bank + i;
320 
321  raw_spin_lock(&bank_lock);
322  status = ipu_read_reg(ipu, bank->status);
323  /* Not clearing all interrupts, see above */
324  status &= ipu_read_reg(ipu, bank->control);
325  raw_spin_unlock(&bank_lock);
326  while ((line = ffs(status))) {
327  struct ipu_irq_map *map;
328 
329  line--;
330  status &= ~(1UL << line);
331 
332  raw_spin_lock(&bank_lock);
333  map = src2map(32 * i + line);
334  if (map)
335  irq = map->irq;
336  raw_spin_unlock(&bank_lock);
337 
338  if (!map) {
339  pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
340  line, i);
341  continue;
342  }
343  generic_handle_irq(irq);
344  }
345  }
346 }
347 
348 static struct irq_chip ipu_irq_chip = {
349  .name = "ipu_irq",
350  .irq_ack = ipu_irq_ack,
351  .irq_mask = ipu_irq_mask,
352  .irq_unmask = ipu_irq_unmask,
353 };
354 
355 /* Install the IRQ handler */
356 int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
357 {
358  unsigned int irq, i;
359  int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS,
360  numa_node_id());
361 
362  if (irq_base < 0)
363  return irq_base;
364 
365  for (i = 0; i < IPU_IRQ_NR_BANKS; i++)
366  irq_bank[i].ipu = ipu;
367 
368  for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
369  int ret;
370 
371  irq = irq_base + i;
372  ret = irq_set_chip(irq, &ipu_irq_chip);
373  if (ret < 0)
374  return ret;
375  ret = irq_set_chip_data(irq, irq_map + i);
376  if (ret < 0)
377  return ret;
378  irq_map[i].ipu = ipu;
379  irq_map[i].irq = irq;
380  irq_map[i].source = -EINVAL;
381  irq_set_handler(irq, handle_level_irq);
382 #ifdef CONFIG_ARM
384 #endif
385  }
386 
387  irq_set_handler_data(ipu->irq_fn, ipu);
388  irq_set_chained_handler(ipu->irq_fn, ipu_irq_fn);
389 
390  irq_set_handler_data(ipu->irq_err, ipu);
391  irq_set_chained_handler(ipu->irq_err, ipu_irq_err);
392 
393  ipu->irq_base = irq_base;
394 
395  return 0;
396 }
397 
398 void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
399 {
400  unsigned int irq, irq_base;
401 
402  irq_base = ipu->irq_base;
403 
404  irq_set_chained_handler(ipu->irq_fn, NULL);
406 
407  irq_set_chained_handler(ipu->irq_err, NULL);
409 
410  for (irq = irq_base; irq < irq_base + CONFIG_MX3_IPU_IRQS; irq++) {
411 #ifdef CONFIG_ARM
412  set_irq_flags(irq, 0);
413 #endif
414  irq_set_chip(irq, NULL);
415  irq_set_chip_data(irq, NULL);
416  }
417 }