irqchip/gic: support config amp os irqs

Signed-off-by: Tony Xie <tony.xie@rock-chips.com>
Change-Id: Id7ff9d5cccfe5656462542fcfa68fef51cdd910e
This commit is contained in:
Tony Xie
2023-06-29 19:52:59 +08:00
committed by Tao Huang
parent 0bbcfb87aa
commit 2e7658ef57
2 changed files with 82 additions and 0 deletions

View File

@@ -10,6 +10,10 @@
#include "irq-gic-common.h" #include "irq-gic-common.h"
#ifdef CONFIG_ROCKCHIP_AMP
#include <soc/rockchip/rockchip_amp.h>
#endif
static DEFINE_RAW_SPINLOCK(irq_controller_lock); static DEFINE_RAW_SPINLOCK(irq_controller_lock);
static const struct gic_kvm_info *gic_kvm_info; static const struct gic_kvm_info *gic_kvm_info;
@@ -112,8 +116,25 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
/* /*
* Set priority on all global interrupts. * Set priority on all global interrupts.
*/ */
#ifdef CONFIG_ROCKCHIP_AMP
for (i = 32; i < gic_irqs; i += 4) {
u32 amp_pri, j;
amp_pri = 0;
for (j = 0; j < 4; j++) {
if (rockchip_amp_check_amp_irq(i + j)) {
amp_pri |= rockchip_amp_get_irq_prio(i + j) <<
(j * 8);
} else {
amp_pri |= GICD_INT_DEF_PRI << (j * 8);
}
}
writel_relaxed(amp_pri, base + GIC_DIST_PRI + i);
}
#else
for (i = 32; i < gic_irqs; i += 4) for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i); writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
#endif
/* /*
* Deactivate and disable all SPIs. Leave the PPI and SGIs * Deactivate and disable all SPIs. Leave the PPI and SGIs

View File

@@ -47,6 +47,10 @@
#include "irq-gic-common.h" #include "irq-gic-common.h"
#ifdef CONFIG_ROCKCHIP_AMP
#include <soc/rockchip/rockchip_amp.h>
#endif
#ifdef CONFIG_ARM64 #ifdef CONFIG_ARM64
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
@@ -194,11 +198,19 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
static void gic_mask_irq(struct irq_data *d) static void gic_mask_irq(struct irq_data *d)
{ {
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return;
#endif
gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR); gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR);
} }
static void gic_eoimode1_mask_irq(struct irq_data *d) static void gic_eoimode1_mask_irq(struct irq_data *d)
{ {
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return;
#endif
gic_mask_irq(d); gic_mask_irq(d);
/* /*
* When masking a forwarded interrupt, make sure it is * When masking a forwarded interrupt, make sure it is
@@ -214,6 +226,10 @@ static void gic_eoimode1_mask_irq(struct irq_data *d)
static void gic_unmask_irq(struct irq_data *d) static void gic_unmask_irq(struct irq_data *d)
{ {
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return;
#endif
gic_poke_irq(d, GIC_DIST_ENABLE_SET); gic_poke_irq(d, GIC_DIST_ENABLE_SET);
} }
@@ -221,6 +237,10 @@ static void gic_eoi_irq(struct irq_data *d)
{ {
u32 hwirq = gic_irq(d); u32 hwirq = gic_irq(d);
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(hwirq))
return;
#endif
if (hwirq < 16) if (hwirq < 16)
hwirq = this_cpu_read(sgi_intid); hwirq = this_cpu_read(sgi_intid);
@@ -231,6 +251,10 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
{ {
u32 hwirq = gic_irq(d); u32 hwirq = gic_irq(d);
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return;
#endif
/* Do not deactivate an IRQ forwarded to a vcpu. */ /* Do not deactivate an IRQ forwarded to a vcpu. */
if (irqd_is_forwarded_to_vcpu(d)) if (irqd_is_forwarded_to_vcpu(d))
return; return;
@@ -246,6 +270,10 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
{ {
u32 reg; u32 reg;
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return -EINVAL;
#endif
switch (which) { switch (which) {
case IRQCHIP_STATE_PENDING: case IRQCHIP_STATE_PENDING:
reg = val ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR; reg = val ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR;
@@ -296,6 +324,11 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
unsigned int gicirq = gic_irq(d); unsigned int gicirq = gic_irq(d);
int ret; int ret;
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return -EINVAL;
#endif
/* Interrupt configuration for SGIs can't be changed */ /* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16) if (gicirq < 16)
return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0; return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0;
@@ -492,10 +525,29 @@ static void gic_dist_init(struct gic_chip_data *gic)
* Set all global interrupts to this CPU only. * Set all global interrupts to this CPU only.
*/ */
cpumask = gic_get_cpumask(gic); cpumask = gic_get_cpumask(gic);
#ifdef CONFIG_ROCKCHIP_AMP
for (i = 32; i < gic_irqs; i += 4) {
u32 maskval;
unsigned int j;
maskval = 0;
for (j = 0; j < 4; j++) {
if (rockchip_amp_check_amp_irq(i + j)) {
maskval |= rockchip_amp_get_irq_cpumask(i + j) <<
(j * 8);
} else {
maskval |= cpumask << (j * 8);
}
}
writel_relaxed(maskval, base + GIC_DIST_TARGET + i * 4 / 4);
}
#else
cpumask |= cpumask << 8; cpumask |= cpumask << 8;
cpumask |= cpumask << 16; cpumask |= cpumask << 16;
for (i = 32; i < gic_irqs; i += 4) for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
#endif
gic_dist_config(base, gic_irqs, NULL); gic_dist_config(base, gic_irqs, NULL);
@@ -847,6 +899,11 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d); void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
unsigned int cpu; unsigned int cpu;
#ifdef CONFIG_ROCKCHIP_AMP
if (rockchip_amp_check_amp_irq(gic_irq(d)))
return -EINVAL;
#endif
if (!force) if (!force)
cpu = cpumask_any_and(mask_val, cpu_online_mask); cpu = cpumask_any_and(mask_val, cpu_online_mask);
else else
@@ -1509,6 +1566,10 @@ static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
gic_enable_of_quirks(node, gic_quirks, gic); gic_enable_of_quirks(node, gic_quirks, gic);
#ifdef CONFIG_ROCKCHIP_AMP
rockchip_amp_get_gic_info();
#endif
return 0; return 0;
error: error: