Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Marvell Armada 370 and Armada XP SoC IRQ handling
0003  *
0004  * Copyright (C) 2012 Marvell
0005  *
0006  * Lior Amsalem <alior@marvell.com>
0007  * Gregory CLEMENT <gregory.clement@free-electrons.com>
0008  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
0009  * Ben Dooks <ben.dooks@codethink.co.uk>
0010  *
0011  * This file is licensed under the terms of the GNU General Public
0012  * License version 2.  This program is licensed "as is" without any
0013  * warranty of any kind, whether express or implied.
0014  */
0015 
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/init.h>
0019 #include <linux/irq.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/irqchip.h>
0022 #include <linux/irqchip/chained_irq.h>
0023 #include <linux/cpu.h>
0024 #include <linux/io.h>
0025 #include <linux/of_address.h>
0026 #include <linux/of_irq.h>
0027 #include <linux/of_pci.h>
0028 #include <linux/irqdomain.h>
0029 #include <linux/slab.h>
0030 #include <linux/syscore_ops.h>
0031 #include <linux/msi.h>
0032 #include <asm/mach/arch.h>
0033 #include <asm/exception.h>
0034 #include <asm/smp_plat.h>
0035 #include <asm/mach/irq.h>
0036 
0037 /*
0038  * Overall diagram of the Armada XP interrupt controller:
0039  *
0040  *    To CPU 0                 To CPU 1
0041  *
0042  *       /\                       /\
0043  *       ||                       ||
0044  * +---------------+     +---------------+
0045  * |               |     |               |
0046  * |    per-CPU    |     |    per-CPU    |
0047  * |  mask/unmask  |     |  mask/unmask  |
0048  * |     CPU0      |     |     CPU1      |
0049  * |               |     |               |
0050  * +---------------+     +---------------+
0051  *        /\                       /\
0052  *        ||                       ||
0053  *        \\_______________________//
0054  *                     ||
0055  *            +-------------------+
0056  *            |                   |
0057  *            | Global interrupt  |
0058  *            |    mask/unmask    |
0059  *            |                   |
0060  *            +-------------------+
0061  *                     /\
0062  *                     ||
0063  *               interrupt from
0064  *                   device
0065  *
0066  * The "global interrupt mask/unmask" is modified using the
0067  * ARMADA_370_XP_INT_SET_ENABLE_OFFS and
0068  * ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS registers, which are relative
0069  * to "main_int_base".
0070  *
0071  * The "per-CPU mask/unmask" is modified using the
0072  * ARMADA_370_XP_INT_SET_MASK_OFFS and
0073  * ARMADA_370_XP_INT_CLEAR_MASK_OFFS registers, which are relative to
0074  * "per_cpu_int_base". This base address points to a special address,
0075  * which automatically accesses the registers of the current CPU.
0076  *
0077  * The per-CPU mask/unmask can also be adjusted using the global
0078  * per-interrupt ARMADA_370_XP_INT_SOURCE_CTL register, which we use
0079  * to configure interrupt affinity.
0080  *
0081  * Due to this model, all interrupts need to be mask/unmasked at two
0082  * different levels: at the global level and at the per-CPU level.
0083  *
0084  * This driver takes the following approach to deal with this:
0085  *
0086  *  - For global interrupts:
0087  *
0088  *    At ->map() time, a global interrupt is unmasked at the per-CPU
0089  *    mask/unmask level. It is therefore unmasked at this level for
0090  *    the current CPU, running the ->map() code. This allows to have
0091  *    the interrupt unmasked at this level in non-SMP
0092  *    configurations. In SMP configurations, the ->set_affinity()
0093  *    callback is called, which using the
0094  *    ARMADA_370_XP_INT_SOURCE_CTL() readjusts the per-CPU mask/unmask
0095  *    for the interrupt.
0096  *
0097  *    The ->mask() and ->unmask() operations only mask/unmask the
0098  *    interrupt at the "global" level.
0099  *
0100  *    So, a global interrupt is enabled at the per-CPU level as soon
0101  *    as it is mapped. At run time, the masking/unmasking takes place
0102  *    at the global level.
0103  *
0104  *  - For per-CPU interrupts
0105  *
0106  *    At ->map() time, a per-CPU interrupt is unmasked at the global
0107  *    mask/unmask level.
0108  *
0109  *    The ->mask() and ->unmask() operations mask/unmask the interrupt
0110  *    at the per-CPU level.
0111  *
0112  *    So, a per-CPU interrupt is enabled at the global level as soon
0113  *    as it is mapped. At run time, the masking/unmasking takes place
0114  *    at the per-CPU level.
0115  */
0116 
0117 /* Registers relative to main_int_base */
0118 #define ARMADA_370_XP_INT_CONTROL       (0x00)
0119 #define ARMADA_370_XP_SW_TRIG_INT_OFFS      (0x04)
0120 #define ARMADA_370_XP_INT_SET_ENABLE_OFFS   (0x30)
0121 #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
0122 #define ARMADA_370_XP_INT_SOURCE_CTL(irq)   (0x100 + irq*4)
0123 #define ARMADA_370_XP_INT_SOURCE_CPU_MASK   0xF
0124 #define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid)   ((BIT(0) | BIT(8)) << cpuid)
0125 
0126 /* Registers relative to per_cpu_int_base */
0127 #define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS   (0x08)
0128 #define ARMADA_370_XP_IN_DRBEL_MSK_OFFS     (0x0c)
0129 #define ARMADA_375_PPI_CAUSE            (0x10)
0130 #define ARMADA_370_XP_CPU_INTACK_OFFS       (0x44)
0131 #define ARMADA_370_XP_INT_SET_MASK_OFFS     (0x48)
0132 #define ARMADA_370_XP_INT_CLEAR_MASK_OFFS   (0x4C)
0133 #define ARMADA_370_XP_INT_FABRIC_MASK_OFFS  (0x54)
0134 #define ARMADA_370_XP_INT_CAUSE_PERF(cpu)   (1 << cpu)
0135 
0136 #define ARMADA_370_XP_MAX_PER_CPU_IRQS      (28)
0137 
0138 #define IPI_DOORBELL_START                      (0)
0139 #define IPI_DOORBELL_END                        (8)
0140 #define IPI_DOORBELL_MASK                       0xFF
0141 #define PCI_MSI_DOORBELL_START                  (16)
0142 #define PCI_MSI_DOORBELL_NR                     (16)
0143 #define PCI_MSI_DOORBELL_END                    (32)
0144 #define PCI_MSI_DOORBELL_MASK                   0xFFFF0000
0145 
0146 static void __iomem *per_cpu_int_base;
0147 static void __iomem *main_int_base;
0148 static struct irq_domain *armada_370_xp_mpic_domain;
0149 static u32 doorbell_mask_reg;
0150 static int parent_irq;
0151 #ifdef CONFIG_PCI_MSI
0152 static struct irq_domain *armada_370_xp_msi_domain;
0153 static struct irq_domain *armada_370_xp_msi_inner_domain;
0154 static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
0155 static DEFINE_MUTEX(msi_used_lock);
0156 static phys_addr_t msi_doorbell_addr;
0157 #endif
0158 
0159 static inline bool is_percpu_irq(irq_hw_number_t irq)
0160 {
0161     if (irq <= ARMADA_370_XP_MAX_PER_CPU_IRQS)
0162         return true;
0163 
0164     return false;
0165 }
0166 
0167 /*
0168  * In SMP mode:
0169  * For shared global interrupts, mask/unmask global enable bit
0170  * For CPU interrupts, mask/unmask the calling CPU's bit
0171  */
0172 static void armada_370_xp_irq_mask(struct irq_data *d)
0173 {
0174     irq_hw_number_t hwirq = irqd_to_hwirq(d);
0175 
0176     if (!is_percpu_irq(hwirq))
0177         writel(hwirq, main_int_base +
0178                 ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
0179     else
0180         writel(hwirq, per_cpu_int_base +
0181                 ARMADA_370_XP_INT_SET_MASK_OFFS);
0182 }
0183 
0184 static void armada_370_xp_irq_unmask(struct irq_data *d)
0185 {
0186     irq_hw_number_t hwirq = irqd_to_hwirq(d);
0187 
0188     if (!is_percpu_irq(hwirq))
0189         writel(hwirq, main_int_base +
0190                 ARMADA_370_XP_INT_SET_ENABLE_OFFS);
0191     else
0192         writel(hwirq, per_cpu_int_base +
0193                 ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0194 }
0195 
0196 #ifdef CONFIG_PCI_MSI
0197 
0198 static struct irq_chip armada_370_xp_msi_irq_chip = {
0199     .name = "MPIC MSI",
0200     .irq_mask = pci_msi_mask_irq,
0201     .irq_unmask = pci_msi_unmask_irq,
0202 };
0203 
0204 static struct msi_domain_info armada_370_xp_msi_domain_info = {
0205     .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
0206            MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
0207     .chip   = &armada_370_xp_msi_irq_chip,
0208 };
0209 
0210 static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
0211 {
0212     unsigned int cpu = cpumask_first(irq_data_get_effective_affinity_mask(data));
0213 
0214     msg->address_lo = lower_32_bits(msi_doorbell_addr);
0215     msg->address_hi = upper_32_bits(msi_doorbell_addr);
0216     msg->data = BIT(cpu + 8) | (data->hwirq + PCI_MSI_DOORBELL_START);
0217 }
0218 
0219 static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data,
0220                       const struct cpumask *mask, bool force)
0221 {
0222     unsigned int cpu;
0223 
0224     if (!force)
0225         cpu = cpumask_any_and(mask, cpu_online_mask);
0226     else
0227         cpu = cpumask_first(mask);
0228 
0229     if (cpu >= nr_cpu_ids)
0230         return -EINVAL;
0231 
0232     irq_data_update_effective_affinity(irq_data, cpumask_of(cpu));
0233 
0234     return IRQ_SET_MASK_OK;
0235 }
0236 
0237 static struct irq_chip armada_370_xp_msi_bottom_irq_chip = {
0238     .name           = "MPIC MSI",
0239     .irq_compose_msi_msg    = armada_370_xp_compose_msi_msg,
0240     .irq_set_affinity   = armada_370_xp_msi_set_affinity,
0241 };
0242 
0243 static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq,
0244                    unsigned int nr_irqs, void *args)
0245 {
0246     int hwirq, i;
0247 
0248     mutex_lock(&msi_used_lock);
0249     hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR,
0250                     order_base_2(nr_irqs));
0251     mutex_unlock(&msi_used_lock);
0252 
0253     if (hwirq < 0)
0254         return -ENOSPC;
0255 
0256     for (i = 0; i < nr_irqs; i++) {
0257         irq_domain_set_info(domain, virq + i, hwirq + i,
0258                     &armada_370_xp_msi_bottom_irq_chip,
0259                     domain->host_data, handle_simple_irq,
0260                     NULL, NULL);
0261     }
0262 
0263     return 0;
0264 }
0265 
0266 static void armada_370_xp_msi_free(struct irq_domain *domain,
0267                    unsigned int virq, unsigned int nr_irqs)
0268 {
0269     struct irq_data *d = irq_domain_get_irq_data(domain, virq);
0270 
0271     mutex_lock(&msi_used_lock);
0272     bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs));
0273     mutex_unlock(&msi_used_lock);
0274 }
0275 
0276 static const struct irq_domain_ops armada_370_xp_msi_domain_ops = {
0277     .alloc  = armada_370_xp_msi_alloc,
0278     .free   = armada_370_xp_msi_free,
0279 };
0280 
0281 static void armada_370_xp_msi_reenable_percpu(void)
0282 {
0283     u32 reg;
0284 
0285     /* Enable MSI doorbell mask and combined cpu local interrupt */
0286     reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
0287         | PCI_MSI_DOORBELL_MASK;
0288     writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0289     /* Unmask local doorbell interrupt */
0290     writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0291 }
0292 
0293 static int armada_370_xp_msi_init(struct device_node *node,
0294                   phys_addr_t main_int_phys_base)
0295 {
0296     msi_doorbell_addr = main_int_phys_base +
0297         ARMADA_370_XP_SW_TRIG_INT_OFFS;
0298 
0299     armada_370_xp_msi_inner_domain =
0300         irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
0301                       &armada_370_xp_msi_domain_ops, NULL);
0302     if (!armada_370_xp_msi_inner_domain)
0303         return -ENOMEM;
0304 
0305     armada_370_xp_msi_domain =
0306         pci_msi_create_irq_domain(of_node_to_fwnode(node),
0307                       &armada_370_xp_msi_domain_info,
0308                       armada_370_xp_msi_inner_domain);
0309     if (!armada_370_xp_msi_domain) {
0310         irq_domain_remove(armada_370_xp_msi_inner_domain);
0311         return -ENOMEM;
0312     }
0313 
0314     armada_370_xp_msi_reenable_percpu();
0315 
0316     return 0;
0317 }
0318 #else
0319 static void armada_370_xp_msi_reenable_percpu(void) {}
0320 
0321 static inline int armada_370_xp_msi_init(struct device_node *node,
0322                      phys_addr_t main_int_phys_base)
0323 {
0324     return 0;
0325 }
0326 #endif
0327 
0328 static void armada_xp_mpic_perf_init(void)
0329 {
0330     unsigned long cpuid;
0331 
0332     /*
0333      * This Performance Counter Overflow interrupt is specific for
0334      * Armada 370 and XP. It is not available on Armada 375, 38x and 39x.
0335      */
0336     if (!of_machine_is_compatible("marvell,armada-370-xp"))
0337         return;
0338 
0339     cpuid = cpu_logical_map(smp_processor_id());
0340 
0341     /* Enable Performance Counter Overflow interrupts */
0342     writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),
0343            per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);
0344 }
0345 
0346 #ifdef CONFIG_SMP
0347 static struct irq_domain *ipi_domain;
0348 
0349 static void armada_370_xp_ipi_mask(struct irq_data *d)
0350 {
0351     u32 reg;
0352     reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0353     reg &= ~BIT(d->hwirq);
0354     writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0355 }
0356 
0357 static void armada_370_xp_ipi_unmask(struct irq_data *d)
0358 {
0359     u32 reg;
0360     reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0361     reg |= BIT(d->hwirq);
0362     writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0363 }
0364 
0365 static void armada_370_xp_ipi_send_mask(struct irq_data *d,
0366                     const struct cpumask *mask)
0367 {
0368     unsigned long map = 0;
0369     int cpu;
0370 
0371     /* Convert our logical CPU mask into a physical one. */
0372     for_each_cpu(cpu, mask)
0373         map |= 1 << cpu_logical_map(cpu);
0374 
0375     /*
0376      * Ensure that stores to Normal memory are visible to the
0377      * other CPUs before issuing the IPI.
0378      */
0379     dsb();
0380 
0381     /* submit softirq */
0382     writel((map << 8) | d->hwirq, main_int_base +
0383         ARMADA_370_XP_SW_TRIG_INT_OFFS);
0384 }
0385 
0386 static void armada_370_xp_ipi_ack(struct irq_data *d)
0387 {
0388     writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
0389 }
0390 
0391 static struct irq_chip ipi_irqchip = {
0392     .name       = "IPI",
0393     .irq_ack    = armada_370_xp_ipi_ack,
0394     .irq_mask   = armada_370_xp_ipi_mask,
0395     .irq_unmask = armada_370_xp_ipi_unmask,
0396     .ipi_send_mask  = armada_370_xp_ipi_send_mask,
0397 };
0398 
0399 static int armada_370_xp_ipi_alloc(struct irq_domain *d,
0400                      unsigned int virq,
0401                      unsigned int nr_irqs, void *args)
0402 {
0403     int i;
0404 
0405     for (i = 0; i < nr_irqs; i++) {
0406         irq_set_percpu_devid(virq + i);
0407         irq_domain_set_info(d, virq + i, i, &ipi_irqchip,
0408                     d->host_data,
0409                     handle_percpu_devid_irq,
0410                     NULL, NULL);
0411     }
0412 
0413     return 0;
0414 }
0415 
0416 static void armada_370_xp_ipi_free(struct irq_domain *d,
0417                      unsigned int virq,
0418                      unsigned int nr_irqs)
0419 {
0420     /* Not freeing IPIs */
0421 }
0422 
0423 static const struct irq_domain_ops ipi_domain_ops = {
0424     .alloc  = armada_370_xp_ipi_alloc,
0425     .free   = armada_370_xp_ipi_free,
0426 };
0427 
0428 static void ipi_resume(void)
0429 {
0430     int i;
0431 
0432     for (i = 0; i < IPI_DOORBELL_END; i++) {
0433         int irq;
0434 
0435         irq = irq_find_mapping(ipi_domain, i);
0436         if (irq <= 0)
0437             continue;
0438         if (irq_percpu_is_enabled(irq)) {
0439             struct irq_data *d;
0440             d = irq_domain_get_irq_data(ipi_domain, irq);
0441             armada_370_xp_ipi_unmask(d);
0442         }
0443     }
0444 }
0445 
0446 static __init void armada_xp_ipi_init(struct device_node *node)
0447 {
0448     int base_ipi;
0449 
0450     ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node),
0451                           IPI_DOORBELL_END,
0452                           &ipi_domain_ops, NULL);
0453     if (WARN_ON(!ipi_domain))
0454         return;
0455 
0456     irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI);
0457     base_ipi = __irq_domain_alloc_irqs(ipi_domain, -1, IPI_DOORBELL_END,
0458                        NUMA_NO_NODE, NULL, false, NULL);
0459     if (WARN_ON(!base_ipi))
0460         return;
0461 
0462     set_smp_ipi_range(base_ipi, IPI_DOORBELL_END);
0463 }
0464 
0465 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
0466 
0467 static int armada_xp_set_affinity(struct irq_data *d,
0468                   const struct cpumask *mask_val, bool force)
0469 {
0470     irq_hw_number_t hwirq = irqd_to_hwirq(d);
0471     unsigned long reg, mask;
0472     int cpu;
0473 
0474     /* Select a single core from the affinity mask which is online */
0475     cpu = cpumask_any_and(mask_val, cpu_online_mask);
0476     mask = 1UL << cpu_logical_map(cpu);
0477 
0478     raw_spin_lock(&irq_controller_lock);
0479     reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
0480     reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;
0481     writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
0482     raw_spin_unlock(&irq_controller_lock);
0483 
0484     irq_data_update_effective_affinity(d, cpumask_of(cpu));
0485 
0486     return IRQ_SET_MASK_OK;
0487 }
0488 
0489 static void armada_xp_mpic_smp_cpu_init(void)
0490 {
0491     u32 control;
0492     int nr_irqs, i;
0493 
0494     control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
0495     nr_irqs = (control >> 2) & 0x3ff;
0496 
0497     for (i = 0; i < nr_irqs; i++)
0498         writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
0499 
0500     /* Disable all IPIs */
0501     writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0502 
0503     /* Clear pending IPIs */
0504     writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
0505 
0506     /* Unmask IPI interrupt */
0507     writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0508 }
0509 
0510 static void armada_xp_mpic_reenable_percpu(void)
0511 {
0512     unsigned int irq;
0513 
0514     /* Re-enable per-CPU interrupts that were enabled before suspend */
0515     for (irq = 0; irq < ARMADA_370_XP_MAX_PER_CPU_IRQS; irq++) {
0516         struct irq_data *data;
0517         int virq;
0518 
0519         virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
0520         if (virq == 0)
0521             continue;
0522 
0523         data = irq_get_irq_data(virq);
0524 
0525         if (!irq_percpu_is_enabled(virq))
0526             continue;
0527 
0528         armada_370_xp_irq_unmask(data);
0529     }
0530 
0531     ipi_resume();
0532 
0533     armada_370_xp_msi_reenable_percpu();
0534 }
0535 
0536 static int armada_xp_mpic_starting_cpu(unsigned int cpu)
0537 {
0538     armada_xp_mpic_perf_init();
0539     armada_xp_mpic_smp_cpu_init();
0540     armada_xp_mpic_reenable_percpu();
0541     return 0;
0542 }
0543 
0544 static int mpic_cascaded_starting_cpu(unsigned int cpu)
0545 {
0546     armada_xp_mpic_perf_init();
0547     armada_xp_mpic_reenable_percpu();
0548     enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
0549     return 0;
0550 }
0551 #else
0552 static void armada_xp_mpic_smp_cpu_init(void) {}
0553 static void ipi_resume(void) {}
0554 #endif
0555 
0556 static struct irq_chip armada_370_xp_irq_chip = {
0557     .name       = "MPIC",
0558     .irq_mask       = armada_370_xp_irq_mask,
0559     .irq_mask_ack   = armada_370_xp_irq_mask,
0560     .irq_unmask     = armada_370_xp_irq_unmask,
0561 #ifdef CONFIG_SMP
0562     .irq_set_affinity = armada_xp_set_affinity,
0563 #endif
0564     .flags      = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
0565 };
0566 
0567 static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
0568                       unsigned int virq, irq_hw_number_t hw)
0569 {
0570     armada_370_xp_irq_mask(irq_get_irq_data(virq));
0571     if (!is_percpu_irq(hw))
0572         writel(hw, per_cpu_int_base +
0573             ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0574     else
0575         writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
0576     irq_set_status_flags(virq, IRQ_LEVEL);
0577 
0578     if (is_percpu_irq(hw)) {
0579         irq_set_percpu_devid(virq);
0580         irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
0581                     handle_percpu_devid_irq);
0582     } else {
0583         irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
0584                     handle_level_irq);
0585         irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq)));
0586     }
0587     irq_set_probe(virq);
0588 
0589     return 0;
0590 }
0591 
0592 static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
0593     .map = armada_370_xp_mpic_irq_map,
0594     .xlate = irq_domain_xlate_onecell,
0595 };
0596 
0597 #ifdef CONFIG_PCI_MSI
0598 static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
0599 {
0600     u32 msimask, msinr;
0601 
0602     msimask = readl_relaxed(per_cpu_int_base +
0603                 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
0604         & PCI_MSI_DOORBELL_MASK;
0605 
0606     writel(~msimask, per_cpu_int_base +
0607            ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
0608 
0609     for (msinr = PCI_MSI_DOORBELL_START;
0610          msinr < PCI_MSI_DOORBELL_END; msinr++) {
0611         unsigned int irq;
0612 
0613         if (!(msimask & BIT(msinr)))
0614             continue;
0615 
0616         irq = msinr - PCI_MSI_DOORBELL_START;
0617 
0618         generic_handle_domain_irq(armada_370_xp_msi_inner_domain, irq);
0619     }
0620 }
0621 #else
0622 static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
0623 #endif
0624 
0625 static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc)
0626 {
0627     struct irq_chip *chip = irq_desc_get_chip(desc);
0628     unsigned long irqmap, irqn, irqsrc, cpuid;
0629 
0630     chained_irq_enter(chip, desc);
0631 
0632     irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);
0633     cpuid = cpu_logical_map(smp_processor_id());
0634 
0635     for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
0636         irqsrc = readl_relaxed(main_int_base +
0637                        ARMADA_370_XP_INT_SOURCE_CTL(irqn));
0638 
0639         /* Check if the interrupt is not masked on current CPU.
0640          * Test IRQ (0-1) and FIQ (8-9) mask bits.
0641          */
0642         if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid)))
0643             continue;
0644 
0645         if (irqn == 1) {
0646             armada_370_xp_handle_msi_irq(NULL, true);
0647             continue;
0648         }
0649 
0650         generic_handle_domain_irq(armada_370_xp_mpic_domain, irqn);
0651     }
0652 
0653     chained_irq_exit(chip, desc);
0654 }
0655 
0656 static void __exception_irq_entry
0657 armada_370_xp_handle_irq(struct pt_regs *regs)
0658 {
0659     u32 irqstat, irqnr;
0660 
0661     do {
0662         irqstat = readl_relaxed(per_cpu_int_base +
0663                     ARMADA_370_XP_CPU_INTACK_OFFS);
0664         irqnr = irqstat & 0x3FF;
0665 
0666         if (irqnr > 1022)
0667             break;
0668 
0669         if (irqnr > 1) {
0670             generic_handle_domain_irq(armada_370_xp_mpic_domain,
0671                           irqnr);
0672             continue;
0673         }
0674 
0675         /* MSI handling */
0676         if (irqnr == 1)
0677             armada_370_xp_handle_msi_irq(regs, false);
0678 
0679 #ifdef CONFIG_SMP
0680         /* IPI Handling */
0681         if (irqnr == 0) {
0682             unsigned long ipimask;
0683             int ipi;
0684 
0685             ipimask = readl_relaxed(per_cpu_int_base +
0686                         ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
0687                 & IPI_DOORBELL_MASK;
0688 
0689             for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END)
0690                 generic_handle_domain_irq(ipi_domain, ipi);
0691         }
0692 #endif
0693 
0694     } while (1);
0695 }
0696 
0697 static int armada_370_xp_mpic_suspend(void)
0698 {
0699     doorbell_mask_reg = readl(per_cpu_int_base +
0700                   ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0701     return 0;
0702 }
0703 
0704 static void armada_370_xp_mpic_resume(void)
0705 {
0706     int nirqs;
0707     irq_hw_number_t irq;
0708 
0709     /* Re-enable interrupts */
0710     nirqs = (readl(main_int_base + ARMADA_370_XP_INT_CONTROL) >> 2) & 0x3ff;
0711     for (irq = 0; irq < nirqs; irq++) {
0712         struct irq_data *data;
0713         int virq;
0714 
0715         virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
0716         if (virq == 0)
0717             continue;
0718 
0719         data = irq_get_irq_data(virq);
0720 
0721         if (!is_percpu_irq(irq)) {
0722             /* Non per-CPU interrupts */
0723             writel(irq, per_cpu_int_base +
0724                    ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0725             if (!irqd_irq_disabled(data))
0726                 armada_370_xp_irq_unmask(data);
0727         } else {
0728             /* Per-CPU interrupts */
0729             writel(irq, main_int_base +
0730                    ARMADA_370_XP_INT_SET_ENABLE_OFFS);
0731 
0732             /*
0733              * Re-enable on the current CPU,
0734              * armada_xp_mpic_reenable_percpu() will take
0735              * care of secondary CPUs when they come up.
0736              */
0737             if (irq_percpu_is_enabled(virq))
0738                 armada_370_xp_irq_unmask(data);
0739         }
0740     }
0741 
0742     /* Reconfigure doorbells for IPIs and MSIs */
0743     writel(doorbell_mask_reg,
0744            per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0745     if (doorbell_mask_reg & IPI_DOORBELL_MASK)
0746         writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0747     if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK)
0748         writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
0749 
0750     ipi_resume();
0751 }
0752 
0753 static struct syscore_ops armada_370_xp_mpic_syscore_ops = {
0754     .suspend    = armada_370_xp_mpic_suspend,
0755     .resume     = armada_370_xp_mpic_resume,
0756 };
0757 
0758 static int __init armada_370_xp_mpic_of_init(struct device_node *node,
0759                          struct device_node *parent)
0760 {
0761     struct resource main_int_res, per_cpu_int_res;
0762     int nr_irqs, i;
0763     u32 control;
0764 
0765     BUG_ON(of_address_to_resource(node, 0, &main_int_res));
0766     BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res));
0767 
0768     BUG_ON(!request_mem_region(main_int_res.start,
0769                    resource_size(&main_int_res),
0770                    node->full_name));
0771     BUG_ON(!request_mem_region(per_cpu_int_res.start,
0772                    resource_size(&per_cpu_int_res),
0773                    node->full_name));
0774 
0775     main_int_base = ioremap(main_int_res.start,
0776                 resource_size(&main_int_res));
0777     BUG_ON(!main_int_base);
0778 
0779     per_cpu_int_base = ioremap(per_cpu_int_res.start,
0780                    resource_size(&per_cpu_int_res));
0781     BUG_ON(!per_cpu_int_base);
0782 
0783     control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
0784     nr_irqs = (control >> 2) & 0x3ff;
0785 
0786     for (i = 0; i < nr_irqs; i++)
0787         writel(i, main_int_base + ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
0788 
0789     armada_370_xp_mpic_domain =
0790         irq_domain_add_linear(node, nr_irqs,
0791                 &armada_370_xp_mpic_irq_ops, NULL);
0792     BUG_ON(!armada_370_xp_mpic_domain);
0793     irq_domain_update_bus_token(armada_370_xp_mpic_domain, DOMAIN_BUS_WIRED);
0794 
0795     /* Setup for the boot CPU */
0796     armada_xp_mpic_perf_init();
0797     armada_xp_mpic_smp_cpu_init();
0798 
0799     armada_370_xp_msi_init(node, main_int_res.start);
0800 
0801     parent_irq = irq_of_parse_and_map(node, 0);
0802     if (parent_irq <= 0) {
0803         irq_set_default_host(armada_370_xp_mpic_domain);
0804         set_handle_irq(armada_370_xp_handle_irq);
0805 #ifdef CONFIG_SMP
0806         armada_xp_ipi_init(node);
0807         cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING,
0808                       "irqchip/armada/ipi:starting",
0809                       armada_xp_mpic_starting_cpu, NULL);
0810 #endif
0811     } else {
0812 #ifdef CONFIG_SMP
0813         cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING,
0814                       "irqchip/armada/cascade:starting",
0815                       mpic_cascaded_starting_cpu, NULL);
0816 #endif
0817         irq_set_chained_handler(parent_irq,
0818                     armada_370_xp_mpic_handle_cascade_irq);
0819     }
0820 
0821     register_syscore_ops(&armada_370_xp_mpic_syscore_ops);
0822 
0823     return 0;
0824 }
0825 
0826 IRQCHIP_DECLARE(armada_370_xp_mpic, "marvell,mpic", armada_370_xp_mpic_of_init);