^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * intc.c -- support for the old ColdFire interrupt controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/coldfire.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/mcfsim.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * The mapping of irq number to a mask register bit is not one-to-one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The irq numbers are either based on "level" of interrupt or fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * for an autovector-able interrupt. So we keep a local data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * that maps from irq to mask register. Not all interrupts will have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * an IMR bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned char mcf_irq2imr[NR_IRQS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Define the miniumun and maximum external interrupt numbers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * This is also used as the "level" interrupt numbers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define EIRQ1 25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define EIRQ7 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * In the early version 2 core ColdFire parts the IMR register was 16 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * in size. Version 3 (and later version 2) core parts have a 32 bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * sized IMR register. Provide some size independent methods to access the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * IMR register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifdef MCFSIM_IMR_IS_16BITS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void mcf_setimr(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u16 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) imr = __raw_readw(MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) __raw_writew(imr | (0x1 << index), MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void mcf_clrimr(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u16 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) imr = __raw_readw(MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __raw_writew(imr & ~(0x1 << index), MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) void mcf_maskimr(unsigned int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u16 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) imr = __raw_readw(MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) imr |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) __raw_writew(imr, MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) void mcf_setimr(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u32 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) imr = __raw_readl(MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) __raw_writel(imr | (0x1 << index), MCFSIM_IMR);
^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) void mcf_clrimr(int index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) imr = __raw_readl(MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) __raw_writel(imr & ~(0x1 << index), MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) void mcf_maskimr(unsigned int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u32 imr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) imr = __raw_readl(MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) imr |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) __raw_writel(imr, MCFSIM_IMR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Interrupts can be "vectored" on the ColdFire cores that support this old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * interrupt controller. That is, the device raising the interrupt can also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * supply the vector number to interrupt through. The AVR register of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * interrupt controller enables or disables this for each external interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * so provide generic support for this. Setting this up is out-of-band for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * the interrupt system API's, and needs to be done by the driver that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * supports this device. Very few devices actually use this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void mcf_autovector(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #ifdef MCFSIM_AVR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if ((irq >= EIRQ1) && (irq <= EIRQ7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 avec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) avec = __raw_readb(MCFSIM_AVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) avec |= (0x1 << (irq - EIRQ1 + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) __raw_writeb(avec, MCFSIM_AVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void intc_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (mcf_irq2imr[d->irq])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mcf_setimr(mcf_irq2imr[d->irq]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void intc_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (mcf_irq2imr[d->irq])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mcf_clrimr(mcf_irq2imr[d->irq]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int intc_irq_set_type(struct irq_data *d, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static struct irq_chip intc_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .name = "CF-INTC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .irq_mask = intc_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .irq_unmask = intc_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .irq_set_type = intc_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) void __init init_IRQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) mcf_maskimr(0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) for (irq = 0; (irq < NR_IRQS); irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) irq_set_chip(irq, &intc_irq_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) irq_set_handler(irq, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)