^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This software is available to you under a choice of one of two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * licenses. You may choose to be licensed under the terms of the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * General Public License (GPL) Version 2, available from the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * COPYING in the main directory of this source tree, or the NetLogic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * license below:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * 1. Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * 2. Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * notice, this list of conditions and the following disclaimer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <asm/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <asm/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/thread_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <asm/netlogic/mips-extns.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <asm/netlogic/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <asm/netlogic/haldefs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <asm/netlogic/common.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #if defined(CONFIG_CPU_XLP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <asm/netlogic/xlp-hal/iomap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <asm/netlogic/xlp-hal/xlp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <asm/netlogic/xlp-hal/pic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #elif defined(CONFIG_CPU_XLR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <asm/netlogic/xlr/iomap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <asm/netlogic/xlr/pic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <asm/netlogic/xlr/fmn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #error "Unknown CPU"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define SMP_IRQ_MASK ((1ULL << IRQ_IPI_SMP_FUNCTION) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) (1ULL << IRQ_IPI_SMP_RESCHEDULE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define SMP_IRQ_MASK 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define PERCPU_IRQ_MASK (SMP_IRQ_MASK | (1ull << IRQ_TIMER) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) (1ull << IRQ_FMN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct nlm_pic_irq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void (*extra_ack)(struct irq_data *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct nlm_soc_info *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int picirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int irt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static void xlp_pic_enable(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) BUG_ON(!pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) spin_lock_irqsave(&pd->node->piclock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) nlm_pic_enable_irt(pd->node->picbase, pd->irt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) spin_unlock_irqrestore(&pd->node->piclock, flags);
^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 void xlp_pic_disable(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) BUG_ON(!pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) spin_lock_irqsave(&pd->node->piclock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) nlm_pic_disable_irt(pd->node->picbase, pd->irt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) spin_unlock_irqrestore(&pd->node->piclock, flags);
^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) static void xlp_pic_mask_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) clear_c0_eimr(pd->picirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ack_c0_eirr(pd->picirq);
^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) static void xlp_pic_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct nlm_pic_irq *pd = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) BUG_ON(!pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (pd->extra_ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) pd->extra_ack(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* re-enable the intr on this cpu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) set_c0_eimr(pd->picirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Ack is a single write, no need to lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) nlm_pic_ack(pd->node->picbase, pd->irt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static struct irq_chip xlp_pic = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .name = "XLP-PIC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .irq_enable = xlp_pic_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .irq_disable = xlp_pic_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .irq_mask_ack = xlp_pic_mask_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .irq_unmask = xlp_pic_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static void cpuintr_disable(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) clear_c0_eimr(d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void cpuintr_enable(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) set_c0_eimr(d->irq);
^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) static void cpuintr_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ack_c0_eirr(d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * Chip definition for CPU originated interrupts(timer, msg) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * IPIs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct irq_chip nlm_cpu_intr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .name = "XLP-CPU-INTR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .irq_enable = cpuintr_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .irq_disable = cpuintr_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .irq_mask = cpuintr_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .irq_ack = cpuintr_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .irq_eoi = cpuintr_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void __init nlm_init_percpu_irqs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) for (i = 0; i < PIC_IRT_FIRST_IRQ; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) irq_set_chip_and_handler(i, &nlm_cpu_intr, handle_percpu_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) irq_set_chip_and_handler(IRQ_IPI_SMP_FUNCTION, &nlm_cpu_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) nlm_smp_function_ipi_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) irq_set_chip_and_handler(IRQ_IPI_SMP_RESCHEDULE, &nlm_cpu_intr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) nlm_smp_resched_ipi_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) void nlm_setup_pic_irq(int node, int picirq, int irq, int irt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct nlm_pic_irq *pic_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int xirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) xirq = nlm_irq_to_xirq(node, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) pic_data = kzalloc(sizeof(*pic_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) BUG_ON(pic_data == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) pic_data->irt = irt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) pic_data->picirq = picirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) pic_data->node = nlm_get_node(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) irq_set_chip_and_handler(xirq, &xlp_pic, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) irq_set_chip_data(xirq, pic_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct nlm_pic_irq *pic_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int xirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) xirq = nlm_irq_to_xirq(node, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pic_data = irq_get_chip_data(xirq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (WARN_ON(!pic_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pic_data->extra_ack = xack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static void nlm_init_node_irqs(int node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct nlm_soc_info *nodep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int i, irt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) pr_info("Init IRQ for node %d\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) nodep = nlm_get_node(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) nodep->irqmask = PERCPU_IRQ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) irt = nlm_irq_to_irt(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (irt == -1) /* unused irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) nodep->irqmask |= 1ull << i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (irt == -2) /* not a direct PIC irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) nlm_pic_init_irt(nodep->picbase, irt, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) node * nlm_threads_per_node(), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) nlm_setup_pic_irq(node, i, i, irt);
^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) void nlm_smp_irq_init(int hwtid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int cpu, node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) cpu = hwtid % nlm_threads_per_node();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) node = hwtid / nlm_threads_per_node();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (cpu == 0 && node != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) nlm_init_node_irqs(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) write_c0_eimr(nlm_get_node(node)->irqmask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) asmlinkage void plat_irq_dispatch(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) uint64_t eirr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int i, node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) node = nlm_nodeid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) eirr = read_c0_eirr_and_eimr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (eirr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) i = __ffs64(eirr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* per-CPU IRQs don't need translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (i < PIC_IRQ_BASE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) do_IRQ(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) #if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* PCI interrupts need a second level dispatch for MSI bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) nlm_dispatch_msi(node, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) nlm_dispatch_msix(node, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* top level irq handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) do_IRQ(nlm_irq_to_xirq(node, i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) #ifdef CONFIG_CPU_XLP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static const struct irq_domain_ops xlp_pic_irq_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .xlate = irq_domain_xlate_onetwocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int __init xlp_of_pic_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct irq_domain *xlp_pic_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int socid, ret, bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* we need a hack to get the PIC's SoC chip id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ret = of_address_to_resource(node, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) pr_err("PIC %pOFn: reg property not found!\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (cpu_is_xlp9xx()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) bus = (res.start >> 20) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) for (socid = 0; socid < NLM_NR_NODES; socid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!nlm_node_present(socid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (nlm_get_node(socid)->socbus == bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (socid == NLM_NR_NODES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) pr_err("PIC %pOFn: Node mapping for bus %d not found!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) node, bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) socid = (res.start >> 18) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!nlm_node_present(socid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pr_err("PIC %pOFn: node %d does not exist!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) node, socid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (!nlm_node_present(socid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) pr_err("PIC %pOFn: node %d does not exist!\n", node, socid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) &xlp_pic_irq_domain_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (xlp_pic_domain == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) pr_err("PIC %pOFn: Creating legacy domain failed!\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) pr_info("Node %d: IRQ domain created for PIC@%pR\n", socid, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static struct of_device_id __initdata xlp_pic_irq_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) { .compatible = "netlogic,xlp-pic", .data = xlp_of_pic_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) void __init arch_init_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* Initialize the irq descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) nlm_init_percpu_irqs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) nlm_init_node_irqs(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) write_c0_eimr(nlm_current_node()->irqmask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #if defined(CONFIG_CPU_XLR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) nlm_setup_fmn_irq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) #ifdef CONFIG_CPU_XLP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) of_irq_init(xlp_pic_irq_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }