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