^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) * Copyright (C) 2011-2012 Texas Instruments Incorporated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This borrows heavily from powerpc version, which is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Derived from arch/i386/kernel/irq.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 1992 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Adapted from arch/i386 by Gary Thomas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Updated and modified by Cort Dougan <cort@fsmlabs.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 1996-2001 Cort Dougan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Adapted for Power Macintosh by Paul Mackerras
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/radix-tree.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/kernel_stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/megamod-pic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/special_insns.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long irq_err_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static DEFINE_RAW_SPINLOCK(core_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void mask_core_irq(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned int prio = data->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) raw_spin_lock(&core_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) and_creg(IER, ~(1 << prio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) raw_spin_unlock(&core_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void unmask_core_irq(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned int prio = data->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) raw_spin_lock(&core_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) or_creg(IER, 1 << prio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) raw_spin_unlock(&core_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static struct irq_chip core_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .name = "core",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .irq_mask = mask_core_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .irq_unmask = unmask_core_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int prio_to_virq[NR_PRIORITY_IRQS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct pt_regs *old_regs = set_irq_regs(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) irq_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) generic_handle_irq(prio_to_virq[prio]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) irq_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) set_irq_regs(old_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static struct irq_domain *core_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int core_domain_map(struct irq_domain *h, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (hw < 4 || hw >= NR_PRIORITY_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) prio_to_virq[hw] = virq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) irq_set_status_flags(virq, IRQ_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) irq_set_chip_and_handler(virq, &core_chip, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const struct irq_domain_ops core_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .map = core_domain_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .xlate = irq_domain_xlate_onecell,
^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) void __init init_IRQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* Mask all priority IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) and_creg(IER, ~0xfff0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) np = of_find_compatible_node(NULL, NULL, "ti,c64x+core-pic");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (np != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* create the core host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) core_domain = irq_domain_add_linear(np, NR_PRIORITY_IRQS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) &core_domain_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (core_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) irq_set_default_host(core_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) printk(KERN_INFO "Core interrupt controller initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* now we're ready for other SoC controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) megamod_pic_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Clear all general IRQ flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) set_creg(ICR, 0xfff0);
^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 ack_bad_irq(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) irq_err_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int arch_show_interrupts(struct seq_file *p, int prec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }