0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
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
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
0169
0170
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
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
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
0334
0335
0336 if (!of_machine_is_compatible("marvell,armada-370-xp"))
0337 return;
0338
0339 cpuid = cpu_logical_map(smp_processor_id());
0340
0341
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
0372 for_each_cpu(cpu, mask)
0373 map |= 1 << cpu_logical_map(cpu);
0374
0375
0376
0377
0378
0379 dsb();
0380
0381
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
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
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
0501 writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
0502
0503
0504 writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
0505
0506
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
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
0640
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
0676 if (irqnr == 1)
0677 armada_370_xp_handle_msi_irq(regs, false);
0678
0679 #ifdef CONFIG_SMP
0680
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
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
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
0729 writel(irq, main_int_base +
0730 ARMADA_370_XP_INT_SET_ENABLE_OFFS);
0731
0732
0733
0734
0735
0736
0737 if (irq_percpu_is_enabled(virq))
0738 armada_370_xp_irq_unmask(data);
0739 }
0740 }
0741
0742
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
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);