// SPDX-License-Identifier: GPL-2.0-only /* * HiSilicon HiP04 INTC * * Copyright (C) 2002-2014 ARM Limited. * Copyright (c) 2013-2014 HiSilicon Ltd. * Copyright (c) 2013-2014 Linaro Ltd. * * Interrupt architecture for the HIP04 INTC: * * o There is one Interrupt Distributor, which receives interrupts * from system devices and sends them to the Interrupt Controllers. * * o There is one CPU Interface per CPU, which sends interrupts sent * by the Distributor, and interrupts generated locally, to the * associated CPU. The base address of the CPU interface is usually * aliased so that the same address points to different chips depending * on the CPU it is accessed from. * * Note that IRQs 0-31 are special - they are local to each CPU. * As such, the enable set/clear, pending set/clear and active bit * registers are banked per-cpu for these sources.
*/
/* * The GIC mapping of CPU interfaces does not necessarily match * the logical CPU numbering. Let's use a mapping as returned * by the GIC itself.
*/ #define NR_HIP04_CPU_IF 16 static u16 hip04_cpu_map[NR_HIP04_CPU_IF] __read_mostly;
/* Interrupt configuration for SGIs can't be changed */ if (irq < 16) return -EINVAL;
/* SPIs have restrictions on the supported types */ if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
type != IRQ_TYPE_EDGE_RISING) return -EINVAL;
raw_spin_lock(&irq_controller_lock);
ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG); if (ret && irq < 32) { /* Misconfigured PPIs are usually not fatal */
pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
ret = 0;
}
/* * Set all global interrupts to this CPU only.
*/
cpumask = hip04_get_cpumask(intc);
cpumask |= cpumask << 16; for (i = 32; i < nr_irqs; i += 2)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + ((i * 2) & ~3));
/* * Get what the GIC says our CPU mask is.
*/
BUG_ON(cpu >= NR_HIP04_CPU_IF);
cpu_mask = hip04_get_cpumask(intc);
hip04_cpu_map[cpu] = cpu_mask;
/* * Clear our mask from the other map entries in case they're * still undefined.
*/ for (i = 0; i < NR_HIP04_CPU_IF; i++) if (i != cpu)
hip04_cpu_map[i] &= ~cpu_mask;
gic_cpu_config(dist_base, 32, GICD_INT_DEF_PRI);
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
}
hip04_data.cpu_base = of_iomap(node, 1);
WARN(!hip04_data.cpu_base, "unable to map hip04 intc cpu registers\n");
/* * Initialize the CPU interface map to all CPUs. * It will be refined as each CPU probes its ID.
*/ for (i = 0; i < NR_HIP04_CPU_IF; i++)
hip04_cpu_map[i] = 0xffff;
/* * Find out how many interrupts are supported. * The HIP04 INTC only supports up to 510 interrupt sources.
*/
nr_irqs = readl_relaxed(hip04_data.dist_base + GIC_DIST_CTR) & 0x1f;
nr_irqs = (nr_irqs + 1) * 32; if (nr_irqs > HIP04_MAX_IRQS)
nr_irqs = HIP04_MAX_IRQS;
hip04_data.nr_irqs = nr_irqs;
irq_base = irq_alloc_descs(-1, 0, nr_irqs, numa_node_id()); if (irq_base < 0) {
pr_err("failed to allocate IRQ numbers\n"); return -EINVAL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.