You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
4.3 KiB
151 lines
4.3 KiB
5 months ago
|
#include "rtconfig.h"
|
||
|
#if defined(TARGET_ARMV8_AARCH64)
|
||
|
#include <rthw.h>
|
||
|
#include <rtthread.h>
|
||
|
#include "interrupt.h"
|
||
|
#include "gic.h"
|
||
|
#include "gicv3.h"
|
||
|
#include "ioremap.h"
|
||
|
#include "phytium_cpu.h"
|
||
|
#include "ftypes.h"
|
||
|
#include "fparameters.h"
|
||
|
|
||
|
struct arm_gic *phytium_gic_table;
|
||
|
|
||
|
extern struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||
|
|
||
|
int arm_gic_redist_address_set(rt_uint64_t index, rt_uint64_t redist_addr, int cpu_id)
|
||
|
{
|
||
|
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||
|
|
||
|
if (cpu_id == 0)
|
||
|
{
|
||
|
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, &cpu_id, sizeof(cpu_id));
|
||
|
}
|
||
|
|
||
|
phytium_gic_table[index].redist_hw_base[cpu_id] = redist_addr;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int arm_gicv3_wait_rwp(rt_uint64_t index, rt_uint64_t irq)
|
||
|
{
|
||
|
rt_uint64_t rwp_bit;
|
||
|
rt_uint64_t base;
|
||
|
|
||
|
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||
|
|
||
|
if (irq < 32)
|
||
|
{
|
||
|
rt_int32_t cpu_id = rt_hw_cpu_id();
|
||
|
|
||
|
base = phytium_gic_table[index].redist_hw_base[cpu_id];
|
||
|
rwp_bit = GICR_CTLR_RWP;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base = phytium_gic_table[index].dist_hw_base;
|
||
|
rwp_bit = GICD_CTLR_RWP;
|
||
|
}
|
||
|
|
||
|
while (HWREG32(base) & rwp_bit)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int phytium_aarch64_arm_gic_redist_init()
|
||
|
{
|
||
|
rt_uint64_t cpu_id = rt_hw_cpu_id();
|
||
|
rt_uint64_t redist_base = phytium_gic_table[0].redist_hw_base[cpu_id];
|
||
|
|
||
|
/* redistributor enable */
|
||
|
GIC_RDIST_WAKER(redist_base) &= ~(1 << 1);
|
||
|
while (GIC_RDIST_WAKER(redist_base) & (1 << 2))
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/* Disable all sgi and ppi interrupt */
|
||
|
GIC_RDISTSGI_ICENABLER0(redist_base) = 0xffffffff;
|
||
|
arm_gicv3_wait_rwp(0, 0);
|
||
|
|
||
|
/* Clear all inetrrupt pending */
|
||
|
GIC_RDISTSGI_ICPENDR0(redist_base) = 0xffffffff;
|
||
|
|
||
|
/* the corresponding interrupt is Group 1 or Non-secure Group 1. */
|
||
|
GIC_RDISTSGI_IGROUPR0(redist_base, 0) = 0xffffffff;
|
||
|
GIC_RDISTSGI_IGRPMODR0(redist_base, 0) = 0xffffffff;
|
||
|
|
||
|
/* Configure default priorities for SGI 0:15 and PPI 16:31. */
|
||
|
for (int i = 0; i < 32; i += 4)
|
||
|
{
|
||
|
GIC_RDISTSGI_IPRIORITYR(redist_base, i) = 0xa0a0a0a0U;
|
||
|
}
|
||
|
|
||
|
/* Trigger level for PPI interrupts*/
|
||
|
GIC_RDISTSGI_ICFGR1(redist_base) = 0;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void phytium_interrupt_init(void)
|
||
|
{
|
||
|
rt_uint64_t gic_cpu_base;
|
||
|
rt_uint64_t gic_dist_base;
|
||
|
rt_uint64_t gic_irq_start;
|
||
|
rt_uint64_t redist_addr;
|
||
|
|
||
|
phytium_gic_table = (struct arm_gic *)arm_gic_get_gic_table_addr();
|
||
|
/* initialize vector table */
|
||
|
rt_hw_vector_init();
|
||
|
|
||
|
/* initialize exceptions table */
|
||
|
rt_memset(isr_table, 0x00, sizeof(isr_table));
|
||
|
|
||
|
#if defined(RT_USING_SMART)
|
||
|
gic_dist_base = (rt_uint64_t)rt_ioremap((void *)platform_get_gic_dist_base(), 0x40000);
|
||
|
gic_cpu_base = (rt_uint64_t)rt_ioremap((void*)platform_get_gic_cpu_base(), 0x1000);
|
||
|
redist_addr = (rt_uint64_t)rt_ioremap(GICV3_RD_BASE_ADDR, 4 * GICV3_RD_OFFSET);
|
||
|
#else
|
||
|
gic_dist_base = platform_get_gic_dist_base();
|
||
|
gic_cpu_base = platform_get_gic_cpu_base();
|
||
|
redist_addr = GICV3_RD_BASE_ADDR;
|
||
|
#endif
|
||
|
|
||
|
gic_irq_start = 0;
|
||
|
arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
|
||
|
arm_gic_cpu_init(0, gic_cpu_base);
|
||
|
arm_gic_redist_address_set(0, redist_addr + 2 * GICV3_RD_OFFSET, 0);
|
||
|
|
||
|
#if defined(TARGET_E2000Q) || defined(TARGET_PHYTIUMPI)
|
||
|
#if RT_CPUS_NR == 2
|
||
|
arm_gic_redist_address_set(0, redist_addr + 3 * GICV3_RD_OFFSET, 1);
|
||
|
#elif RT_CPUS_NR == 3
|
||
|
arm_gic_redist_address_set(0, redist_addr + 3 * GICV3_RD_OFFSET, 1);
|
||
|
arm_gic_redist_address_set(0, redist_addr, 2);
|
||
|
#elif RT_CPUS_NR == 4
|
||
|
arm_gic_redist_address_set(0, redist_addr + 3 * GICV3_RD_OFFSET, 1);
|
||
|
arm_gic_redist_address_set(0, redist_addr, 2);
|
||
|
arm_gic_redist_address_set(0, redist_addr + GICV3_RD_OFFSET, 3);
|
||
|
#endif
|
||
|
#else
|
||
|
#if defined(TARGET_E2000D)
|
||
|
rt_uint32_t cpu_offset = 2;
|
||
|
#endif
|
||
|
#if RT_CPUS_NR == 2
|
||
|
arm_gic_redist_address_set(0, redist_addr + (1 + cpu_offset) * GICV3_RD_OFFSET, 1);
|
||
|
#elif RT_CPUS_NR == 3
|
||
|
arm_gic_redist_address_set(0, redist_addr + (1 + cpu_offset) * GICV3_RD_OFFSET, 1);
|
||
|
arm_gic_redist_address_set(0, redist_addr + (2 + cpu_offset) * GICV3_RD_OFFSET, 2);
|
||
|
#elif RT_CPUS_NR == 4
|
||
|
arm_gic_redist_address_set(0, redist_addr + (1 + cpu_offset) * GICV3_RD_OFFSET, 1);
|
||
|
arm_gic_redist_address_set(0, redist_addr + (2 + cpu_offset) * GICV3_RD_OFFSET, 2);
|
||
|
arm_gic_redist_address_set(0, redist_addr + (3 + cpu_offset) * GICV3_RD_OFFSET, 3);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
phytium_aarch64_arm_gic_redist_init();
|
||
|
}
|
||
|
#endif
|