^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2004 MIPS Inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: chris@mips.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel_stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/msc01_ic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static unsigned long _icctrl_msc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define MSC01_IC_REG_BASE _icctrl_msc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define MSCIC_WRITE(reg, data) do { *(volatile u32 *)(reg) = data; } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MSCIC_READ(reg, data) do { data = *(volatile u32 *)(reg); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static unsigned int irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* mask off an interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static inline void mask_msc_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned int irq = d->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (irq < (irq_base + 32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32));
^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) /* unmask an interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static inline void unmask_msc_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned int irq = d->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (irq < (irq_base + 32))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Masks and ACKs an IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void level_mask_and_ack_msc_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) mask_msc_irq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!cpu_has_veic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) MSCIC_WRITE(MSC01_IC_EOI, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^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) * Masks and ACKs an IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static void edge_mask_and_ack_msc_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int irq = d->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) mask_msc_irq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!cpu_has_veic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) MSCIC_WRITE(MSC01_IC_EOI, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MSCIC_READ(MSC01_IC_SUP+irq*8, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Interrupt handler for interrupts coming from SOC-it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void ll_msc_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* read the interrupt vector register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) MSCIC_READ(MSC01_IC_VEC, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (irq < 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) do_IRQ(irq + irq_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* Ignore spurious interrupt */
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static void msc_bind_eic_interrupt(int irq, int set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) MSCIC_WRITE(MSC01_IC_RAMW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static struct irq_chip msc_levelirq_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .name = "SOC-it-Level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .irq_ack = level_mask_and_ack_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .irq_mask = mask_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .irq_mask_ack = level_mask_and_ack_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .irq_unmask = unmask_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .irq_eoi = unmask_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static struct irq_chip msc_edgeirq_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .name = "SOC-it-Edge",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .irq_ack = edge_mask_and_ack_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .irq_mask = mask_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .irq_mask_ack = edge_mask_and_ack_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .irq_unmask = unmask_msc_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .irq_eoi = unmask_msc_irq,
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) _icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Reset interrupt controller - initialises all registers to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) board_bind_eic_interrupt = &msc_bind_eic_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) for (; nirq > 0; nirq--, imp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int n = imp->im_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) switch (imp->im_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case MSC01_IRQ_EDGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) irq_set_chip_and_handler_name(irqbase + n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) &msc_edgeirq_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) handle_edge_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) "edge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (cpu_has_veic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case MSC01_IRQ_LEVEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) irq_set_chip_and_handler_name(irqbase + n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) &msc_levelirq_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) handle_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "level");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (cpu_has_veic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) irq_base = irqbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT); /* Enable interrupt generation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }