linux/drivers/dma/ipu/ipu_irq.c
<<
>>
Prefs
   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#include <linux/dma/ipu-dma.h>
  19
  20#include "ipu_intern.h"
  21
  22/*
  23 * Register read / write - shall be inlined by the compiler
  24 */
  25static u32 ipu_read_reg(struct ipu *ipu, unsigned long reg)
  26{
  27        return __raw_readl(ipu->reg_ipu + reg);
  28}
  29
  30static void ipu_write_reg(struct ipu *ipu, u32 value, unsigned long reg)
  31{
  32        __raw_writel(value, ipu->reg_ipu + reg);
  33}
  34
  35
  36/*
  37 * IPU IRQ chip driver
  38 */
  39
  40#define IPU_IRQ_NR_FN_BANKS 3
  41#define IPU_IRQ_NR_ERR_BANKS 2
  42#define IPU_IRQ_NR_BANKS (IPU_IRQ_NR_FN_BANKS + IPU_IRQ_NR_ERR_BANKS)
  43
  44struct ipu_irq_bank {
  45        unsigned int    control;
  46        unsigned int    status;
  47        struct ipu      *ipu;
  48};
  49
  50static struct ipu_irq_bank irq_bank[IPU_IRQ_NR_BANKS] = {
  51        /* 3 groups of functional interrupts */
  52        {
  53                .control        = IPU_INT_CTRL_1,
  54                .status         = IPU_INT_STAT_1,
  55        }, {
  56                .control        = IPU_INT_CTRL_2,
  57                .status         = IPU_INT_STAT_2,
  58        }, {
  59                .control        = IPU_INT_CTRL_3,
  60                .status         = IPU_INT_STAT_3,
  61        },
  62        /* 2 groups of error interrupts */
  63        {
  64                .control        = IPU_INT_CTRL_4,
  65                .status         = IPU_INT_STAT_4,
  66        }, {
  67                .control        = IPU_INT_CTRL_5,
  68                .status         = IPU_INT_STAT_5,
  69        },
  70};
  71
  72struct ipu_irq_map {
  73        unsigned int            irq;
  74        int                     source;
  75        struct ipu_irq_bank     *bank;
  76        struct ipu              *ipu;
  77};
  78
  79static struct ipu_irq_map irq_map[CONFIG_MX3_IPU_IRQS];
  80/* Protects allocations from the above array of maps */
  81static DEFINE_MUTEX(map_lock);
  82/* Protects register accesses and individual mappings */
  83static DEFINE_RAW_SPINLOCK(bank_lock);
  84
  85static struct ipu_irq_map *src2map(unsigned int src)
  86{
  87        int i;
  88
  89        for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++)
  90                if (irq_map[i].source == src)
  91                        return irq_map + i;
  92
  93        return NULL;
  94}
  95
  96static void ipu_irq_unmask(struct irq_data *d)
  97{
  98        struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
  99        struct ipu_irq_bank *bank;
 100        uint32_t reg;
 101        unsigned long lock_flags;
 102
 103        raw_spin_lock_irqsave(&bank_lock, lock_flags);
 104
 105        bank = map->bank;
 106        if (!bank) {
 107                raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 108                pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 109                return;
 110        }
 111
 112        reg = ipu_read_reg(bank->ipu, bank->control);
 113        reg |= (1UL << (map->source & 31));
 114        ipu_write_reg(bank->ipu, reg, bank->control);
 115
 116        raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 117}
 118
 119static void ipu_irq_mask(struct irq_data *d)
 120{
 121        struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
 122        struct ipu_irq_bank *bank;
 123        uint32_t reg;
 124        unsigned long lock_flags;
 125
 126        raw_spin_lock_irqsave(&bank_lock, lock_flags);
 127
 128        bank = map->bank;
 129        if (!bank) {
 130                raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 131                pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 132                return;
 133        }
 134
 135        reg = ipu_read_reg(bank->ipu, bank->control);
 136        reg &= ~(1UL << (map->source & 31));
 137        ipu_write_reg(bank->ipu, reg, bank->control);
 138
 139        raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 140}
 141
 142static void ipu_irq_ack(struct irq_data *d)
 143{
 144        struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
 145        struct ipu_irq_bank *bank;
 146        unsigned long lock_flags;
 147
 148        raw_spin_lock_irqsave(&bank_lock, lock_flags);
 149
 150        bank = map->bank;
 151        if (!bank) {
 152                raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 153                pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 154                return;
 155        }
 156
 157        ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
 158        raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 159}
 160
 161/**
 162 * ipu_irq_status() - returns the current interrupt status of the specified IRQ.
 163 * @irq:        interrupt line to get status for.
 164 * @return:     true if the interrupt is pending/asserted or false if the
 165 *              interrupt is not pending.
 166 */
 167bool ipu_irq_status(unsigned int irq)
 168{
 169        struct ipu_irq_map *map = irq_get_chip_data(irq);
 170        struct ipu_irq_bank *bank;
 171        unsigned long lock_flags;
 172        bool ret;
 173
 174        raw_spin_lock_irqsave(&bank_lock, lock_flags);
 175        bank = map->bank;
 176        ret = bank && ipu_read_reg(bank->ipu, bank->status) &
 177                (1UL << (map->source & 31));
 178        raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 179
 180        return ret;
 181}
 182
 183/**
 184 * ipu_irq_map() - map an IPU interrupt source to an IRQ number
 185 * @source:     interrupt source bit position (see below)
 186 * @return:     mapped IRQ number or negative error code
 187 *
 188 * The source parameter has to be explained further. On i.MX31 IPU has 137 IRQ
 189 * sources, they are broken down in 5 32-bit registers, like 32, 32, 24, 32, 17.
 190 * However, the source argument of this function is not the sequence number of
 191 * the possible IRQ, but rather its bit position. So, first interrupt in fourth
 192 * register has source number 96, and not 88. This makes calculations easier,
 193 * and also provides forward compatibility with any future IPU implementations
 194 * with any interrupt bit assignments.
 195 */
 196int ipu_irq_map(unsigned int source)
 197{
 198        int i, ret = -ENOMEM;
 199        struct ipu_irq_map *map;
 200
 201        might_sleep();
 202
 203        mutex_lock(&map_lock);
 204        map = src2map(source);
 205        if (map) {
 206                pr_err("IPU: Source %u already mapped to IRQ %u\n", source, map->irq);
 207                ret = -EBUSY;
 208                goto out;
 209        }
 210
 211        for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
 212                if (irq_map[i].source < 0) {
 213                        unsigned long lock_flags;
 214
 215                        raw_spin_lock_irqsave(&bank_lock, lock_flags);
 216                        irq_map[i].source = source;
 217                        irq_map[i].bank = irq_bank + source / 32;
 218                        raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 219
 220                        ret = irq_map[i].irq;
 221                        pr_debug("IPU: mapped source %u to IRQ %u\n",
 222                                 source, ret);
 223                        break;
 224                }
 225        }
 226out:
 227        mutex_unlock(&map_lock);
 228
 229        if (ret < 0)
 230                pr_err("IPU: couldn't map source %u: %d\n", source, ret);
 231
 232        return ret;
 233}
 234
 235/**
 236 * ipu_irq_map() - map an IPU interrupt source to an IRQ number
 237 * @source:     interrupt source bit position (see ipu_irq_map())
 238 * @return:     0 or negative error code
 239 */
 240int ipu_irq_unmap(unsigned int source)
 241{
 242        int i, ret = -EINVAL;
 243
 244        might_sleep();
 245
 246        mutex_lock(&map_lock);
 247        for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
 248                if (irq_map[i].source == source) {
 249                        unsigned long lock_flags;
 250
 251                        pr_debug("IPU: unmapped source %u from IRQ %u\n",
 252                                 source, irq_map[i].irq);
 253
 254                        raw_spin_lock_irqsave(&bank_lock, lock_flags);
 255                        irq_map[i].source = -EINVAL;
 256                        irq_map[i].bank = NULL;
 257                        raw_spin_unlock_irqrestore(&bank_lock, lock_flags);
 258
 259                        ret = 0;
 260                        break;
 261                }
 262        }
 263        mutex_unlock(&map_lock);
 264
 265        return ret;
 266}
 267
 268/* Chained IRQ handler for IPU function and error interrupt */
 269static void ipu_irq_handler(struct irq_desc *desc)
 270{
 271        struct ipu *ipu = irq_desc_get_handler_data(desc);
 272        u32 status;
 273        int i, line;
 274
 275        for (i = 0; i < IPU_IRQ_NR_BANKS; i++) {
 276                struct ipu_irq_bank *bank = irq_bank + i;
 277
 278                raw_spin_lock(&bank_lock);
 279                status = ipu_read_reg(ipu, bank->status);
 280                /*
 281                 * Don't think we have to clear all interrupts here, they will
 282                 * be acked by ->handle_irq() (handle_level_irq). However, we
 283                 * might want to clear unhandled interrupts after the loop...
 284                 */
 285                status &= ipu_read_reg(ipu, bank->control);
 286                raw_spin_unlock(&bank_lock);
 287                while ((line = ffs(status))) {
 288                        struct ipu_irq_map *map;
 289                        unsigned int irq;
 290
 291                        line--;
 292                        status &= ~(1UL << line);
 293
 294                        raw_spin_lock(&bank_lock);
 295                        map = src2map(32 * i + line);
 296                        if (!map) {
 297                                raw_spin_unlock(&bank_lock);
 298                                pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
 299                                       line, i);
 300                                continue;
 301                        }
 302                        irq = map->irq;
 303                        raw_spin_unlock(&bank_lock);
 304                        generic_handle_irq(irq);
 305                }
 306        }
 307}
 308
 309static struct irq_chip ipu_irq_chip = {
 310        .name           = "ipu_irq",
 311        .irq_ack        = ipu_irq_ack,
 312        .irq_mask       = ipu_irq_mask,
 313        .irq_unmask     = ipu_irq_unmask,
 314};
 315
 316/* Install the IRQ handler */
 317int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
 318{
 319        unsigned int irq, i;
 320        int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS,
 321                                       numa_node_id());
 322
 323        if (irq_base < 0)
 324                return irq_base;
 325
 326        for (i = 0; i < IPU_IRQ_NR_BANKS; i++)
 327                irq_bank[i].ipu = ipu;
 328
 329        for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
 330                int ret;
 331
 332                irq = irq_base + i;
 333                ret = irq_set_chip(irq, &ipu_irq_chip);
 334                if (ret < 0)
 335                        return ret;
 336                ret = irq_set_chip_data(irq, irq_map + i);
 337                if (ret < 0)
 338                        return ret;
 339                irq_map[i].ipu = ipu;
 340                irq_map[i].irq = irq;
 341                irq_map[i].source = -EINVAL;
 342                irq_set_handler(irq, handle_level_irq);
 343                irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
 344        }
 345
 346        irq_set_chained_handler_and_data(ipu->irq_fn, ipu_irq_handler, ipu);
 347
 348        irq_set_chained_handler_and_data(ipu->irq_err, ipu_irq_handler, ipu);
 349
 350        ipu->irq_base = irq_base;
 351
 352        return 0;
 353}
 354
 355void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
 356{
 357        unsigned int irq, irq_base;
 358
 359        irq_base = ipu->irq_base;
 360
 361        irq_set_chained_handler_and_data(ipu->irq_fn, NULL, NULL);
 362
 363        irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
 364
 365        for (irq = irq_base; irq < irq_base + CONFIG_MX3_IPU_IRQS; irq++) {
 366                irq_set_status_flags(irq, IRQ_NOREQUEST);
 367                irq_set_chip(irq, NULL);
 368                irq_set_chip_data(irq, NULL);
 369        }
 370}
 371