mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-22 11:30:01 +08:00
[libcpu/aarch64] add smp support
This commit is contained in:
@@ -6,18 +6,23 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
* 2021-12-28 GuEe-GUI add fpu support
|
||||
*/
|
||||
|
||||
#ifndef __ARMV8_H__
|
||||
#define __ARMV8_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
/* the exception stack without VFP registers */
|
||||
struct rt_hw_exp_stack
|
||||
{
|
||||
unsigned long long pc;
|
||||
unsigned long long spsr;
|
||||
unsigned long long x30;
|
||||
unsigned long long xz;
|
||||
unsigned long long xzr;
|
||||
unsigned long long fpcr;
|
||||
unsigned long long fpsr;
|
||||
unsigned long long x28;
|
||||
unsigned long long x29;
|
||||
unsigned long long x26;
|
||||
@@ -48,6 +53,8 @@ struct rt_hw_exp_stack
|
||||
unsigned long long x3;
|
||||
unsigned long long x0;
|
||||
unsigned long long x1;
|
||||
|
||||
unsigned long long fpu[16];
|
||||
};
|
||||
|
||||
#define SP_ELx ( ( unsigned long long ) 0x01 )
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-18 Jesven the first version
|
||||
*/
|
||||
|
||||
.macro SAVE_FPU, reg
|
||||
STR Q0, [\reg, #-0x10]!
|
||||
STR Q1, [\reg, #-0x10]!
|
||||
STR Q2, [\reg, #-0x10]!
|
||||
STR Q3, [\reg, #-0x10]!
|
||||
STR Q4, [\reg, #-0x10]!
|
||||
STR Q5, [\reg, #-0x10]!
|
||||
STR Q6, [\reg, #-0x10]!
|
||||
STR Q7, [\reg, #-0x10]!
|
||||
STR Q8, [\reg, #-0x10]!
|
||||
STR Q9, [\reg, #-0x10]!
|
||||
STR Q10, [\reg, #-0x10]!
|
||||
STR Q11, [\reg, #-0x10]!
|
||||
STR Q12, [\reg, #-0x10]!
|
||||
STR Q13, [\reg, #-0x10]!
|
||||
STR Q14, [\reg, #-0x10]!
|
||||
STR Q15, [\reg, #-0x10]!
|
||||
.endm
|
||||
|
||||
.macro RESTORE_FPU, reg
|
||||
LDR Q15, [\reg], #0x10
|
||||
LDR Q14, [\reg], #0x10
|
||||
LDR Q13, [\reg], #0x10
|
||||
LDR Q12, [\reg], #0x10
|
||||
LDR Q11, [\reg], #0x10
|
||||
LDR Q10, [\reg], #0x10
|
||||
LDR Q9, [\reg], #0x10
|
||||
LDR Q8, [\reg], #0x10
|
||||
LDR Q7, [\reg], #0x10
|
||||
LDR Q6, [\reg], #0x10
|
||||
LDR Q5, [\reg], #0x10
|
||||
LDR Q4, [\reg], #0x10
|
||||
LDR Q3, [\reg], #0x10
|
||||
LDR Q2, [\reg], #0x10
|
||||
LDR Q1, [\reg], #0x10
|
||||
LDR Q0, [\reg], #0x10
|
||||
.endm
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -134,6 +134,57 @@ __asm_flush_dcache_range:
|
||||
dsb sy
|
||||
ret
|
||||
|
||||
/* void __asm_invalidate_dcache_range(start, end)
|
||||
*
|
||||
* invalidate data cache in the range
|
||||
*
|
||||
* x0: start address
|
||||
* x1: end address
|
||||
*/
|
||||
.globl __asm_invalidate_dcache_range
|
||||
__asm_invalidate_dcache_range:
|
||||
mrs x3, ctr_el0
|
||||
lsr x3, x3, #16
|
||||
and x3, x3, #0xf
|
||||
mov x2, #4
|
||||
lsl x2, x2, x3 /* cache line size */
|
||||
|
||||
/* x2 <- minimal cache line size in cache system */
|
||||
sub x3, x2, #1
|
||||
bic x0, x0, x3
|
||||
|
||||
1: dc ivac, x0 /* invalidate data or unified cache */
|
||||
add x0, x0, x2
|
||||
cmp x0, x1
|
||||
b.lo 1b
|
||||
dsb sy
|
||||
ret
|
||||
|
||||
/* void __asm_invalidate_icache_range(start, end)
|
||||
*
|
||||
* invalidate icache in the range
|
||||
*
|
||||
* x0: start address
|
||||
* x1: end address
|
||||
*/
|
||||
.globl __asm_invalidate_icache_range
|
||||
__asm_invalidate_icache_range:
|
||||
mrs x3, ctr_el0
|
||||
and x3, x3, #0xf
|
||||
mov x2, #4
|
||||
lsl x2, x2, x3 /* cache line size */
|
||||
|
||||
/* x2 <- minimal cache line size in cache system */
|
||||
sub x3, x2, #1
|
||||
bic x0, x0, x3
|
||||
|
||||
1: ic ivau, x0 /* invalidate instruction or unified cache */
|
||||
add x0, x0, x2
|
||||
cmp x0, x1
|
||||
b.lo 1b
|
||||
dsb sy
|
||||
ret
|
||||
|
||||
/*
|
||||
* void __asm_invalidate_icache_all(void)
|
||||
*
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-12-28 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
void __asm_flush_dcache_all(void);
|
||||
void __asm_invalidate_dcache_all(void);
|
||||
void __asm_flush_dcache_range(unsigned long start, unsigned long end);
|
||||
void __asm_invalidate_dcache_range(unsigned long start, unsigned long end);
|
||||
|
||||
void __asm_invalidate_icache_all(void);
|
||||
void __asm_invalidate_icache_range(unsigned long start, unsigned long end);
|
||||
|
||||
void rt_hw_dcache_flush_all(void)
|
||||
{
|
||||
__asm_flush_dcache_all();
|
||||
}
|
||||
|
||||
void rt_hw_dcache_invalidate_all(void)
|
||||
{
|
||||
__asm_invalidate_dcache_all();
|
||||
}
|
||||
|
||||
void rt_hw_dcache_flush_range(unsigned long start_addr, unsigned long size)
|
||||
{
|
||||
__asm_flush_dcache_range(start_addr, start_addr + size);
|
||||
}
|
||||
|
||||
void rt_hw_dcache_invalidate_range(unsigned long start_addr,unsigned long size)
|
||||
{
|
||||
__asm_invalidate_dcache_range(start_addr, start_addr + size);
|
||||
}
|
||||
|
||||
void rt_hw_icache_invalidate_all()
|
||||
{
|
||||
__asm_invalidate_icache_all();
|
||||
}
|
||||
|
||||
void rt_hw_icache_invalidate_range(unsigned long start_addr, int size)
|
||||
{
|
||||
__asm_invalidate_icache_range(start_addr, start_addr + size);
|
||||
}
|
||||
|
||||
void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_INVALIDATE)
|
||||
{
|
||||
rt_hw_icache_invalidate_range((unsigned long)addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_FLUSH)
|
||||
{
|
||||
rt_hw_dcache_flush_range((unsigned long)addr, size);
|
||||
}
|
||||
else if (ops == RT_HW_CACHE_INVALIDATE)
|
||||
{
|
||||
rt_hw_dcache_invalidate_range((unsigned long)addr, size);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -7,8 +7,17 @@
|
||||
* Date Author Notes
|
||||
* 2018-10-06 ZhaoXiaowei the first version
|
||||
* 2021-11-04 GuEe-GUI set sp with SP_ELx
|
||||
* 2021-12-28 GuEe-GUI add fpu and smp support
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
#include "asm_fpu.h"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
*enable gtimer
|
||||
*/
|
||||
@@ -58,6 +67,7 @@ rt_hw_get_gtimer_frq:
|
||||
|
||||
.macro SAVE_CONTEXT
|
||||
/* Save the entire context. */
|
||||
SAVE_FPU SP
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
@@ -73,6 +83,9 @@ rt_hw_get_gtimer_frq:
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
MRS X28, FPCR
|
||||
MRS X29, FPSR
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
|
||||
MRS X0, CurrentEL
|
||||
@@ -107,6 +120,7 @@ rt_hw_get_gtimer_frq:
|
||||
|
||||
.macro SAVE_CONTEXT_T
|
||||
/* Save the entire context. */
|
||||
SAVE_FPU SP
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
@@ -122,6 +136,9 @@ rt_hw_get_gtimer_frq:
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
MRS X28, FPCR
|
||||
MRS X29, FPSR
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
|
||||
MRS X0, CurrentEL
|
||||
@@ -182,6 +199,9 @@ rt_hw_get_gtimer_frq:
|
||||
0:
|
||||
|
||||
LDP X30, XZR, [SP], #0x10
|
||||
LDP X28, X29, [SP], #0x10
|
||||
MSR FPCR, X28
|
||||
MSR FPSR, X29
|
||||
LDP X28, X29, [SP], #0x10
|
||||
LDP X26, X27, [SP], #0x10
|
||||
LDP X24, X25, [SP], #0x10
|
||||
@@ -197,6 +217,7 @@ rt_hw_get_gtimer_frq:
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
RESTORE_FPU SP
|
||||
|
||||
ERET
|
||||
|
||||
@@ -227,22 +248,46 @@ rt_hw_interrupt_enable_exit:
|
||||
RET
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_to(rt_ubase_t to);
|
||||
* r0 --> to
|
||||
* #endif
|
||||
* X0 --> to
|
||||
* X1 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
#ifdef RT_USING_SMP
|
||||
STR X0, [SP, #-0x8]!
|
||||
MOV X0, X1
|
||||
BL rt_cpus_lock_status_restore
|
||||
LDR X0, [SP], #0x8
|
||||
#endif /*RT_USING_SMP*/
|
||||
LDR X0, [X0]
|
||||
RESTORE_CONTEXT
|
||||
|
||||
.text
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
* #endif
|
||||
* X0 --> from
|
||||
* X1 --> to
|
||||
* X2 --> to_thread
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
#ifdef RT_USING_SMP
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STR X30, [SP, #-0x8]!
|
||||
MOV X0, X2
|
||||
BL rt_cpus_lock_status_restore
|
||||
LDR X30, [SP], #0x8
|
||||
LDP X0, X1, [SP], #0x10
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
MOV X8,X0
|
||||
MOV X9,X1
|
||||
@@ -262,19 +307,32 @@ rt_hw_context_switch:
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
ADR X2, rt_thread_switch_interrupt_flag
|
||||
#ifdef RT_USING_SMP
|
||||
/* x0 = context */
|
||||
/* x1 = ¤t_thread->sp */
|
||||
/* x2 = &to_thread->sp, */
|
||||
/* x3 = to_thread TCB */
|
||||
STR X0, [X1]
|
||||
LDR X0, [x2]
|
||||
MOV SP, X0
|
||||
MOV X0, X3
|
||||
BL rt_cpus_lock_status_restore
|
||||
MOV X0, SP
|
||||
RESTORE_CONTEXT
|
||||
#else
|
||||
LDR X2, =rt_thread_switch_interrupt_flag
|
||||
LDR X3, [X2]
|
||||
CMP X3, #1
|
||||
B.EQ _reswitch
|
||||
ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread
|
||||
LDR X4, =rt_interrupt_from_thread // set rt_interrupt_from_thread
|
||||
MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1
|
||||
STR X0, [X4]
|
||||
STR X3, [X2]
|
||||
_reswitch:
|
||||
ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread
|
||||
LDR X2, =rt_interrupt_to_thread // set rt_interrupt_to_thread
|
||||
STR X1, [X2]
|
||||
RET
|
||||
|
||||
#endif
|
||||
.text
|
||||
|
||||
// -- Exception handlers ----------------------------------
|
||||
@@ -308,10 +366,15 @@ vector_irq:
|
||||
BL rt_interrupt_leave
|
||||
|
||||
LDP X0, X1, [SP], #0x10
|
||||
#ifdef RT_USING_SMP
|
||||
/* Never reture If can switch */
|
||||
BL rt_scheduler_do_irq_switch
|
||||
MOV X0, SP
|
||||
#endif
|
||||
|
||||
// if rt_thread_switch_interrupt_flag set, jump to
|
||||
// rt_hw_context_switch_interrupt_do and don't return
|
||||
ADR X1, rt_thread_switch_interrupt_flag
|
||||
LDR X1, =rt_thread_switch_interrupt_flag
|
||||
LDR X2, [X1]
|
||||
CMP X2, #1
|
||||
B.NE vector_irq_exit
|
||||
@@ -319,11 +382,11 @@ vector_irq:
|
||||
MOV X2, #0 // clear flag
|
||||
STR X2, [X1]
|
||||
|
||||
ADR X3, rt_interrupt_from_thread
|
||||
LDR X3, =rt_interrupt_from_thread
|
||||
LDR X4, [X3]
|
||||
STR x0, [X4] // store sp in preempted tasks's TCB
|
||||
|
||||
ADR x3, rt_interrupt_to_thread
|
||||
LDR x3, =rt_interrupt_to_thread
|
||||
LDR X4, [X3]
|
||||
LDR x0, [X4] // get new task's stack pointer
|
||||
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
*/
|
||||
|
||||
#ifndef __CP15_H__
|
||||
#define __CP15_H__
|
||||
|
||||
#ifndef __STATIC_FORCEINLINE
|
||||
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
|
||||
#endif
|
||||
|
||||
#define __WFI() __asm__ volatile ("wfi":::"memory")
|
||||
|
||||
#define __WFE() __asm__ volatile ("wfe":::"memory")
|
||||
|
||||
#define __SEV() __asm__ volatile ("sev")
|
||||
|
||||
__STATIC_FORCEINLINE void __ISB(void)
|
||||
{
|
||||
__asm__ volatile ("isb 0xF":::"memory");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Data Synchronization Barrier
|
||||
\details Acts as a special kind of Data Memory Barrier.
|
||||
It completes when all explicit memory accesses before this instruction complete.
|
||||
*/
|
||||
__STATIC_FORCEINLINE void __DSB(void)
|
||||
{
|
||||
__asm__ volatile ("dsb 0xF":::"memory");
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Data Memory Barrier
|
||||
\details Ensures the apparent order of the explicit memory operations before
|
||||
and after the instruction, without ensuring their completion.
|
||||
*/
|
||||
|
||||
__STATIC_FORCEINLINE void __DMB(void)
|
||||
{
|
||||
__asm__ volatile ("dmb 0xF":::"memory");
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
static inline void send_ipi_msg(int cpu, int ipi_vector)
|
||||
{
|
||||
IPI_MAILBOX_SET(cpu) = 1 << ipi_vector;
|
||||
}
|
||||
|
||||
static inline void setup_bootstrap_addr(int cpu, int addr)
|
||||
{
|
||||
CORE_MAILBOX3_SET(cpu) = addr;
|
||||
}
|
||||
|
||||
static inline void enable_cpu_ipi_intr(int cpu)
|
||||
{
|
||||
COREMB_INTCTL(cpu) = IPI_MAILBOX_INT_MASK;
|
||||
}
|
||||
|
||||
static inline void enable_cpu_timer_intr(int cpu)
|
||||
{
|
||||
CORETIMER_INTCTL(cpu) = 0x8;
|
||||
}
|
||||
|
||||
static inline void enable_cntv(void)
|
||||
{
|
||||
rt_uint32_t cntv_ctl;
|
||||
cntv_ctl = 1;
|
||||
asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL
|
||||
}
|
||||
|
||||
static inline void disable_cntv(void)
|
||||
{
|
||||
rt_uint32_t cntv_ctl;
|
||||
cntv_ctl = 0;
|
||||
asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL
|
||||
}
|
||||
|
||||
static inline void mask_cntv(void)
|
||||
{
|
||||
rt_uint32_t cntv_ctl;
|
||||
cntv_ctl = 2;
|
||||
asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL
|
||||
}
|
||||
|
||||
static inline void unmask_cntv(void)
|
||||
{
|
||||
rt_uint32_t cntv_ctl;
|
||||
cntv_ctl = 1;
|
||||
asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL
|
||||
}
|
||||
|
||||
static inline rt_uint64_t read_cntvct(void)
|
||||
{
|
||||
rt_uint32_t val,val1;
|
||||
asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (val),"=r" (val1));
|
||||
return (val);
|
||||
}
|
||||
|
||||
static inline rt_uint64_t read_cntvoff(void)
|
||||
{
|
||||
|
||||
rt_uint64_t val;
|
||||
asm volatile("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val));
|
||||
return (val);
|
||||
}
|
||||
|
||||
static inline rt_uint32_t read_cntv_tval(void)
|
||||
{
|
||||
rt_uint32_t val;
|
||||
asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val) );
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static inline void write_cntv_tval(rt_uint32_t val)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val) );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline rt_uint32_t read_cntfrq(void)
|
||||
{
|
||||
rt_uint32_t val;
|
||||
asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val) );
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static inline rt_uint32_t read_cntctrl(void)
|
||||
{
|
||||
rt_uint32_t val;
|
||||
asm volatile ("mrc p15, 0, %0, c14, c1, 0" : "=r"(val) );
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t write_cntctrl(uint32_t val)
|
||||
{
|
||||
|
||||
asm volatile ("mcr p15, 0, %0, c14, c1, 0" : :"r"(val) );
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long rt_cpu_get_smp_id(void);
|
||||
|
||||
void rt_cpu_mmu_disable(void);
|
||||
void rt_cpu_mmu_enable(void);
|
||||
void rt_cpu_tlb_set(volatile unsigned long*);
|
||||
|
||||
void rt_cpu_dcache_clean_flush(void);
|
||||
void rt_cpu_icache_flush(void);
|
||||
|
||||
void rt_cpu_vector_set_base(rt_ubase_t addr);
|
||||
void rt_hw_mmu_init(void);
|
||||
void rt_hw_vector_init(void);
|
||||
|
||||
void set_timer_counter(unsigned int counter);
|
||||
void set_timer_control(unsigned int control);
|
||||
#endif
|
||||
+55
-35
@@ -7,25 +7,38 @@
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
* 2019-07-28 zdzn add smp support
|
||||
* 2021-12-21 GuEe-GUI set tpidr_el2 as multiprocessor id instead of mpidr_el1
|
||||
* 2021-12-28 GuEe-GUI add spinlock for aarch64
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
#include "cp15.h"
|
||||
#include <cpuport.h>
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* The more common mpidr_el1 table, redefine it in BSP if it is in other cases */
|
||||
RT_WEAK rt_uint64_t rt_cpu_mpidr_early[] =
|
||||
{
|
||||
[0] = 0x80000000,
|
||||
[1] = 0x80000001,
|
||||
[2] = 0x80000002,
|
||||
[3] = 0x80000003,
|
||||
[4] = 0x80000004,
|
||||
[5] = 0x80000005,
|
||||
[6] = 0x80000006,
|
||||
[7] = 0x80000007,
|
||||
[RT_CPUS_NR] = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
int rt_hw_cpu_id(void)
|
||||
{
|
||||
int cpu_id;
|
||||
rt_base_t value;
|
||||
|
||||
__asm__ volatile (
|
||||
"mrs %0, mpidr_el1"
|
||||
:"=r"(value)
|
||||
);
|
||||
cpu_id = value & 0xf;
|
||||
return cpu_id;
|
||||
};
|
||||
__asm__ volatile ("mrs %0, tpidr_el1":"=r"(value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
|
||||
@@ -35,38 +48,45 @@ void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
|
||||
|
||||
void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned long newval;
|
||||
rt_hw_spinlock_t lockval;
|
||||
__asm__ __volatile__(
|
||||
"pld [%0]"
|
||||
::"r"(&lock->slock)
|
||||
);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldrex %0, [%3]\n"
|
||||
" add %1, %0, %4\n"
|
||||
" strex %2, %1, [%3]\n"
|
||||
" teq %2, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
|
||||
: "r" (&lock->slock), "I" (1 << 16)
|
||||
: "cc");
|
||||
|
||||
while (lockval.tickets.next != lockval.tickets.owner) {
|
||||
__WFE();
|
||||
lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner);
|
||||
}
|
||||
rt_hw_spinlock_t lock_val, new_lockval;
|
||||
unsigned int tmp;
|
||||
|
||||
__asm__ volatile (
|
||||
/* Increment the next ticket. */
|
||||
" prfm pstl1strm, %3\n"
|
||||
"1: ldaxr %w0, %3\n"
|
||||
" add %w1, %w0, %w5\n"
|
||||
" stxr %w2, %w1, %3\n"
|
||||
" cbnz %w2, 1b\n"
|
||||
/* Check wether we get the lock */
|
||||
" eor %w1, %w0, %w0, ror #16\n"
|
||||
" cbz %w1, 3f\n"
|
||||
/*
|
||||
* Didn't get lock and spin on the owner.
|
||||
* Should send a local event to avoid missing an
|
||||
* unlock before the exclusive load.
|
||||
*/
|
||||
" sevl\n"
|
||||
"2: wfe\n"
|
||||
" ldaxrh %w2, %4\n"
|
||||
" eor %w1, %w2, %w0, lsr #16\n"
|
||||
" cbnz %w1, 2b\n"
|
||||
/* got the lock. */
|
||||
"3:"
|
||||
: "=&r" (lock_val), "=&r" (new_lockval), "=&r" (tmp), "+Q" (*lock)
|
||||
: "Q" (lock->tickets.owner), "I" (1 << 16)
|
||||
: "memory");
|
||||
__DMB();
|
||||
}
|
||||
|
||||
void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
__DMB();
|
||||
lock->tickets.owner++;
|
||||
__DSB();
|
||||
__SEV();
|
||||
__asm__ volatile (
|
||||
"stlrh %w1, %0\n"
|
||||
: "=Q" (lock->tickets.owner)
|
||||
: "r" (lock->tickets.owner + 1)
|
||||
: "memory");
|
||||
}
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
|
||||
@@ -13,6 +13,13 @@
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
#define __WFI() __asm__ volatile ("wfi":::"memory")
|
||||
#define __WFE() __asm__ volatile ("wfe":::"memory")
|
||||
#define __SEV() __asm__ volatile ("sev")
|
||||
#define __ISB() __asm__ volatile ("isb 0xf":::"memory")
|
||||
#define __DSB() __asm__ volatile ("dsb 0xf":::"memory")
|
||||
#define __DMB() __asm__ volatile ("dmb 0xf":::"memory")
|
||||
|
||||
rt_inline void rt_hw_isb(void)
|
||||
{
|
||||
__asm__ volatile ("isb":::"memory");
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <gic.h>
|
||||
#include <cp15.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
struct arm_gic
|
||||
{
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-12-20 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <gtimer.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#define EL1_PHY_TIMER_IRQ_NUM 30
|
||||
|
||||
static volatile rt_uint64_t timer_step;
|
||||
|
||||
static void rt_hw_timer_isr(int vector, void *parameter)
|
||||
{
|
||||
rt_hw_set_gtimer_val(timer_step);
|
||||
rt_tick_increase();
|
||||
}
|
||||
|
||||
void rt_hw_gtimer_init(void)
|
||||
{
|
||||
rt_hw_interrupt_install(EL1_PHY_TIMER_IRQ_NUM, rt_hw_timer_isr, RT_NULL, "tick");
|
||||
__ISB();
|
||||
timer_step = rt_hw_get_gtimer_frq();
|
||||
__DSB();
|
||||
timer_step /= RT_TICK_PER_SECOND;
|
||||
rt_hw_gtimer_local_enable();
|
||||
}
|
||||
|
||||
void rt_hw_gtimer_local_enable(void)
|
||||
{
|
||||
rt_hw_gtimer_disable();
|
||||
rt_hw_set_gtimer_val(timer_step);
|
||||
rt_hw_interrupt_umask(EL1_PHY_TIMER_IRQ_NUM);
|
||||
rt_hw_gtimer_enable();
|
||||
}
|
||||
|
||||
void rt_hw_gtimer_local_disable(void)
|
||||
{
|
||||
rt_hw_gtimer_disable();
|
||||
rt_hw_interrupt_mask(EL1_PHY_TIMER_IRQ_NUM);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-12-20 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#ifndef __GTIMER_H__
|
||||
#define __GTIMER_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
void rt_hw_gtimer_init(void);
|
||||
void rt_hw_gtimer_local_enable(void);
|
||||
void rt_hw_gtimer_local_disable(void);
|
||||
|
||||
void rt_hw_gtimer_enable();
|
||||
void rt_hw_gtimer_disable();
|
||||
void rt_hw_set_gtimer_val(rt_uint64_t value);
|
||||
rt_uint64_t rt_hw_get_gtimer_val();
|
||||
rt_uint64_t rt_hw_get_cntpct_val();
|
||||
rt_uint64_t rt_hw_get_gtimer_frq();
|
||||
|
||||
#endif /* __GTIMER_H__ */
|
||||
@@ -15,16 +15,15 @@
|
||||
#include "gic.h"
|
||||
#include "armv8.h"
|
||||
#include "mmu.h"
|
||||
#include "cpuport.h"
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
/* Those variables will be accessed in ISR, so we need to share them. */
|
||||
rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
rt_ubase_t rt_thread_switch_interrupt_flag = 0;
|
||||
#endif
|
||||
|
||||
const unsigned int VECTOR_BASE = 0x00;
|
||||
extern int system_vectors;
|
||||
@@ -39,9 +38,9 @@ extern volatile rt_uint8_t rt_interrupt_nest;
|
||||
static void default_isr_handler(int vector, void *param)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector);
|
||||
rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(), vector);
|
||||
#else
|
||||
rt_kprintf("unhandled irq: %d\n",vector);
|
||||
rt_kprintf("unhandled irq: %d\n", vector);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -138,7 +137,7 @@ void rt_hw_interrupt_mask(int vector)
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
#ifndef BSP_USING_GIC
|
||||
if (vector < 32)
|
||||
if (vector < 32)
|
||||
{
|
||||
IRQ_ENABLE1 = (1 << vector);
|
||||
}
|
||||
@@ -397,7 +396,20 @@ void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
|
||||
{
|
||||
#ifdef BSP_USING_GIC
|
||||
arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
|
||||
#else
|
||||
int i;
|
||||
|
||||
__DSB();
|
||||
|
||||
for (i = 0; i < RT_CPUS_NR; ++i)
|
||||
{
|
||||
if (cpu_mask & (1 << i))
|
||||
{
|
||||
IPI_MAILBOX_SET(i) = 1 << ipi_vector;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__DSB();
|
||||
}
|
||||
|
||||
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
|
||||
|
||||
+170
-286
File diff suppressed because it is too large
Load Diff
+52
-56
@@ -4,75 +4,71 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-02-20 bigmagic first version
|
||||
* Date Author Notes
|
||||
* 2021-11-28 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef __MMU_H__
|
||||
#define __MMU_H__
|
||||
#ifndef __MMU_H_
|
||||
#define __MMU_H_
|
||||
|
||||
/*
|
||||
* CR1 bits (CP#15 CR1)
|
||||
*/
|
||||
#define CR_M (1 << 0) /* MMU enable */
|
||||
#define CR_A (1 << 1) /* Alignment abort enable */
|
||||
#define CR_C (1 << 2) /* Dcache enable */
|
||||
#define CR_W (1 << 3) /* Write buffer enable */
|
||||
#define CR_P (1 << 4) /* 32-bit exception handler */
|
||||
#define CR_D (1 << 5) /* 32-bit data address range */
|
||||
#define CR_L (1 << 6) /* Implementation defined */
|
||||
#define CR_B (1 << 7) /* Big endian */
|
||||
#define CR_S (1 << 8) /* System MMU protection */
|
||||
#define CR_R (1 << 9) /* ROM MMU protection */
|
||||
#define CR_F (1 << 10) /* Implementation defined */
|
||||
#define CR_Z (1 << 11) /* Implementation defined */
|
||||
#define CR_I (1 << 12) /* Icache enable */
|
||||
#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
|
||||
#define CR_RR (1 << 14) /* Round Robin cache replacement */
|
||||
#define CR_L4 (1 << 15) /* LDR pc can set T bit */
|
||||
#define CR_DT (1 << 16)
|
||||
#define CR_IT (1 << 18)
|
||||
#define CR_ST (1 << 19)
|
||||
#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */
|
||||
#define CR_U (1 << 22) /* Unaligned access operation */
|
||||
#define CR_XP (1 << 23) /* Extended page tables */
|
||||
#define CR_VE (1 << 24) /* Vectored interrupts */
|
||||
#define CR_EE (1 << 25) /* Exception (Big) Endian */
|
||||
#define CR_TRE (1 << 28) /* TEX remap enable */
|
||||
#define CR_AFE (1 << 29) /* Access flag enable */
|
||||
#define CR_TE (1 << 30) /* Thumb exception enable */
|
||||
#include <rtthread.h>
|
||||
|
||||
#define MMU_LEVEL_MASK 0x1ffUL
|
||||
#define MMU_MAP_ERROR_VANOTALIGN -1
|
||||
#define MMU_MAP_ERROR_PANOTALIGN -2
|
||||
#define MMU_MAP_ERROR_NOPAGE -3
|
||||
#define MMU_MAP_ERROR_CONFLICT -4
|
||||
/* normal memory wra mapping type */
|
||||
#define NORMAL_MEM 0
|
||||
/* normal nocache memory mapping type */
|
||||
#define NORMAL_NOCACHE_MEM 1
|
||||
/* device mapping type */
|
||||
#define DEVICE_MEM 2
|
||||
|
||||
#define MEM_ATTR_MEMORY ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x1UL << 2))
|
||||
#define MEM_ATTR_IO ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x2UL << 2))
|
||||
#define MMU_MAP_ERROR_VANOTALIGN (-1)
|
||||
#define MMU_MAP_ERROR_PANOTALIGN (-2)
|
||||
#define MMU_MAP_ERROR_NOPAGE (-3)
|
||||
#define MMU_MAP_ERROR_CONFLICT (-4)
|
||||
|
||||
#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000)
|
||||
struct mem_desc
|
||||
{
|
||||
unsigned long vaddr_start;
|
||||
unsigned long vaddr_end;
|
||||
unsigned long paddr_start;
|
||||
unsigned long attr;
|
||||
};
|
||||
|
||||
void mmu_init(void);
|
||||
#define MMU_AF_SHIFT 10
|
||||
#define MMU_SHARED_SHIFT 8
|
||||
#define MMU_AP_SHIFT 6
|
||||
#define MMU_MA_SHIFT 2
|
||||
|
||||
void mmu_enable(void);
|
||||
#define MMU_AP_KAUN 0UL /* kernel r/w, user none */
|
||||
#define MMU_AP_KAUA 1UL /* kernel r/w, user r/w */
|
||||
#define MMU_AP_KRUN 2UL /* kernel r, user none */
|
||||
#define MMU_AP_KRUR 3UL /* kernel r, user r */
|
||||
|
||||
int armv8_map_2M(unsigned long va, unsigned long pa, int count, unsigned long attr);
|
||||
#define MMU_MAP_CUSTOM(ap, mtype) \
|
||||
(\
|
||||
(0x1UL << MMU_AF_SHIFT) |\
|
||||
(0x2UL << MMU_SHARED_SHIFT) |\
|
||||
((ap) << MMU_AP_SHIFT) |\
|
||||
((mtype) << MMU_MA_SHIFT)\
|
||||
)
|
||||
#define MMU_MAP_K_RO MMU_MAP_CUSTOM(MMU_AP_KRUN, NORMAL_MEM)
|
||||
#define MMU_MAP_K_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_MEM)
|
||||
#define MMU_MAP_K_RW MMU_MAP_CUSTOM(MMU_AP_KAUN, NORMAL_NOCACHE_MEM)
|
||||
#define MMU_MAP_K_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUN, DEVICE_MEM)
|
||||
#define MMU_MAP_U_RO MMU_MAP_CUSTOM(MMU_AP_KRUR, NORMAL_NOCACHE_MEM)
|
||||
#define MMU_MAP_U_RWCB MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_MEM)
|
||||
#define MMU_MAP_U_RW MMU_MAP_CUSTOM(MMU_AP_KAUA, NORMAL_NOCACHE_MEM)
|
||||
#define MMU_MAP_U_DEVICE MMU_MAP_CUSTOM(MMU_AP_KAUA, DEVICE_MEM)
|
||||
|
||||
void armv8_map(unsigned long va, unsigned long pa, unsigned long size, unsigned long attr);
|
||||
void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_size_t desc_nr);
|
||||
void rt_hw_mmu_init(void);
|
||||
int rt_hw_mmu_map(unsigned long addr, unsigned long size, unsigned long attr);
|
||||
|
||||
//dcache
|
||||
void rt_hw_dcache_enable(void);
|
||||
void rt_hw_dcache_flush_all(void);
|
||||
void rt_hw_dcache_invalidate_all(void);
|
||||
void rt_hw_dcache_flush_range(unsigned long start_addr, unsigned long size);
|
||||
void rt_hw_dcache_invalidate_range(unsigned long start_addr,unsigned long size);
|
||||
void rt_hw_dcache_invalidate_all(void);
|
||||
void rt_hw_dcache_disable(void);
|
||||
|
||||
//icache
|
||||
void rt_hw_icache_enable(void);
|
||||
void rt_hw_icache_invalidate_all(void);
|
||||
void rt_hw_icache_disable(void);
|
||||
void rt_hw_icache_invalidate_all();
|
||||
void rt_hw_icache_invalidate_range(unsigned long start_addr, int size);
|
||||
|
||||
|
||||
#endif /*__MMU_H__*/
|
||||
#endif /* __MMU_H_ */
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-09 GuEe-GUI The first version
|
||||
*/
|
||||
|
||||
#include <psci.h>
|
||||
#include <smccc.h>
|
||||
#include <armv8.h>
|
||||
|
||||
typedef uint64_t (*psci_call_handle)(uint32_t fn, uint64_t arg0, uint64_t arg1, uint64_t arg2);
|
||||
|
||||
static uint64_t psci_smc_call(uint32_t fn, uint64_t arg0, uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
return arm_smc_call(fn, arg0, arg1, arg2, 0, 0, 0, 0).x0;
|
||||
}
|
||||
|
||||
static uint64_t psci_hvc_call(uint32_t fn, uint64_t arg0, uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
return arm_hvc_call(fn, arg0, arg1, arg2, 0, 0, 0, 0).x0;
|
||||
}
|
||||
|
||||
static psci_call_handle psci_call = psci_smc_call;
|
||||
|
||||
static uint64_t shutdown_args[3] = {0, 0, 0};
|
||||
static uint64_t reboot_args[3] = {0, 0, 0};
|
||||
|
||||
void arm_psci_init(uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args)
|
||||
{
|
||||
if (rt_hw_get_current_el() < 2)
|
||||
{
|
||||
psci_call = psci_hvc_call;
|
||||
}
|
||||
|
||||
if (platform_shutdown_args != RT_NULL)
|
||||
{
|
||||
shutdown_args[0] = platform_shutdown_args[0];
|
||||
shutdown_args[1] = platform_shutdown_args[1];
|
||||
shutdown_args[2] = platform_shutdown_args[2];
|
||||
}
|
||||
|
||||
if (platform_reboot_args != RT_NULL)
|
||||
{
|
||||
reboot_args[0] = platform_reboot_args[0];
|
||||
reboot_args[1] = platform_reboot_args[1];
|
||||
reboot_args[2] = platform_reboot_args[2];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t arm_psci_get_version()
|
||||
{
|
||||
return (uint32_t)psci_call(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t arm_psci_get_affinity_info(uint64_t target_affinity, uint64_t lowest_affinity_level)
|
||||
{
|
||||
return (uint32_t)psci_call(PSCI_0_2_FN_AFFINITY_INFO, target_affinity, lowest_affinity_level, 0);
|
||||
}
|
||||
|
||||
uint32_t arm_psci_get_feature(uint32_t psci_func_id)
|
||||
{
|
||||
return (uint32_t)psci_call(PSCI_1_0_FN_PSCI_FEATURES, psci_func_id, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t arm_psci_cpu_off(uint64_t state)
|
||||
{
|
||||
return (uint32_t)psci_call(PSCI_0_2_FN_CPU_OFF, state, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t arm_psci_cpu_on(uint64_t mpid, uint64_t entry)
|
||||
{
|
||||
/* [40:63] and [24:31] must be zero, other is aff3, aff2, aff1, aff0 */
|
||||
mpid = mpid & 0xff00ffffff;
|
||||
|
||||
return (uint32_t)psci_call(PSCI_0_2_FN_CPU_ON, mpid, entry, 0);
|
||||
}
|
||||
|
||||
uint32_t arm_psci_cpu_suspend(uint32_t power_state, uint64_t entry)
|
||||
{
|
||||
return (uint32_t)psci_call(PSCI_0_2_FN_CPU_SUSPEND, power_state, entry, 0);
|
||||
}
|
||||
|
||||
void arm_psci_system_off()
|
||||
{
|
||||
psci_call(PSCI_0_2_FN_SYSTEM_OFF, shutdown_args[0], shutdown_args[1], shutdown_args[2]);
|
||||
}
|
||||
|
||||
void arm_psci_system_reboot()
|
||||
{
|
||||
psci_call(PSCI_0_2_FN_SYSTEM_RESET, reboot_args[0], reboot_args[1], reboot_args[2]);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-09 GuEe-GUI The first version
|
||||
*/
|
||||
|
||||
#ifndef __PSCI_H__
|
||||
#define __PSCI_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Non-Confidential PSCI 1.0 release (30 January 2015), and errata fix for PSCI 0.2, unsupport PSCI 0.1
|
||||
*/
|
||||
#define PSCI_VER_0_2 0x00000002
|
||||
|
||||
/* PSCI 0.2 interface */
|
||||
#define PSCI_0_2_FN_BASE 0x84000000
|
||||
#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
|
||||
#define PSCI_0_2_FN_END 0x8400001F
|
||||
|
||||
#define PSCI_0_2_FN64_BASE 0xC4000000
|
||||
#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n))
|
||||
#define PSCI_0_2_FN64_END 0xC400001F
|
||||
|
||||
#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0)
|
||||
#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1)
|
||||
#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2)
|
||||
#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3)
|
||||
#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4)
|
||||
#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5)
|
||||
#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6)
|
||||
#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7)
|
||||
#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8)
|
||||
#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9)
|
||||
|
||||
#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1)
|
||||
#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3)
|
||||
#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4)
|
||||
#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
|
||||
#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
|
||||
|
||||
/* PSCI 1.0 interface */
|
||||
#define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10)
|
||||
#define PSCI_1_0_FN_CPU_FREEZE PSCI_0_2_FN(11)
|
||||
#define PSCI_1_0_FN_CPU_DEFAULT_SUSPEND PSCI_0_2_FN(12)
|
||||
#define PSCI_1_0_FN_NODE_HW_STATE PSCI_0_2_FN(13)
|
||||
#define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14)
|
||||
#define PSCI_1_0_FN_SET_SUSPEND_MODE PSCI_0_2_FN(15)
|
||||
#define PSCI_1_0_FN_STAT_RESIDENCY PSCI_0_2_FN(16)
|
||||
#define PSCI_1_0_FN_STAT_COUNT PSCI_0_2_FN(17)
|
||||
|
||||
#define PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND PSCI_0_2_FN64(12)
|
||||
#define PSCI_1_0_FN64_NODE_HW_STATE PSCI_0_2_FN64(13)
|
||||
#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14)
|
||||
#define PSCI_1_0_FN64_STAT_RESIDENCY PSCI_0_2_FN64(16)
|
||||
#define PSCI_1_0_FN64_STAT_COUNT PSCI_0_2_FN64(17)
|
||||
|
||||
/* 1KB stack per core */
|
||||
#define PSCI_STACK_SHIFT 10
|
||||
#define PSCI_STACK_SIZE (1 << PSCI_STACK_SHIFT)
|
||||
|
||||
/* PSCI affinity level state returned by AFFINITY_INFO */
|
||||
#define PSCI_AFFINITY_LEVEL_ON 0
|
||||
#define PSCI_AFFINITY_LEVEL_OFF 1
|
||||
#define PSCI_AFFINITY_LEVEL_ON_PENDING 2
|
||||
|
||||
/*
|
||||
* PSCI power state
|
||||
* power_level:
|
||||
* Level 0: cores
|
||||
* Level 1: clusters
|
||||
* Level 2: system
|
||||
* state_type:
|
||||
* value 0: standby or retention state
|
||||
* value 1: powerdown state(entry and context_id is valid)
|
||||
* state_id:
|
||||
* StateID
|
||||
*/
|
||||
#define PSCI_POWER_STATE(power_level, state_type, state_id) \
|
||||
( \
|
||||
((power_level) << 24) | \
|
||||
((state_type) << 16) | \
|
||||
((state_id) << 24) \
|
||||
)
|
||||
|
||||
/*
|
||||
* For system, cluster, core
|
||||
* 0: run
|
||||
* 1: standby(only core)
|
||||
* 2: retention
|
||||
* 3: powerdown
|
||||
*/
|
||||
#define PSCI_POWER_STATE_ID(state_id_power_level, system, cluster, core) \
|
||||
( \
|
||||
((state_id_power_level) << 12) | \
|
||||
((system) << 8) | \
|
||||
((cluster) << 4) | \
|
||||
(core) \
|
||||
)
|
||||
|
||||
#define PSCI_RET_SUCCESS 0
|
||||
#define PSCI_RET_NOT_SUPPORTED (-1)
|
||||
#define PSCI_RET_INVALID_PARAMETERS (-2)
|
||||
#define PSCI_RET_DENIED (-3)
|
||||
#define PSCI_RET_ALREADY_ON (-4)
|
||||
#define PSCI_RET_ON_PENDING (-5)
|
||||
#define PSCI_RET_INTERNAL_FAILURE (-6)
|
||||
#define PSCI_RET_NOT_PRESENT (-7)
|
||||
#define PSCI_RET_DISABLED (-8)
|
||||
#define PSCI_RET_INVALID_ADDRESS (-9)
|
||||
|
||||
void arm_psci_init(uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args);
|
||||
|
||||
uint32_t arm_psci_get_version();
|
||||
uint32_t arm_psci_get_affinity_info(uint64_t target_affinity, uint64_t lowest_affinity_level);
|
||||
uint32_t arm_psci_get_feature(uint32_t psci_func_id);
|
||||
|
||||
uint32_t arm_psci_cpu_off(uint64_t state);
|
||||
uint32_t arm_psci_cpu_on(uint64_t mpid, uint64_t entry);
|
||||
uint32_t arm_psci_cpu_suspend(uint32_t power_state, uint64_t entry);
|
||||
|
||||
void arm_psci_system_off();
|
||||
void arm_psci_system_reboot();
|
||||
|
||||
#endif /*__PSCI_H__*/
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-09 GuEe-GUI The first version
|
||||
*/
|
||||
|
||||
/*
|
||||
* smc calling convention call
|
||||
*/
|
||||
.macro SMCCC_CALL INS
|
||||
stp x8, x29, [sp,#-16]! /* push the frame pointer (x29) for the purposes of AAPCS64 compatibility */
|
||||
\INS #0
|
||||
ldp x8, x29, [sp], #16
|
||||
|
||||
stp x0, x1, [x8]
|
||||
stp x2, x3, [x8, #16]
|
||||
str x6, [x8, #32]
|
||||
ret
|
||||
.endm
|
||||
|
||||
/*
|
||||
* smc call
|
||||
*/
|
||||
.globl arm_smc_call
|
||||
arm_smc_call:
|
||||
SMCCC_CALL smc
|
||||
|
||||
/*
|
||||
* hvc call
|
||||
*/
|
||||
.globl arm_hvc_call
|
||||
arm_hvc_call:
|
||||
SMCCC_CALL hvc
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-09-09 GuEe-GUI The first version
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* The ARM SMCCC v1.0 calling convention provides the following guarantees about registers:
|
||||
* Register Modified Return State
|
||||
* X0...X3 Yes Result values
|
||||
* X4...X17 Yes Unpredictable
|
||||
* X18...X30 No Preserved
|
||||
* SP_EL0 No Preserved
|
||||
* SP_ELx No Preserved
|
||||
*/
|
||||
|
||||
struct arm_smccc_ret
|
||||
{
|
||||
uint64_t x0; /* Parameter registers */
|
||||
uint64_t x1; /* Parameter registers */
|
||||
uint64_t x2; /* Parameter registers */
|
||||
uint64_t x3; /* Parameter registers */
|
||||
uint64_t x6; /* Parameter register: Optional Session ID register */
|
||||
};
|
||||
|
||||
struct arm_smccc_ret arm_smc_call(uint32_t w0, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6, uint32_t w7);
|
||||
struct arm_smccc_ret arm_hvc_call(uint32_t w0, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6, uint32_t w7);
|
||||
@@ -8,10 +8,9 @@
|
||||
* 2011-09-23 Bernard the first version
|
||||
* 2011-10-05 Bernard add thumb mode
|
||||
* 2021-11-04 GuEe-GUI set sp with SP_ELx
|
||||
* 2021-12-28 GuEe-GUI add fpu support
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
#include <armv8.h>
|
||||
|
||||
#define INITIAL_SPSR_EL3 (PSTATE_EL3 | SP_ELx)
|
||||
@@ -35,6 +34,39 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_ad
|
||||
|
||||
stk = (rt_ubase_t*)stack_addr;
|
||||
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q0 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q0 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q1 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q1 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q2 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q2 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q3 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q3 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q4 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q4 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q5 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q5 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q6 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q6 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q7 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q7 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q8 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q8 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q9 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q9 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q10 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q10 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q11 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q11 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q12 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q12 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q13 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q13 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q14 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q14 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q15 */
|
||||
*(--stk) = (rt_ubase_t) 0; /* Q15 */
|
||||
|
||||
*(--stk) = ( rt_ubase_t ) 11; /* X1 */
|
||||
*(--stk) = ( rt_ubase_t ) parameter; /* X0 */
|
||||
*(--stk) = ( rt_ubase_t ) 33; /* X3 */
|
||||
@@ -65,6 +97,8 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_ad
|
||||
*(--stk) = ( rt_ubase_t ) 26; /* X26 */
|
||||
*(--stk) = ( rt_ubase_t ) 29; /* X29 */
|
||||
*(--stk) = ( rt_ubase_t ) 28; /* X28 */
|
||||
*(--stk) = ( rt_ubase_t ) 0; /* FPSR */
|
||||
*(--stk) = ( rt_ubase_t ) 0; /* FPCR */
|
||||
*(--stk) = ( rt_ubase_t ) 0; /* XZR - has no effect, used so there are an even number of registers. */
|
||||
*(--stk) = ( rt_ubase_t ) texit; /* X30 - procedure call link register. */
|
||||
|
||||
|
||||
@@ -64,15 +64,16 @@ void rt_hw_trap_irq(void)
|
||||
uint32_t irq;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
uint32_t value = 0;
|
||||
value = IRQ_PEND_BASIC & 0x3ff;
|
||||
uint32_t value = IRQ_PEND_BASIC & 0x3ff;
|
||||
|
||||
#ifdef BSP_USING_CORETIMER
|
||||
uint32_t cpu_id = 0;
|
||||
#ifdef RT_USING_SMP
|
||||
cpu_id = rt_hw_cpu_id();
|
||||
uint32_t cpu_id = rt_hw_cpu_id();
|
||||
uint32_t mailbox_data = IPI_MAILBOX_CLEAR(cpu_id);
|
||||
#else
|
||||
uint32_t cpu_id = 0;
|
||||
#endif
|
||||
uint32_t int_source = CORE_IRQSOURCE(cpu_id) & 0x3ff;
|
||||
|
||||
if (int_source & 0x02)
|
||||
{
|
||||
isr_func = isr_table[IRQ_ARM_TIMER].handler;
|
||||
@@ -84,8 +85,34 @@ void rt_hw_trap_irq(void)
|
||||
param = isr_table[IRQ_ARM_TIMER].param;
|
||||
isr_func(IRQ_ARM_TIMER, param);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
if (int_source & 0xf0)
|
||||
{
|
||||
/* it's a ipi interrupt */
|
||||
if (mailbox_data & 0x1)
|
||||
{
|
||||
/* clear mailbox */
|
||||
IPI_MAILBOX_CLEAR(cpu_id) = mailbox_data;
|
||||
isr_func = isr_table[IRQ_ARM_MAILBOX].handler;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
isr_table[IRQ_ARM_MAILBOX].counter++;
|
||||
#endif
|
||||
if (isr_func)
|
||||
{
|
||||
param = isr_table[IRQ_ARM_MAILBOX].param;
|
||||
isr_func(IRQ_ARM_MAILBOX, param);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE_MAILBOX3_CLEAR(cpu_id) = mailbox_data;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
/* local interrupt*/
|
||||
if (value)
|
||||
|
||||
@@ -7,16 +7,54 @@
|
||||
* 2020-01-15 bigmagic the first version
|
||||
* 2020-08-10 SummerGift support clang compiler
|
||||
* 2021-11-04 GuEe-GUI set sp with SP_ELx
|
||||
* 2021-12-28 GuEe-GUI add smp support
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
.section ".text.entrypoint","ax"
|
||||
|
||||
#define SECONDARY_STACK_SIZE 4096
|
||||
|
||||
.globl _start
|
||||
.globl secondary_cpu_start
|
||||
_start:
|
||||
/* Read cpu id */
|
||||
mrs x1, mpidr_el1
|
||||
and x1, x1, #3
|
||||
cbz x1, cpu_setup /* If cpu id > 0, stop slave cores */
|
||||
and x1, x1, #0xff
|
||||
cbnz x1, cpu_idle /* If cpu id > 0, stop slave cores */
|
||||
|
||||
secondary_cpu_start:
|
||||
#ifdef RT_USING_SMP
|
||||
/* Read cpu mpidr_el1 */
|
||||
mrs x1, mpidr_el1
|
||||
|
||||
/* Read cpu id */
|
||||
ldr x0, =rt_cpu_mpidr_early /* BSP must be defined `rt_cpu_mpidr_early' table in smp */
|
||||
mov x2, #0
|
||||
|
||||
cpu_id_confirm:
|
||||
add x2, x2, #1 /* Next cpu id inc */
|
||||
ldr x3, [x0], #8
|
||||
cmp x3, #0
|
||||
beq cpu_idle /* Mean that `rt_cpu_mpidr_early' table is end */
|
||||
cmp x3, x1
|
||||
bne cpu_id_confirm
|
||||
|
||||
/* Get cpu id success */
|
||||
sub x0, x2, #1
|
||||
msr tpidr_el1, x0 /* Save cpu id global */
|
||||
cbz x0, cpu_setup /* Only go to cpu_setup when cpu id = 0 */
|
||||
|
||||
/* Set current cpu's stack top */
|
||||
sub x0, x0, #1
|
||||
mov x1, #SECONDARY_STACK_SIZE
|
||||
adr x2, .secondary_cpu_stack_top
|
||||
msub x1, x0, x1, x2
|
||||
|
||||
b cpu_check_el
|
||||
#else
|
||||
msr tpidr_el1, xzr
|
||||
b cpu_setup
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
cpu_idle:
|
||||
wfe
|
||||
@@ -25,6 +63,7 @@ cpu_idle:
|
||||
cpu_setup:
|
||||
ldr x1, =_start
|
||||
|
||||
cpu_check_el:
|
||||
mrs x0, CurrentEL /* CurrentEL Register. bit 2, 3. Others reserved */
|
||||
and x0, x0, #12 /* Clear reserved bits */
|
||||
|
||||
@@ -84,15 +123,41 @@ cpu_in_el1:
|
||||
bic x1, x1, #(1 << 1) /* Disable Alignment check */
|
||||
msr sctlr_el1, x1
|
||||
|
||||
ldr x1, =__bss_start
|
||||
ldr w2, =__bss_size
|
||||
#ifdef RT_USING_SMP
|
||||
ldr x1, =_start
|
||||
cmp sp, x1
|
||||
bne secondary_cpu_c_start
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
clean_bss_loop:
|
||||
cbz w2, jump_to_entry
|
||||
str xzr, [x1], #8
|
||||
sub w2, w2, #8
|
||||
cbnz w2, clean_bss_loop
|
||||
ldr x0, =__bss_start
|
||||
ldr x1, =__bss_end
|
||||
sub x2, x1, x0
|
||||
mov x3, x1
|
||||
cmp x2, #7
|
||||
bls clean_bss_check
|
||||
|
||||
clean_bss_loop_quad:
|
||||
str xzr, [x0], #8
|
||||
sub x2, x3, x0
|
||||
cmp x2, #7
|
||||
bhi clean_bss_loop_quad
|
||||
cmp x1, x0
|
||||
bls jump_to_entry
|
||||
|
||||
clean_bss_loop_byte:
|
||||
str xzr, [x0], #1
|
||||
|
||||
clean_bss_check:
|
||||
cmp x1, x0
|
||||
bhi clean_bss_loop_byte
|
||||
|
||||
jump_to_entry:
|
||||
b rtthread_startup
|
||||
b cpu_idle /* For failsafe, halt this core too */
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
.align 12
|
||||
.secondary_cpu_stack:
|
||||
.space (SECONDARY_STACK_SIZE * (RT_CPUS_NR - 1))
|
||||
.secondary_cpu_stack_top:
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user