irq: gic v2/v3: support set target cpu by mpidr dynamiclly

Change-Id: I4a45ad1d81ab9b2e8ae958e6307030200bb405f1
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2019-02-19 15:54:53 +08:00 committed by Jianhong Chen
parent f2835bc289
commit 79d3f33751
1 changed files with 21 additions and 27 deletions

View File

@ -4,6 +4,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/gic.h>
#include <config.h>
@ -15,6 +16,9 @@
#define gicd_writel(v, offset) writel(v, (void *)GICD_BASE + (offset))
#define gicc_writel(v, offset) writel(v, (void *)GICC_BASE + (offset))
/* 64-bit write */
#define gicd_writeq(v, offset) writeq(v, (void *)GICD_BASE + (offset))
#define IRQ_REG_X4(irq) (4 * ((irq) / 4))
#define IRQ_REG_X16(irq) (4 * ((irq) / 16))
#define IRQ_REG_X32(irq) (4 * ((irq) / 32))
@ -22,6 +26,14 @@
#define IRQ_REG_X16_OFFSET(irq) ((irq) % 16)
#define IRQ_REG_X32_OFFSET(irq) ((irq) % 32)
#define MPIDR_CPU_MASK 0xff
#define IROUTER_IRM_SHIFT 31
#define IROUTER_IRM_MASK 0x1
#define gicd_irouter_val_from_mpidr(mpidr, irm) \
((mpidr & ~(0xff << 24)) | \
(irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT)
typedef enum INT_TRIG {
INT_LEVEL_TRIGGER,
INT_EDGE_TRIGGER
@ -45,27 +57,6 @@ struct gic_cpu_data {
static struct gic_dist_data gicd_save;
static struct gic_cpu_data gicc_save;
__maybe_unused static u8 g_gic_cpumask = 0x01;
__maybe_unused static u32 gic_get_cpumask(void)
{
u32 mask = 0, i;
for (i = mask = 0; i < 32; i += 4) {
mask = gicd_readl(GICD_ITARGETSRn + 4 * i);
mask |= mask >> 16;
mask |= mask >> 8;
if (mask)
break;
}
if (!mask)
printf("GIC CPU mask not found.\n");
debug("GIC CPU mask = 0x%08x\n", mask);
return mask;
}
static inline void int_set_prio_filter(u32 priority)
{
gicc_writel(priority & 0xff, GICC_PMR);
@ -145,7 +136,7 @@ static int gic_irq_set_trigger(int irq, eINT_TRIG trig)
static int gic_irq_enable(int irq)
{
#ifdef CONFIG_GICV2
u32 val;
u32 val, cpu_mask;
u32 shift = (irq % 4) * 8;
if (irq >= PLATFORM_GIC_IRQS_NR)
@ -156,19 +147,24 @@ static int gic_irq_enable(int irq)
val |= 1 << IRQ_REG_X32_OFFSET(irq);
gicd_writel(val, GICD_ISENABLERn + IRQ_REG_X32(irq));
/* set target */
cpu_mask = 1 << (read_mpidr() & MPIDR_CPU_MASK);
val = gicd_readl(GICD_ITARGETSRn + IRQ_REG_X4(irq));
val &= ~(0xFF << shift);
val |= (g_gic_cpumask << shift);
val |= (cpu_mask << shift);
gicd_writel(val, GICD_ITARGETSRn + IRQ_REG_X4(irq));
#else
u32 val;
u64 affinity_val;
/* set enable */
val = gicd_readl(GICD_ISENABLERn + IRQ_REG_X32(irq));
val |= 1 << IRQ_REG_X32_OFFSET(irq);
gicd_writel(val, GICD_ISENABLERn + IRQ_REG_X32(irq));
/* set itouter(target) */
affinity_val = gicd_irouter_val_from_mpidr(read_mpidr(), 0);
gicd_writeq(affinity_val, GICD_IROUTERn + (irq << 3));
#endif
return 0;
@ -360,8 +356,6 @@ static int gic_irq_init(void)
int_enable_secure_signal();
int_enable_nosecure_signal();
int_enable_distributor();
g_gic_cpumask = gic_get_cpumask();
#endif
return 0;