Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2001 MontaVista Software Inc.
0004  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
0005  *
0006  * Copyright (C) 2001 Ralf Baechle
0007  * Copyright (C) 2005  MIPS Technologies, Inc.  All rights reserved.
0008  *  Author: Maciej W. Rozycki <macro@mips.com>
0009  *
0010  * This file define the irq handler for MIPS CPU interrupts.
0011  */
0012 
0013 /*
0014  * Almost all MIPS CPUs define 8 interrupt sources.  They are typically
0015  * level triggered (i.e., cannot be cleared from CPU; must be cleared from
0016  * device).
0017  *
0018  * The first two are software interrupts (i.e. not exposed as pins) which
0019  * may be used for IPIs in multi-threaded single-core systems.
0020  *
0021  * The last one is usually the CPU timer interrupt if the counter register
0022  * is present, or for old CPUs with an external FPU by convention it's the
0023  * FPU exception interrupt.
0024  */
0025 #include <linux/init.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/kernel.h>
0028 #include <linux/irq.h>
0029 #include <linux/irqchip.h>
0030 #include <linux/irqdomain.h>
0031 
0032 #include <asm/irq_cpu.h>
0033 #include <asm/mipsregs.h>
0034 #include <asm/mipsmtregs.h>
0035 #include <asm/setup.h>
0036 
0037 static struct irq_domain *irq_domain;
0038 static struct irq_domain *ipi_domain;
0039 
0040 static inline void unmask_mips_irq(struct irq_data *d)
0041 {
0042     set_c0_status(IE_SW0 << d->hwirq);
0043     irq_enable_hazard();
0044 }
0045 
0046 static inline void mask_mips_irq(struct irq_data *d)
0047 {
0048     clear_c0_status(IE_SW0 << d->hwirq);
0049     irq_disable_hazard();
0050 }
0051 
0052 static struct irq_chip mips_cpu_irq_controller = {
0053     .name       = "MIPS",
0054     .irq_ack    = mask_mips_irq,
0055     .irq_mask   = mask_mips_irq,
0056     .irq_mask_ack   = mask_mips_irq,
0057     .irq_unmask = unmask_mips_irq,
0058     .irq_eoi    = unmask_mips_irq,
0059     .irq_disable    = mask_mips_irq,
0060     .irq_enable = unmask_mips_irq,
0061 };
0062 
0063 /*
0064  * Basically the same as above but taking care of all the MT stuff
0065  */
0066 
0067 static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
0068 {
0069     unsigned int vpflags = dvpe();
0070 
0071     clear_c0_cause(C_SW0 << d->hwirq);
0072     evpe(vpflags);
0073     unmask_mips_irq(d);
0074     return 0;
0075 }
0076 
0077 /*
0078  * While we ack the interrupt interrupts are disabled and thus we don't need
0079  * to deal with concurrency issues.  Same for mips_cpu_irq_end.
0080  */
0081 static void mips_mt_cpu_irq_ack(struct irq_data *d)
0082 {
0083     unsigned int vpflags = dvpe();
0084     clear_c0_cause(C_SW0 << d->hwirq);
0085     evpe(vpflags);
0086     mask_mips_irq(d);
0087 }
0088 
0089 #ifdef CONFIG_GENERIC_IRQ_IPI
0090 
0091 static void mips_mt_send_ipi(struct irq_data *d, unsigned int cpu)
0092 {
0093     irq_hw_number_t hwirq = irqd_to_hwirq(d);
0094     unsigned long flags;
0095     int vpflags;
0096 
0097     local_irq_save(flags);
0098 
0099     /* We can only send IPIs to VPEs within the local core */
0100     WARN_ON(!cpus_are_siblings(smp_processor_id(), cpu));
0101 
0102     vpflags = dvpe();
0103     settc(cpu_vpe_id(&cpu_data[cpu]));
0104     write_vpe_c0_cause(read_vpe_c0_cause() | (C_SW0 << hwirq));
0105     evpe(vpflags);
0106 
0107     local_irq_restore(flags);
0108 }
0109 
0110 #endif /* CONFIG_GENERIC_IRQ_IPI */
0111 
0112 static struct irq_chip mips_mt_cpu_irq_controller = {
0113     .name       = "MIPS",
0114     .irq_startup    = mips_mt_cpu_irq_startup,
0115     .irq_ack    = mips_mt_cpu_irq_ack,
0116     .irq_mask   = mask_mips_irq,
0117     .irq_mask_ack   = mips_mt_cpu_irq_ack,
0118     .irq_unmask = unmask_mips_irq,
0119     .irq_eoi    = unmask_mips_irq,
0120     .irq_disable    = mask_mips_irq,
0121     .irq_enable = unmask_mips_irq,
0122 #ifdef CONFIG_GENERIC_IRQ_IPI
0123     .ipi_send_single = mips_mt_send_ipi,
0124 #endif
0125 };
0126 
0127 asmlinkage void __weak plat_irq_dispatch(void)
0128 {
0129     unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
0130     int irq;
0131 
0132     if (!pending) {
0133         spurious_interrupt();
0134         return;
0135     }
0136 
0137     pending >>= CAUSEB_IP;
0138     while (pending) {
0139         struct irq_domain *d;
0140 
0141         irq = fls(pending) - 1;
0142         if (IS_ENABLED(CONFIG_GENERIC_IRQ_IPI) && irq < 2)
0143             d = ipi_domain;
0144         else
0145             d = irq_domain;
0146 
0147         do_domain_IRQ(d, irq);
0148         pending &= ~BIT(irq);
0149     }
0150 }
0151 
0152 static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
0153                  irq_hw_number_t hw)
0154 {
0155     struct irq_chip *chip;
0156 
0157     if (hw < 2 && cpu_has_mipsmt) {
0158         /* Software interrupts are used for MT/CMT IPI */
0159         chip = &mips_mt_cpu_irq_controller;
0160     } else {
0161         chip = &mips_cpu_irq_controller;
0162     }
0163 
0164     if (cpu_has_vint)
0165         set_vi_handler(hw, plat_irq_dispatch);
0166 
0167     irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
0168 
0169     return 0;
0170 }
0171 
0172 static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
0173     .map = mips_cpu_intc_map,
0174     .xlate = irq_domain_xlate_onecell,
0175 };
0176 
0177 #ifdef CONFIG_GENERIC_IRQ_IPI
0178 
0179 struct cpu_ipi_domain_state {
0180     DECLARE_BITMAP(allocated, 2);
0181 };
0182 
0183 static int mips_cpu_ipi_alloc(struct irq_domain *domain, unsigned int virq,
0184                   unsigned int nr_irqs, void *arg)
0185 {
0186     struct cpu_ipi_domain_state *state = domain->host_data;
0187     unsigned int i, hwirq;
0188     int ret;
0189 
0190     for (i = 0; i < nr_irqs; i++) {
0191         hwirq = find_first_zero_bit(state->allocated, 2);
0192         if (hwirq == 2)
0193             return -EBUSY;
0194         bitmap_set(state->allocated, hwirq, 1);
0195 
0196         ret = irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq,
0197                             &mips_mt_cpu_irq_controller,
0198                             NULL);
0199         if (ret)
0200             return ret;
0201 
0202         ret = irq_domain_set_hwirq_and_chip(domain->parent, virq + i, hwirq,
0203                             &mips_mt_cpu_irq_controller,
0204                             NULL);
0205 
0206         if (ret)
0207             return ret;
0208 
0209         ret = irq_set_irq_type(virq + i, IRQ_TYPE_LEVEL_HIGH);
0210         if (ret)
0211             return ret;
0212     }
0213 
0214     return 0;
0215 }
0216 
0217 static int mips_cpu_ipi_match(struct irq_domain *d, struct device_node *node,
0218                   enum irq_domain_bus_token bus_token)
0219 {
0220     bool is_ipi;
0221 
0222     switch (bus_token) {
0223     case DOMAIN_BUS_IPI:
0224         is_ipi = d->bus_token == bus_token;
0225         return (!node || (to_of_node(d->fwnode) == node)) && is_ipi;
0226     default:
0227         return 0;
0228     }
0229 }
0230 
0231 static const struct irq_domain_ops mips_cpu_ipi_chip_ops = {
0232     .alloc  = mips_cpu_ipi_alloc,
0233     .match  = mips_cpu_ipi_match,
0234 };
0235 
0236 static void mips_cpu_register_ipi_domain(struct device_node *of_node)
0237 {
0238     struct cpu_ipi_domain_state *ipi_domain_state;
0239 
0240     ipi_domain_state = kzalloc(sizeof(*ipi_domain_state), GFP_KERNEL);
0241     ipi_domain = irq_domain_add_hierarchy(irq_domain,
0242                           IRQ_DOMAIN_FLAG_IPI_SINGLE,
0243                           2, of_node,
0244                           &mips_cpu_ipi_chip_ops,
0245                           ipi_domain_state);
0246     if (!ipi_domain)
0247         panic("Failed to add MIPS CPU IPI domain");
0248     irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);
0249 }
0250 
0251 #else /* !CONFIG_GENERIC_IRQ_IPI */
0252 
0253 static inline void mips_cpu_register_ipi_domain(struct device_node *of_node) {}
0254 
0255 #endif /* !CONFIG_GENERIC_IRQ_IPI */
0256 
0257 static void __init __mips_cpu_irq_init(struct device_node *of_node)
0258 {
0259     /* Mask interrupts. */
0260     clear_c0_status(ST0_IM);
0261     clear_c0_cause(CAUSEF_IP);
0262 
0263     irq_domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
0264                        &mips_cpu_intc_irq_domain_ops,
0265                        NULL);
0266     if (!irq_domain)
0267         panic("Failed to add irqdomain for MIPS CPU");
0268 
0269     /*
0270      * Only proceed to register the software interrupt IPI implementation
0271      * for CPUs which implement the MIPS MT (multi-threading) ASE.
0272      */
0273     if (cpu_has_mipsmt)
0274         mips_cpu_register_ipi_domain(of_node);
0275 }
0276 
0277 void __init mips_cpu_irq_init(void)
0278 {
0279     __mips_cpu_irq_init(NULL);
0280 }
0281 
0282 int __init mips_cpu_irq_of_init(struct device_node *of_node,
0283                 struct device_node *parent)
0284 {
0285     __mips_cpu_irq_init(of_node);
0286     return 0;
0287 }
0288 IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init);