ARM: imx: remove mach/dma-mx1-mx2.h
[deliverable/linux.git] / drivers / dma / ipu / ipu_irq.c
CommitLineData
5296b56d
GL
1/*
2 * Copyright (C) 2008
3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
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>
88289c80 17#include <linux/module.h>
5296b56d
GL
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 */
26static u32 ipu_read_reg(struct ipu *ipu, unsigned long reg)
27{
28 return __raw_readl(ipu->reg_ipu + reg);
29}
30
31static 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
45struct ipu_irq_bank {
46 unsigned int control;
47 unsigned int status;
48 spinlock_t lock;
49 struct ipu *ipu;
50};
51
52static 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
74struct ipu_irq_map {
75 unsigned int irq;
76 int source;
77 struct ipu_irq_bank *bank;
78 struct ipu *ipu;
79};
80
81static struct ipu_irq_map irq_map[CONFIG_MX3_IPU_IRQS];
82/* Protects allocations from the above array of maps */
83static DEFINE_MUTEX(map_lock);
84/* Protects register accesses and individual mappings */
289b4e7a 85static DEFINE_RAW_SPINLOCK(bank_lock);
5296b56d
GL
86
87static 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
6a035138 98static void ipu_irq_unmask(struct irq_data *d)
5296b56d 99{
6a035138 100 struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
5296b56d
GL
101 struct ipu_irq_bank *bank;
102 uint32_t reg;
103 unsigned long lock_flags;
104
289b4e7a 105 raw_spin_lock_irqsave(&bank_lock, lock_flags);
5296b56d
GL
106
107 bank = map->bank;
108 if (!bank) {
289b4e7a 109 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
6a035138 110 pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
5296b56d
GL
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
289b4e7a 118 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
5296b56d
GL
119}
120
6a035138 121static void ipu_irq_mask(struct irq_data *d)
5296b56d 122{
6a035138 123 struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
5296b56d
GL
124 struct ipu_irq_bank *bank;
125 uint32_t reg;
126 unsigned long lock_flags;
127
289b4e7a 128 raw_spin_lock_irqsave(&bank_lock, lock_flags);
5296b56d
GL
129
130 bank = map->bank;
131 if (!bank) {
289b4e7a 132 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
6a035138 133 pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
5296b56d
GL
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
289b4e7a 141 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
5296b56d
GL
142}
143
6a035138 144static void ipu_irq_ack(struct irq_data *d)
5296b56d 145{
6a035138 146 struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
5296b56d
GL
147 struct ipu_irq_bank *bank;
148 unsigned long lock_flags;
149
289b4e7a 150 raw_spin_lock_irqsave(&bank_lock, lock_flags);
5296b56d
GL
151
152 bank = map->bank;
153 if (!bank) {
289b4e7a 154 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
6a035138 155 pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
5296b56d
GL
156 return;
157 }
158
159 ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
289b4e7a 160 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
5296b56d
GL
161}
162
163/**
164 * ipu_irq_status() - returns the current interrupt status of the specified IRQ.
165 * @irq: interrupt line to get status for.
166 * @return: true if the interrupt is pending/asserted or false if the
167 * interrupt is not pending.
168 */
169bool ipu_irq_status(unsigned int irq)
170{
6a035138 171 struct ipu_irq_map *map = irq_get_chip_data(irq);
5296b56d
GL
172 struct ipu_irq_bank *bank;
173 unsigned long lock_flags;
174 bool ret;
175
289b4e7a 176 raw_spin_lock_irqsave(&bank_lock, lock_flags);
5296b56d
GL
177 bank = map->bank;
178 ret = bank && ipu_read_reg(bank->ipu, bank->status) &
179 (1UL << (map->source & 31));
289b4e7a 180 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
5296b56d
GL
181
182 return ret;
183}
184
185/**
186 * ipu_irq_map() - map an IPU interrupt source to an IRQ number
187 * @source: interrupt source bit position (see below)
188 * @return: mapped IRQ number or negative error code
189 *
190 * The source parameter has to be explained further. On i.MX31 IPU has 137 IRQ
191 * sources, they are broken down in 5 32-bit registers, like 32, 32, 24, 32, 17.
192 * However, the source argument of this function is not the sequence number of
193 * the possible IRQ, but rather its bit position. So, first interrupt in fourth
194 * register has source number 96, and not 88. This makes calculations easier,
195 * and also provides forward compatibility with any future IPU implementations
196 * with any interrupt bit assignments.
197 */
198int 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
289b4e7a 217 raw_spin_lock_irqsave(&bank_lock, lock_flags);
5296b56d
GL
218 irq_map[i].source = source;
219 irq_map[i].bank = irq_bank + source / 32;
289b4e7a 220 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
5296b56d
GL
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 }
228out:
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
237/**
238 * ipu_irq_map() - map an IPU interrupt source to an IRQ number
239 * @source: interrupt source bit position (see ipu_irq_map())
240 * @return: 0 or negative error code
241 */
242int 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
289b4e7a 256 raw_spin_lock_irqsave(&bank_lock, lock_flags);
5296b56d
GL
257 irq_map[i].source = -EINVAL;
258 irq_map[i].bank = NULL;
289b4e7a 259 raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
5296b56d
GL
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 */
271static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
272{
6a035138 273 struct ipu *ipu = irq_get_handler_data(irq);
5296b56d
GL
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
289b4e7a 280 raw_spin_lock(&bank_lock);
5296b56d
GL
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);
289b4e7a 288 raw_spin_unlock(&bank_lock);
5296b56d
GL
289 while ((line = ffs(status))) {
290 struct ipu_irq_map *map;
291
292 line--;
293 status &= ~(1UL << line);
294
289b4e7a 295 raw_spin_lock(&bank_lock);
5296b56d
GL
296 map = src2map(32 * i + line);
297 if (map)
298 irq = map->irq;
289b4e7a 299 raw_spin_unlock(&bank_lock);
5296b56d
GL
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 */
312static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
313{
6a035138 314 struct ipu *ipu = irq_desc_get_handler_data(desc);
5296b56d
GL
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
289b4e7a 321 raw_spin_lock(&bank_lock);
5296b56d
GL
322 status = ipu_read_reg(ipu, bank->status);
323 /* Not clearing all interrupts, see above */
324 status &= ipu_read_reg(ipu, bank->control);
289b4e7a 325 raw_spin_unlock(&bank_lock);
5296b56d
GL
326 while ((line = ffs(status))) {
327 struct ipu_irq_map *map;
328
329 line--;
330 status &= ~(1UL << line);
331
289b4e7a 332 raw_spin_lock(&bank_lock);
5296b56d
GL
333 map = src2map(32 * i + line);
334 if (map)
335 irq = map->irq;
289b4e7a 336 raw_spin_unlock(&bank_lock);
5296b56d
GL
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
348static struct irq_chip ipu_irq_chip = {
6a035138
TG
349 .name = "ipu_irq",
350 .irq_ack = ipu_irq_ack,
351 .irq_mask = ipu_irq_mask,
352 .irq_unmask = ipu_irq_unmask,
5296b56d
GL
353};
354
355/* Install the IRQ handler */
234f2df5 356int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
5296b56d 357{
88289c80
SG
358 unsigned int irq, i;
359 int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS,
360 numa_node_id());
5296b56d 361
88289c80
SG
362 if (irq_base < 0)
363 return irq_base;
5296b56d
GL
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;
6a035138 372 ret = irq_set_chip(irq, &ipu_irq_chip);
5296b56d
GL
373 if (ret < 0)
374 return ret;
6a035138 375 ret = irq_set_chip_data(irq, irq_map + i);
5296b56d
GL
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;
6a035138 381 irq_set_handler(irq, handle_level_irq);
5296b56d
GL
382#ifdef CONFIG_ARM
383 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
384#endif
385 }
386
6a035138
TG
387 irq_set_handler_data(ipu->irq_fn, ipu);
388 irq_set_chained_handler(ipu->irq_fn, ipu_irq_fn);
5296b56d 389
6a035138
TG
390 irq_set_handler_data(ipu->irq_err, ipu);
391 irq_set_chained_handler(ipu->irq_err, ipu_irq_err);
5296b56d 392
88289c80
SG
393 ipu->irq_base = irq_base;
394
5296b56d
GL
395 return 0;
396}
397
398void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
399{
5296b56d
GL
400 unsigned int irq, irq_base;
401
88289c80 402 irq_base = ipu->irq_base;
5296b56d 403
6a035138
TG
404 irq_set_chained_handler(ipu->irq_fn, NULL);
405 irq_set_handler_data(ipu->irq_fn, NULL);
5296b56d 406
6a035138
TG
407 irq_set_chained_handler(ipu->irq_err, NULL);
408 irq_set_handler_data(ipu->irq_err, NULL);
5296b56d
GL
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
6a035138
TG
414 irq_set_chip(irq, NULL);
415 irq_set_chip_data(irq, NULL);
5296b56d
GL
416 }
417}
This page took 0.267018 seconds and 5 git commands to generate.