Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.6-rc1 417 lines 10 kB view raw
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> 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 */ 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 */ 85static DEFINE_RAW_SPINLOCK(bank_lock); 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 98static 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 121static 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 144static 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 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{ 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 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 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 } 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 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 */ 271static 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 */ 312static 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 348static 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 */ 356int __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 383 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 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 398void 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); 405 irq_set_handler_data(ipu->irq_fn, NULL); 406 407 irq_set_chained_handler(ipu->irq_err, NULL); 408 irq_set_handler_data(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}