freertos: add freertos support [1/1]

PD#SWPL-71741
PD#SWPL-128739

Problem:
1 add freertos support
2 rtos mipi irq miss frequently when booting kernel

Solution:
1 add freertos support
2 mark gic distributor disable

Verify:
C2 T7

Change-Id: Ib2b18fbcb026afa8df7654eac90355f080e9a74b
Signed-off-by: wanwei.jiang <wanwei.jiang@amlogic.com>
This commit is contained in:
wanwei.jiang
2022-02-28 09:54:55 +08:00
committed by Dongjin Kim
parent d7bfa70f25
commit 9512f6d7f0
4 changed files with 100 additions and 1 deletions

View File

@@ -48,6 +48,10 @@
#include <asm/mach/arch.h>
#include <asm/mpu.h>
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
#include <linux/amlogic/freertos.h>
#endif
#define CREATE_TRACE_POINTS
#include <trace/events/ipi.h>
@@ -76,6 +80,9 @@ enum ipi_msg_type {
IPI_IRQ_WORK,
IPI_COMPLETION,
NR_IPI,
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
IPI_FREERTOS = NR_IPI,
#endif
/*
* CPU_BACKTRACE is special and not included in NR_IPI
* or tracable with trace_ipi_*
@@ -687,6 +694,13 @@ static void do_handle_IPI(int ipinr)
break;
case IPI_CPU_BACKTRACE:
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS_NOFITIER) && IS_ENABLED(CONFIG_AMLOGIC_FREERTOS_C3)
call_freertos_notifiers(1, NULL);
#endif
if (!freertos_finish())
break;
#endif
printk_deferred_enter();
nmi_cpu_backtrace(get_irq_regs());
printk_deferred_exit();
@@ -771,6 +785,14 @@ void smp_send_reschedule(int cpu)
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS_IPI_SEND)
void arch_send_ipi_rtos(int cpu)
{
smp_cross_call(cpumask_of(cpu), IPI_FREERTOS);
}
EXPORT_SYMBOL(arch_send_ipi_rtos);
#endif
void smp_send_stop(void)
{
unsigned long timeout;

View File

@@ -59,6 +59,10 @@
#undef CREATE_TRACE_POINTS
#include <trace/hooks/debug.h>
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
#include <linux/amlogic/freertos.h>
#endif
DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
EXPORT_PER_CPU_SYMBOL(cpu_number);
EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_raise);
@@ -82,6 +86,9 @@ enum ipi_msg_type {
IPI_TIMER,
IPI_IRQ_WORK,
IPI_WAKEUP,
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
IPI_FREERTOS = 7,
#endif
NR_IPI
};
@@ -810,6 +817,9 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
[IPI_TIMER] = "Timer broadcast interrupts",
[IPI_IRQ_WORK] = "IRQ work interrupts",
[IPI_WAKEUP] = "CPU wake-up interrupts",
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
[IPI_FREERTOS] = "CPU freertos interrupts",
#endif
};
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
@@ -856,6 +866,13 @@ void arch_irq_work_raise(void)
}
#endif
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS_IPI_SEND)
void arch_send_ipi_rtos(int cpu)
{
smp_cross_call(cpumask_of(cpu), IPI_FREERTOS);
}
#endif
static void local_cpu_stop(void)
{
set_cpu_online(smp_processor_id(), false);
@@ -949,6 +966,12 @@ static void do_handle_IPI(int ipinr)
break;
#endif
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
case IPI_FREERTOS:
freertos_finish();
break;
#endif
default:
pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
break;

View File

@@ -10,6 +10,10 @@
#include "irq-gic-common.h"
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
#include <linux/amlogic/freertos.h>
#endif
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
void gic_enable_of_quirks(const struct device_node *np,
@@ -94,30 +98,62 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void))
{
unsigned int i;
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
u32 tmp;
#endif
/*
* Set all global interrupts to be level triggered, active low.
*/
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
for (i = 32; i < gic_irqs; i += 16) {
tmp = readl_relaxed(base + GIC_DIST_CONFIG + i / 4);
tmp = freertos_get_irqregval
(GICD_INT_ACTLOW_LVLTRIG, tmp, i, 16);
writel_relaxed(tmp, base + GIC_DIST_CONFIG + i / 4);
}
#else
for (i = 32; i < gic_irqs; i += 16)
writel_relaxed(GICD_INT_ACTLOW_LVLTRIG,
base + GIC_DIST_CONFIG + i / 4);
#endif
/*
* Set priority on all global interrupts.
*/
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
for (i = 32; i < gic_irqs; i += 4) {
tmp = readl_relaxed(base + GIC_DIST_PRI + i);
tmp = freertos_get_irqregval
(GICD_INT_DEF_PRI_X4, tmp, i, 4);
writel_relaxed(tmp, base + GIC_DIST_PRI + i);
}
#else
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
#endif
/*
* Deactivate and disable all SPIs. Leave the PPI and SGIs
* alone as they are in the redistributor registers on GICv3.
*/
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
for (i = 32; i < gic_irqs; i += 32) {
writel_relaxed
(freertos_get_irqregval(GICD_INT_EN_CLR_X32, 0, i, 32),
base + GIC_DIST_ACTIVE_CLEAR + i / 8);
writel_relaxed
(freertos_get_irqregval(GICD_INT_EN_CLR_X32, 0, i, 32),
base + GIC_DIST_ENABLE_CLEAR + i / 8);
}
#else
for (i = 32; i < gic_irqs; i += 32) {
writel_relaxed(GICD_INT_EN_CLR_X32,
base + GIC_DIST_ACTIVE_CLEAR + i / 8);
writel_relaxed(GICD_INT_EN_CLR_X32,
base + GIC_DIST_ENABLE_CLEAR + i / 8);
}
#endif
if (sync_access)
sync_access();

View File

@@ -48,6 +48,10 @@
#include "irq-gic-common.h"
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
#include <linux/amlogic/freertos.h>
#endif
#ifdef CONFIG_ARM64
#include <asm/cpufeature.h>
@@ -466,15 +470,21 @@ static void gic_cpu_if_up(struct gic_chip_data *gic)
writel_relaxed(bypass | mode | GICC_ENABLE, cpu_base + GIC_CPU_CTRL);
}
static void gic_dist_init(struct gic_chip_data *gic)
{
unsigned int i;
u32 cpumask;
unsigned int gic_irqs = gic->gic_irqs;
void __iomem *base = gic_data_dist_base(gic);
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
u32 tmp;
#endif
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
/*disable gic distributor will result in freertos lost interrupt*/
#else
writel_relaxed(GICD_DISABLE, base + GIC_DIST_CTRL);
#endif
/*
* Set all global interrupts to this CPU only.
@@ -482,8 +492,16 @@ static void gic_dist_init(struct gic_chip_data *gic)
cpumask = gic_get_cpumask(gic);
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
#if IS_ENABLED(CONFIG_AMLOGIC_FREERTOS)
for (i = 32; i < gic_irqs; i += 4) {
tmp = readl_relaxed(base + GIC_DIST_TARGET + i * 4 / 4);
tmp = freertos_get_irqregval(cpumask, tmp, i, 4);
writel_relaxed(tmp, base + GIC_DIST_TARGET + i * 4 / 4);
}
#else
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
#endif
gic_dist_config(base, gic_irqs, NULL);