[bsp/virt64/aarch64] Add 'qemu-virt64-aarch64' bsp

This commit is contained in:
GuEe-GUI
2021-08-06 18:35:58 +08:00
parent 73bd7a7d66
commit b7dd004de0
28 changed files with 2014 additions and 5 deletions
+6
View File
@@ -5,6 +5,10 @@ from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
gic390_group = Split('''
gic_pl390.c
''')
gic400_group = Split('''
gic_pl400.c
''')
@@ -14,6 +18,8 @@ gic_pl500.c
''')
src = ()
if GetDepend('BSP_USING_GIC390'):
src = gic390_group
if GetDepend('BSP_USING_GIC400'):
src = gic400_group
if GetDepend('BSP_USING_GIC500'):
+273
View File
@@ -0,0 +1,273 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-31 GuEe-GUI the first version
*/
#include <rtthread.h>
#include "gic_pl390.h"
#define BIT(n) (1ul<<(n))
#define MASK(n) (BIT(n)-1ul)
#define IRQ_REG(IRQ) ((IRQ) / 32)
#define IRQ_BIT(IRQ) BIT((IRQ) % 32)
#define IRQ_MASK MASK(10)
#define IRQ_SET_ALL 0xffffffff
#define IS_IRQ_VALID(X) (((X)&IRQ_MASK) < GIC390_SPECIAL_IRQ_START)
#define TARGET_CPU_ALLINT(CPU) \
( \
(((CPU) & 0xff) << 0 ) | \
(((CPU) & 0xff) << 8 ) | \
(((CPU) & 0xff) << 16) | \
(((CPU) & 0xff) << 24) \
)
#define CPU(X) (1<<(X))
#define TARGET_CPU0_ALLINT TARGET_CPU_ALLINT(CPU(0))
/* memory map for GIC distributor */
struct gic_dist_map
{
rt_uint32_t enable; /* 0x000 */
rt_uint32_t ic_type; /* 0x004 */
rt_uint32_t dist_ident; /* 0x008 */
rt_uint32_t res1[29]; /* [0x00C, 0x080) */
rt_uint32_t security[32]; /* [0x080, 0x100) */
rt_uint32_t enable_set[32]; /* [0x100, 0x180) */
rt_uint32_t enable_clr[32]; /* [0x180, 0x200) */
rt_uint32_t pending_set[32]; /* [0x200, 0x280) */
rt_uint32_t pending_clr[32]; /* [0x280, 0x300) */
rt_uint32_t active[32]; /* [0x300, 0x380) */
rt_uint32_t res2[32]; /* [0x380, 0x400) */
rt_uint32_t priority[255]; /* [0x400, 0x7FC) */
rt_uint32_t res3; /* 0x7FC */
rt_uint32_t targets[255]; /* [0x800, 0xBFC) */
rt_uint32_t res4; /* 0xBFC */
rt_uint32_t config[64]; /* [0xC00, 0xD00) */
rt_uint32_t spi[32]; /* [0xD00, 0xD80) */
rt_uint32_t res5[20]; /* [0xD80, 0xDD0) */
rt_uint32_t res6; /* 0xDD0 */
rt_uint32_t legacy_int; /* 0xDD4 */
rt_uint32_t res7[2]; /* [0xDD8, 0xDE0) */
rt_uint32_t match_d; /* 0xDE0 */
rt_uint32_t enable_d; /* 0xDE4 */
rt_uint32_t res8[70]; /* [0xDE8, 0xF00) */
rt_uint32_t sgi_control; /* 0xF00 */
rt_uint32_t res9[3]; /* [0xF04, 0xF10) */
rt_uint32_t sgi_pending_clr[4]; /* [0xF10, 0xF20) */
rt_uint32_t res10[40]; /* [0xF20, 0xFC0) */
rt_uint32_t periph_id[12]; /* [0xFC0, 0xFF0) */
rt_uint32_t component_id[4]; /* [0xFF0, 0xFFF] */
};
/* memory map for GIC CPU interface */
struct gic_cpu_iface_map
{
rt_uint32_t icontrol; /* 0x000 */
rt_uint32_t pri_msk_c; /* 0x004 */
rt_uint32_t pb_c; /* 0x008 */
rt_uint32_t int_ack; /* 0x00C */
rt_uint32_t eoi; /* 0x010 */
rt_uint32_t run_priority; /* 0x014 */
rt_uint32_t hi_pend; /* 0x018 */
rt_uint32_t ns_alias_bp_c; /* 0x01C */
rt_uint32_t ns_alias_ack; /* 0x020 GIC400 only */
rt_uint32_t ns_alias_eoi; /* 0x024 GIC400 only */
rt_uint32_t ns_alias_hi_pend; /* 0x028 GIC400 only */
rt_uint32_t res1[5]; /* [0x02C, 0x040) */
rt_uint32_t integ_en_c; /* 0x040 PL390 only */
rt_uint32_t interrupt_out; /* 0x044 PL390 only */
rt_uint32_t res2[2]; /* [0x048, 0x050) */
rt_uint32_t match_c; /* 0x050 PL390 only */
rt_uint32_t enable_c; /* 0x054 PL390 only */
rt_uint32_t res3[30]; /* [0x058, 0x0FC) */
rt_uint32_t active_priority[4]; /* [0x0D0, 0xDC] GIC400 only */
rt_uint32_t ns_active_priority[4]; /* [0xE0,0xEC] GIC400 only */
rt_uint32_t res4[3];
rt_uint32_t cpu_if_ident; /* 0x0FC */
rt_uint32_t res5[948]; /* [0x100. 0xFC0) */
rt_uint32_t periph_id[8]; /* [0xFC0, 9xFF0) PL390 only */
rt_uint32_t component_id[4]; /* [0xFF0, 0xFFF] PL390 only */
};
volatile struct gic_dist_map *gic_dist =
(volatile struct gic_dist_map*)(GIC_PL390_DISTRIBUTOR_PPTR);
volatile struct gic_cpu_iface_map *gic_cpuiface =
(volatile struct gic_cpu_iface_map*)(GIC_PL390_CONTROLLER_PPTR);
/*
* The only sane way to get an GIC IRQ number that can be properly
* ACKED later is through the int_ack register. Unfortunately, reading
* this register changes the interrupt state to pending so future
* reads will not return the same value For this reason, we have a
* global variable to store the IRQ number.
*/
static rt_uint32_t active_irq = GIC390_IRQ_NONE;
rt_inline int is_irq_edge_triggered(int irq)
{
int word = irq / 16;
int bit = ((irq & 0xf) * 2);
return !!(gic_dist->config[word] & BIT(bit + 1));
}
rt_inline void dist_pending_clr(int irq)
{
int word = irq / 32;
int bit = irq & 0x1f;
gic_dist->pending_clr[word] = BIT(bit);
}
rt_inline void dist_init(void)
{
int i;
int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1);
gic_dist->enable = 0;
for (i = 0; i < nirqs; i += 32)
{
/* disable */
gic_dist->enable_clr[i / 32] = IRQ_SET_ALL;
/* clear pending */
gic_dist->pending_clr[i / 32] = IRQ_SET_ALL;
}
/* reset interrupts priority */
for (i = 32; i < nirqs; i += 4)
{
gic_dist->priority[i / 4] = 0x0;
}
/*
* reset int target to cpu 0
* (Should really query which processor we're running on and use that)
*/
for (i = 0; i < nirqs; i += 4)
{
gic_dist->targets[i / 4] = TARGET_CPU0_ALLINT;
}
/* level-triggered, 1-N */
for (i = 64; i < nirqs; i += 32)
{
gic_dist->config[i / 32] = 0;
}
/* enable the int controller */
gic_dist->enable = 1;
}
rt_inline void cpu_iface_init(void)
{
rt_uint32_t i;
/* For non-Exynos4, the registers are banked per CPU, need to clear them */
gic_dist->enable_clr[0] = IRQ_SET_ALL;
gic_dist->pending_clr[0] = IRQ_SET_ALL;
gic_dist->priority[0] = 0x00;
/* put everything in group 0 */
/* clear any software generated interrupts */
for (i = 0; i < 16; i += 4)
{
gic_dist->sgi_pending_clr[i / 4] = IRQ_SET_ALL;
}
gic_cpuiface->icontrol = 0;
gic_cpuiface->pri_msk_c = 0x000000f0;
gic_cpuiface->pb_c = 0x00000003;
while (((i = gic_cpuiface->int_ack) & IRQ_MASK) != GIC390_IRQ_NONE)
{
gic_cpuiface->eoi = i;
}
gic_cpuiface->icontrol = 0x1;
}
void arm_gic_irq_init(void)
{
dist_init();
cpu_iface_init();
}
int arm_gic_get_active_irq(void)
{
int irq;
if (!IS_IRQ_VALID(active_irq))
{
active_irq = gic_cpuiface->int_ack;
}
if (IS_IRQ_VALID(active_irq))
{
irq = active_irq & IRQ_MASK;
}
else
{
irq = GIC390_IRQ_NONE;
}
return irq;
}
void arm_gic_mask(int irq)
{
int word = irq / 32;
int bit = irq & 0x1f;
gic_dist->enable_clr[word] = BIT(bit);
}
void arm_gic_umask(int irq)
{
int word = irq / 32;
int bit = irq & 0x1f;
gic_dist->enable_set[word] = BIT(bit);
}
void arm_gic_ack(int irq)
{
if (!(IS_IRQ_VALID(active_irq) && (active_irq & IRQ_MASK) == irq))
{
return;
}
if (is_irq_edge_triggered(irq))
{
dist_pending_clr(irq);
}
gic_cpuiface->eoi = active_irq;
active_irq = GIC390_IRQ_NONE;
}
int rt_hw_interrupt_get_irq(void)
{
return arm_gic_get_active_irq();
}
void rt_hw_interrupt_ack(int fiq_irq)
{
return arm_gic_ack(fiq_irq);
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-31 GuEe-GUI the first version
*/
#ifndef GIC_PL390_H__
#define GIC_PL390_H__
#include <board.h>
#define GIC390_SPECIAL_IRQ_START 1020
#define GIC390_IRQ_NONE 1023
void arm_gic_irq_init(void);
int arm_gic_get_active_irq(void);
void arm_gic_ack(int irq);
void arm_gic_mask(int irq);
void arm_gic_umask(int irq);
#endif
+6 -1
View File
@@ -35,7 +35,7 @@ _start:
// ldr x2, =EL1_stack
// mov sp, x2
ldr x1, =_start
ldr x1, =init_el1_stack_limit
// set up EL1
mrs x0, CurrentEL // CurrentEL Register. bit 2, 3. Others reserved
@@ -109,3 +109,8 @@ _start:
bl entry
// for failsafe, halt this core too
b .L__current_cpu_idle
.bss
.align 3
init_el1_stack:
.space 4096
init_el1_stack_limit:
+19
View File
@@ -9,6 +9,7 @@
* 2019-07-28 zdzn add smp support
* 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues,
* write addr to mailbox3 to startup smp, and we use mailbox0 for ipi
* 2021-07-31 GuEe-GUI Add gic pl390 branch
*/
#include <rthw.h>
@@ -19,6 +20,10 @@
#include "armv8.h"
#include "interrupt.h"
#ifdef BSP_USING_GIC390
#include <gic_pl390.h>
#endif
#define MAX_HANDLERS 72
#ifdef RT_USING_SMP
@@ -41,6 +46,7 @@ void rt_hw_vector_init(void)
rt_hw_set_current_vbar((rt_ubase_t)&system_vectors); // cpu_gcc.S
}
#ifndef BSP_USING_GIC
static void default_isr_handler(int vector, void *param)
{
#ifdef RT_USING_SMP
@@ -49,12 +55,16 @@ static void default_isr_handler(int vector, void *param)
rt_kprintf("unhandled irq: %d\n",vector);
#endif
}
#endif
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
#ifdef BSP_USING_GIC390
arm_gic_irq_init();
#else
rt_uint32_t index;
/* mask all of interrupts */
@@ -76,6 +86,7 @@ void rt_hw_interrupt_init(void)
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
#endif
}
/**
@@ -84,6 +95,9 @@ void rt_hw_interrupt_init(void)
*/
void rt_hw_interrupt_mask(int vector)
{
#ifdef BSP_USING_GIC390
arm_gic_mask(vector);
#else
if (vector < 32)
{
IRQ_DISABLE1 = (1 << vector);
@@ -98,6 +112,7 @@ void rt_hw_interrupt_mask(int vector)
vector = vector - 64;
IRQ_DISABLE_BASIC = (1 << vector);
}
#endif
}
/**
@@ -106,6 +121,9 @@ void rt_hw_interrupt_mask(int vector)
*/
void rt_hw_interrupt_umask(int vector)
{
#ifdef BSP_USING_GIC390
arm_gic_umask(vector);
#else
if (vector < 32)
{
IRQ_ENABLE1 = (1 << vector);
@@ -120,6 +138,7 @@ void rt_hw_interrupt_umask(int vector)
vector = vector - 64;
IRQ_ENABLE_BASIC = (1 << vector);
}
#endif
}
/**
-2
View File
@@ -14,8 +14,6 @@
#include <rthw.h>
#include <board.h>
#include "raspi.h"
#define INT_IRQ 0x00
#define INT_FIQ 0x01
+24 -1
View File
@@ -4,7 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*
* Date Author Notes
* 2018-10-06 ZhaoXiaowei the first version
* 2018-10-06 ZhaoXiaowei the first version
* 2021-07-31 GuEe-GUI Add gic_pl390 branch
*/
#include <rtthread.h>
@@ -13,6 +14,10 @@
#include "interrupt.h"
#include "armv8.h"
#ifdef BSP_USING_GIC390
#include <gic_pl390.h>
#endif
extern struct rt_thread *rt_current_thread;
#ifdef RT_USING_FINSH
extern long list_thread(void);
@@ -65,6 +70,8 @@ void rt_hw_trap_irq(void)
uint32_t irq;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
#ifndef BSP_USING_GIC390
uint32_t value = 0;
value = IRQ_PEND_BASIC & 0x3ff;
#ifdef BSP_USING_CORETIMER
@@ -100,6 +107,15 @@ void rt_hw_trap_irq(void)
value &= 0x0f;
irq = __rt_ffs(value) + 63;
}
#else
irq = arm_gic_get_active_irq();
if (irq == GIC390_IRQ_NONE)
{
/* Spurious interrupt */
return;
}
#endif
/* get interrupt service routine */
isr_func = isr_table[irq].handler;
@@ -113,11 +129,17 @@ void rt_hw_trap_irq(void)
/* turn to interrupt service routine */
isr_func(irq, param);
}
#ifndef BSP_USING_GIC390
}
#else
/* end of interrupt */
arm_gic_ack(irq);
#endif
}
void rt_hw_trap_fiq(void)
{
#ifndef BSP_USING_GIC390
void *param;
uint32_t irq;
rt_isr_handler_t isr_func;
@@ -199,4 +221,5 @@ void rt_hw_trap_fiq(void)
isr_func(irq, param);
}
}
#endif
}