^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 2001 MontaVista Software Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001 Ralf Baechle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Author: Maciej W. Rozycki <macro@mips.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This file define the irq handler for MIPS CPU interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Almost all MIPS CPUs define 8 interrupt sources. They are typically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * level triggered (i.e., cannot be cleared from CPU; must be cleared from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * device).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * The first two are software interrupts (i.e. not exposed as pins) which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * may be used for IPIs in multi-threaded single-core systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * The last one is usually the CPU timer interrupt if the counter register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * is present, or for old CPUs with an external FPU by convention it's the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * FPU exception interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/irqchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/irq_cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/mipsmtregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct irq_domain *irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct irq_domain *ipi_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline void unmask_mips_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) set_c0_status(IE_SW0 << d->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) irq_enable_hazard();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static inline void mask_mips_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) clear_c0_status(IE_SW0 << d->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) irq_disable_hazard();
^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) static struct irq_chip mips_cpu_irq_controller = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .name = "MIPS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .irq_ack = mask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .irq_mask = mask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .irq_mask_ack = mask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .irq_unmask = unmask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .irq_eoi = unmask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .irq_disable = mask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .irq_enable = unmask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Basically the same as above but taking care of all the MT stuff
^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) static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned int vpflags = dvpe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) clear_c0_cause(C_SW0 << d->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) evpe(vpflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unmask_mips_irq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * While we ack the interrupt interrupts are disabled and thus we don't need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * to deal with concurrency issues. Same for mips_cpu_irq_end.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void mips_mt_cpu_irq_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int vpflags = dvpe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) clear_c0_cause(C_SW0 << d->hwirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) evpe(vpflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) mask_mips_irq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #ifdef CONFIG_GENERIC_IRQ_IPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void mips_mt_send_ipi(struct irq_data *d, unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) irq_hw_number_t hwirq = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int vpflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* We can only send IPIs to VPEs within the local core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) WARN_ON(!cpus_are_siblings(smp_processor_id(), cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) vpflags = dvpe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) settc(cpu_vpe_id(&cpu_data[cpu]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) write_vpe_c0_cause(read_vpe_c0_cause() | (C_SW0 << hwirq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) evpe(vpflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #endif /* CONFIG_GENERIC_IRQ_IPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static struct irq_chip mips_mt_cpu_irq_controller = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .name = "MIPS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .irq_startup = mips_mt_cpu_irq_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .irq_ack = mips_mt_cpu_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .irq_mask = mask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .irq_mask_ack = mips_mt_cpu_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .irq_unmask = unmask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .irq_eoi = unmask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .irq_disable = mask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .irq_enable = unmask_mips_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #ifdef CONFIG_GENERIC_IRQ_IPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .ipi_send_single = mips_mt_send_ipi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) asmlinkage void __weak plat_irq_dispatch(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) unsigned int virq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) spurious_interrupt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return;
^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) pending >>= CAUSEB_IP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) while (pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) irq = fls(pending) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (IS_ENABLED(CONFIG_GENERIC_IRQ_IPI) && irq < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) virq = irq_linear_revmap(ipi_domain, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) virq = irq_linear_revmap(irq_domain, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) do_IRQ(virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) pending &= ~BIT(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^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) static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct irq_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (hw < 2 && cpu_has_mipsmt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* Software interrupts are used for MT/CMT IPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) chip = &mips_mt_cpu_irq_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) chip = &mips_cpu_irq_controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (cpu_has_vint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) set_vi_handler(hw, plat_irq_dispatch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .map = mips_cpu_intc_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .xlate = irq_domain_xlate_onecell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #ifdef CONFIG_GENERIC_IRQ_IPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct cpu_ipi_domain_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) DECLARE_BITMAP(allocated, 2);
^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) static int mips_cpu_ipi_alloc(struct irq_domain *domain, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned int nr_irqs, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct cpu_ipi_domain_state *state = domain->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int i, hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) for (i = 0; i < nr_irqs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) hwirq = find_first_zero_bit(state->allocated, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (hwirq == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) bitmap_set(state->allocated, hwirq, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ret = irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) &mips_mt_cpu_irq_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = irq_domain_set_hwirq_and_chip(domain->parent, virq + i, hwirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) &mips_mt_cpu_irq_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ret = irq_set_irq_type(virq + i, IRQ_TYPE_LEVEL_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int mips_cpu_ipi_match(struct irq_domain *d, struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) enum irq_domain_bus_token bus_token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bool is_ipi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) switch (bus_token) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case DOMAIN_BUS_IPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) is_ipi = d->bus_token == bus_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return (!node || (to_of_node(d->fwnode) == node)) && is_ipi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static const struct irq_domain_ops mips_cpu_ipi_chip_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .alloc = mips_cpu_ipi_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .match = mips_cpu_ipi_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void mips_cpu_register_ipi_domain(struct device_node *of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct cpu_ipi_domain_state *ipi_domain_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ipi_domain_state = kzalloc(sizeof(*ipi_domain_state), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ipi_domain = irq_domain_add_hierarchy(irq_domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) IRQ_DOMAIN_FLAG_IPI_SINGLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 2, of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) &mips_cpu_ipi_chip_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ipi_domain_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!ipi_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) panic("Failed to add MIPS CPU IPI domain");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #else /* !CONFIG_GENERIC_IRQ_IPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static inline void mips_cpu_register_ipi_domain(struct device_node *of_node) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #endif /* !CONFIG_GENERIC_IRQ_IPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static void __init __mips_cpu_irq_init(struct device_node *of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* Mask interrupts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) clear_c0_status(ST0_IM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) clear_c0_cause(CAUSEF_IP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) irq_domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) &mips_cpu_intc_irq_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (!irq_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) panic("Failed to add irqdomain for MIPS CPU");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Only proceed to register the software interrupt IPI implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * for CPUs which implement the MIPS MT (multi-threading) ASE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (cpu_has_mipsmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) mips_cpu_register_ipi_domain(of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) void __init mips_cpu_irq_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) __mips_cpu_irq_init(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int __init mips_cpu_irq_of_init(struct device_node *of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) __mips_cpu_irq_init(of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init);