增加所有文件
This commit is contained in:
315
arch/armv7-r/arm_faults.c
Normal file
315
arch/armv7-r/arm_faults.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <bits.h>
|
||||
#include <param.h>
|
||||
#include <ctype.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <armv7-r/register.h>
|
||||
#include <armv7-r/exceptions.h>
|
||||
#include <armv7-r/arm.h>
|
||||
|
||||
#if CONFIG_OS_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#endif
|
||||
|
||||
static void dump_stack(const void *ptr, size_t len)
|
||||
{
|
||||
addr_t address = (addr_t)ptr;
|
||||
size_t count;
|
||||
|
||||
for (count = 0 ; count < len; count += 16) {
|
||||
union {
|
||||
uint32_t buf[4];
|
||||
uint8_t cbuf[16];
|
||||
} u;
|
||||
size_t s = ROUNDUP(MIN(len - count, 16), 4);
|
||||
size_t i;
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "0x%08x: ", address);
|
||||
for (i = 0; i < s / 4; i++) {
|
||||
u.buf[i] = ((const uint32_t *)address)[i];
|
||||
ssdk_printf(SSDK_EMERG, "%08x ", u.buf[i]);
|
||||
}
|
||||
for (; i < 4; i++) {
|
||||
ssdk_printf(SSDK_EMERG, " ");
|
||||
}
|
||||
ssdk_printf(SSDK_EMERG, "|");
|
||||
|
||||
for (i=0; i < 16; i++) {
|
||||
unsigned char c = u.cbuf[i];
|
||||
if (i < s && isprint(c)) {
|
||||
ssdk_printf(SSDK_EMERG, "%c", c);
|
||||
} else {
|
||||
ssdk_printf(SSDK_EMERG, ".");
|
||||
}
|
||||
}
|
||||
ssdk_printf(SSDK_EMERG, "|\r\n");
|
||||
address += 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_mode_regs(uint32_t spsr, uint32_t svc_r13, uint32_t svc_r14)
|
||||
{
|
||||
struct arm_mode_regs regs;
|
||||
arm_save_mode_regs(®s);
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_USR) ? '*' : ' ', "usr", regs.usr_r13, regs.usr_r14);
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", 'a', "svc", regs.svc_r13, regs.svc_r14);
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", svc_r13, svc_r14);
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
|
||||
ssdk_printf(SSDK_EMERG, "%c%s r13 0x%08x r14 0x%08x\r\n", ((spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
|
||||
|
||||
// dump the bottom of the current stack
|
||||
addr_t stack;
|
||||
switch (spsr & MODE_MASK) {
|
||||
case MODE_FIQ:
|
||||
stack = regs.fiq_r13;
|
||||
break;
|
||||
case MODE_IRQ:
|
||||
stack = regs.irq_r13;
|
||||
break;
|
||||
case MODE_SVC:
|
||||
stack = svc_r13;
|
||||
break;
|
||||
case MODE_UND:
|
||||
stack = regs.und_r13;
|
||||
break;
|
||||
case MODE_SYS:
|
||||
stack = regs.sys_r13;
|
||||
break;
|
||||
default:
|
||||
stack = 0;
|
||||
}
|
||||
|
||||
if (stack != 0) {
|
||||
ssdk_printf(SSDK_EMERG, "bottom of stack at 0x%08x:\r\n", (unsigned int)stack);
|
||||
dump_stack((void *)stack, 128);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_fault_frame(struct arm_fault_frame *frame)
|
||||
{
|
||||
#if CONFIG_OS_FREERTOS
|
||||
TaskHandle_t current_thread = xTaskGetCurrentTaskHandle();
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "current_thread %p, name %s\r\n",
|
||||
current_thread, current_thread ? pcTaskGetName(current_thread) : "");
|
||||
#endif
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\r\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
|
||||
ssdk_printf(SSDK_EMERG, "r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\r\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
|
||||
ssdk_printf(SSDK_EMERG, "r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\r\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
|
||||
ssdk_printf(SSDK_EMERG, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\r\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
|
||||
ssdk_printf(SSDK_EMERG, "spsr 0x%08x\r\n", frame->spsr);
|
||||
|
||||
dump_mode_regs(frame->spsr, (uintptr_t)(frame + 1), frame->lr);
|
||||
}
|
||||
|
||||
static void dump_iframe(struct arm_iframe *frame)
|
||||
{
|
||||
ssdk_printf(SSDK_EMERG, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\r\n", frame->r0, frame->r1, frame->r2, frame->r3);
|
||||
ssdk_printf(SSDK_EMERG, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\r\n", frame->r12, frame->usp, frame->ulr, frame->pc);
|
||||
ssdk_printf(SSDK_EMERG, "spsr 0x%08x\r\n", frame->spsr);
|
||||
|
||||
dump_mode_regs(frame->spsr, (uintptr_t)(frame + 1), frame->lr);
|
||||
}
|
||||
|
||||
static void exception_die(struct arm_fault_frame *frame, const char *msg)
|
||||
{
|
||||
ssdk_printf(SSDK_EMERG, "%s", msg);
|
||||
dump_fault_frame(frame);
|
||||
|
||||
for (;;);
|
||||
}
|
||||
|
||||
static void exception_die_iframe(struct arm_iframe *frame, const char *msg)
|
||||
{
|
||||
ssdk_printf(SSDK_EMERG, "%s", msg);
|
||||
dump_iframe(frame);
|
||||
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void arm_undefined_handler(struct arm_iframe *frame)
|
||||
{
|
||||
/* look at the undefined instruction, figure out if it's something we can handle */
|
||||
bool in_thumb = frame->spsr & (1<<5);
|
||||
if (in_thumb) {
|
||||
frame->pc -= 2;
|
||||
} else {
|
||||
frame->pc -= 4;
|
||||
}
|
||||
|
||||
__UNUSED uint32_t opcode = *(uint32_t *)frame->pc;
|
||||
ssdk_printf(SSDK_EMERG, "undefined opcode 0x%x\r\n", opcode);
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
if (in_thumb) {
|
||||
/* look for a 32bit thumb instruction */
|
||||
if (opcode & 0x0000e800) {
|
||||
/* swap the 16bit words */
|
||||
opcode = (opcode >> 16) | (opcode << 16);
|
||||
}
|
||||
|
||||
if (((opcode & 0xec000e00) == 0xec000a00) || // vfp
|
||||
((opcode & 0xef000000) == 0xef000000) || // advanced simd data processing
|
||||
((opcode & 0xff100000) == 0xf9000000)) { // VLD
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "vfp/neon thumb instruction 0x%08x at 0x%x\r\n", opcode, frame->pc);
|
||||
}
|
||||
} else {
|
||||
/* look for arm vfp/neon coprocessor instructions */
|
||||
if (((opcode & 0x0c000e00) == 0x0c000a00) || // vfp
|
||||
((opcode & 0xfe000000) == 0xf2000000) || // advanced simd data processing
|
||||
((opcode & 0xff100000) == 0xf4000000)) { // VLD
|
||||
ssdk_printf(SSDK_EMERG, "vfp/neon arm instruction 0x%08x at 0x%x\r\n", opcode, frame->pc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
exception_die_iframe(frame, "undefined abort, halting\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void arm_data_abort_handler(struct arm_fault_frame *frame)
|
||||
{
|
||||
uint32_t fsr = arm_read_dfsr();
|
||||
uint32_t far = arm_read_dfar();
|
||||
|
||||
uint32_t fault_status = (BIT(fsr, 10) ? (1<<4) : 0) | BITS(fsr, 3, 0);
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "\r\n\ncpu data abort, ");
|
||||
__UNUSED bool write = !!BIT(fsr, 11);
|
||||
|
||||
/* decode the fault status (from table B3-23) */
|
||||
switch (fault_status) {
|
||||
case 0x01: // alignment fault
|
||||
ssdk_printf(SSDK_EMERG, "alignment fault on %s\r\n", write ? "write" : "read");
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x07: // translation fault
|
||||
ssdk_printf(SSDK_EMERG, "translation fault on %s\r\n", write ? "write" : "read");
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06: // access flag fault
|
||||
ssdk_printf(SSDK_EMERG, "access flag fault on %s\r\n", write ? "write" : "read");
|
||||
break;
|
||||
case 0x09:
|
||||
case 0x0B: // domain fault
|
||||
ssdk_printf(SSDK_EMERG, "domain fault, domain %lu\r\n", BITS_SHIFT(fsr, 7, 4));
|
||||
break;
|
||||
case 0x0D:
|
||||
case 0x0F: // permission fault
|
||||
ssdk_printf(SSDK_EMERG, "permission fault on %s\r\n", write ? "write" : "read");
|
||||
break;
|
||||
case 0x02: // debug event
|
||||
ssdk_printf(SSDK_EMERG, "debug event\r\n");
|
||||
break;
|
||||
case 0x08: // synchronous external abort
|
||||
ssdk_printf(SSDK_EMERG, "synchronous external abort on %s\r\n", write ? "write" : "read");
|
||||
break;
|
||||
case 0x16: // asynchronous external abort
|
||||
ssdk_printf(SSDK_EMERG, "asynchronous external abort on %s\r\n", write ? "write" : "read");
|
||||
break;
|
||||
case 0x10: // TLB conflict event
|
||||
case 0x19: // synchronous parity error on memory access
|
||||
case 0x04: // fault on instruction cache maintenance
|
||||
case 0x0C: // synchronous external abort on translation table walk
|
||||
case 0x0E: // "
|
||||
case 0x1C: // synchronous parity error on translation table walk
|
||||
case 0x1E: // "
|
||||
case 0x18: // asynchronous parity error on memory access
|
||||
default:
|
||||
ssdk_printf(SSDK_EMERG, "unhandled fault\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "DFAR 0x%x (fault address)\r\n", far);
|
||||
ssdk_printf(SSDK_EMERG, "DFSR 0x%x (fault status register)\r\n", fsr);
|
||||
|
||||
exception_die(frame, "halting\r\n");
|
||||
}
|
||||
|
||||
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
|
||||
{
|
||||
uint32_t fsr = arm_read_ifsr();
|
||||
uint32_t far = arm_read_ifar();
|
||||
|
||||
uint32_t fault_status = (BIT(fsr, 10) ? (1<<4) : 0) | BITS(fsr, 3, 0);
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "\r\n\ncpu prefetch abort, ");
|
||||
|
||||
/* decode the fault status (from table B3-23) */
|
||||
switch (fault_status) {
|
||||
case 0x01: // alignment fault
|
||||
ssdk_printf(SSDK_EMERG, "alignment fault\r\n");
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x07: // translation fault
|
||||
ssdk_printf(SSDK_EMERG, "translation fault\r\n");
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06: // access flag fault
|
||||
ssdk_printf(SSDK_EMERG, "access flag fault\r\n");
|
||||
break;
|
||||
case 0x09:
|
||||
case 0x0B: // domain fault
|
||||
ssdk_printf(SSDK_EMERG, "domain fault, domain %lu\r\n", BITS_SHIFT(fsr, 7, 4));
|
||||
break;
|
||||
case 0x0D:
|
||||
case 0x0F: // permission fault
|
||||
ssdk_printf(SSDK_EMERG, "permission fault\r\n");
|
||||
break;
|
||||
case 0x02: // debug event
|
||||
ssdk_printf(SSDK_EMERG, "debug event\r\n");
|
||||
break;
|
||||
case 0x08: // synchronous external abort
|
||||
ssdk_printf(SSDK_EMERG, "synchronous external abort\r\n");
|
||||
break;
|
||||
case 0x16: // asynchronous external abort
|
||||
ssdk_printf(SSDK_EMERG, "asynchronous external abort\r\n");
|
||||
break;
|
||||
case 0x10: // TLB conflict event
|
||||
case 0x19: // synchronous parity error on memory access
|
||||
case 0x04: // fault on instruction cache maintenance
|
||||
case 0x0C: // synchronous external abort on translation table walk
|
||||
case 0x0E: // "
|
||||
case 0x1C: // synchronous parity error on translation table walk
|
||||
case 0x1E: // "
|
||||
case 0x18: // asynchronous parity error on memory access
|
||||
default:
|
||||
ssdk_printf(SSDK_EMERG, "unhandled fault\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_EMERG, "IFAR 0x%x (fault address)\r\n", far);
|
||||
ssdk_printf(SSDK_EMERG, "IFSR 0x%x (fault status register)\r\n", fsr);
|
||||
|
||||
exception_die(frame, "halting\r\n");
|
||||
}
|
||||
54
arch/armv7-r/arm_fpu.c
Normal file
54
arch/armv7-r/arm_fpu.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* arm_fpu.c
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM fpu function.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
|
||||
#include <armv7-r/register.h>
|
||||
#include <armv7-r/fpu.h>
|
||||
|
||||
/* CPACR */
|
||||
|
||||
#define CPACR_CP10_SHIFT (20)
|
||||
#define CPACR_CP10_MASK (3 << CPACR_CP10_SHIFT)
|
||||
#define CPACR_CP11_SHIFT (22)
|
||||
#define CPACR_CP11_MASK (3 << CPACR_CP11_SHIFT)
|
||||
|
||||
/* FPEXC */
|
||||
|
||||
#define FPEXC_EX (31)
|
||||
#define FPEXC_EN (30)
|
||||
|
||||
/*
|
||||
* fpu enable.
|
||||
*/
|
||||
void arm_fpu_enable(void)
|
||||
{
|
||||
uint32_t cpacr = arm_read_cpacr();
|
||||
cpacr |= ((3 << CPACR_CP10_SHIFT) | (3 << CPACR_CP11_SHIFT));
|
||||
arm_write_cpacr(cpacr);
|
||||
|
||||
uint32_t fpexc = arm_read_fpexc();
|
||||
fpexc |= (1 << FPEXC_EN);
|
||||
arm_write_fpexc(fpexc);
|
||||
}
|
||||
|
||||
/*
|
||||
* fpu disable.
|
||||
*/
|
||||
void arm_fpu_disable(void)
|
||||
{
|
||||
uint32_t fpexc = arm_read_fpexc();
|
||||
fpexc &= ~(1 << FPEXC_EN);
|
||||
arm_write_fpexc(fpexc);
|
||||
}
|
||||
|
||||
#endif
|
||||
101
arch/armv7-r/arm_irq.c
Normal file
101
arch/armv7-r/arm_irq.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* arm_irq.c
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM irq function.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
#include <armv7-r/arm.h>
|
||||
#include <armv7-r/register.h>
|
||||
#include <bits.h>
|
||||
#include <debug.h>
|
||||
#include <types.h>
|
||||
|
||||
#include "irq.h"
|
||||
|
||||
/*
|
||||
* is irq masked.
|
||||
*
|
||||
* @return masked or not.
|
||||
*/
|
||||
bool arch_irq_is_masked(void)
|
||||
{
|
||||
uint32_t cpsr = read_cpsr();
|
||||
return (!!(cpsr & PSR_I_BIT));
|
||||
}
|
||||
|
||||
/*
|
||||
* is irq mode.
|
||||
*
|
||||
* @return irq mode or not.
|
||||
*/
|
||||
bool arch_in_irq_mode(void)
|
||||
{
|
||||
uint32_t cpsr;
|
||||
uint8_t mode;
|
||||
|
||||
cpsr = read_cpsr();
|
||||
mode = cpsr & MODE_MASK;
|
||||
return ((mode != MODE_USR) && (mode != MODE_SYS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable vectored interrupt mode.
|
||||
*/
|
||||
void arch_vectored_irq_enable(bool en)
|
||||
{
|
||||
uint32_t sctlr;
|
||||
|
||||
sctlr = arm_read_sctlr();
|
||||
|
||||
if (en) {
|
||||
sctlr |= 1U << 24;
|
||||
} else {
|
||||
sctlr &= ~(1U << 24);
|
||||
}
|
||||
|
||||
arm_write_sctlr(sctlr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether core is in FIQ mode or not
|
||||
*
|
||||
* @return true FIQ mode
|
||||
* @return false otherwise
|
||||
*/
|
||||
bool arch_in_fiq_mode(void)
|
||||
{
|
||||
uint32_t cpsr = read_cpsr();
|
||||
|
||||
return (cpsr & MODE_MASK) == MODE_FIQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief irq handler
|
||||
*
|
||||
* This function is used by irq interrupt when VE != 1.
|
||||
*
|
||||
*/
|
||||
void arm_irq_handler(void)
|
||||
{
|
||||
#ifdef USE_STACK_COLORATION
|
||||
if (!arch_check_exception_stack()) {
|
||||
ssdk_printf(SSDK_ALERT, "exception stack overflow!\r\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
irq_dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fiq handler
|
||||
*
|
||||
* This function is used by fiq interrupt.
|
||||
*
|
||||
*/
|
||||
void arm_fiq_handler(void) { irq_dispatch(); }
|
||||
248
arch/armv7-r/arm_mpu.c
Normal file
248
arch/armv7-r/arm_mpu.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* mpu.c
|
||||
*
|
||||
* Copyright (c) 2019 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R MPU driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#if CONFIG_ARCH_WITH_MPU
|
||||
#include <armv7-r/arm.h>
|
||||
#include <armv7-r/mpu.h>
|
||||
#include <armv7-r/register.h>
|
||||
#include <math.h>
|
||||
#include <bits.h>
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
/* RBAR bits [31:5] */
|
||||
#define MPU_RBAR_MASK (0xffffffe0)
|
||||
|
||||
/* RACR bits */
|
||||
#define MPU_RACR_B_SHIFT (0) /* Bufferable */
|
||||
#define MPU_RACR_C_SHIFT (1) /* Cacheable */
|
||||
#define MPU_RACR_S_SHIFT (2) /* Sharable. For normal memory only. */
|
||||
#define MPU_RACR_TEX_SHIFT (3) /* Type extension */
|
||||
#define MPU_RACR_AP_SHIFT (8) /* Access permission */
|
||||
#define MPU_RACR_XN_SHIFT (12) /* Execution Never */
|
||||
|
||||
/* RACR Access permissions */
|
||||
#define RACR_AP_NO_NO (0) /* Privileged NO, Unprivileged NO */
|
||||
#define RACR_AP_RW_NO (1) /* Privileged RW, Unprivileged NO */
|
||||
#define RACR_AP_RW_RO (2) /* Privileged RW, Unprivileged RO */
|
||||
#define RACR_AP_RW_RW (3) /* Privileged RW, Unprivileged RW */
|
||||
#define RACR_AP_RO_NO (5) /* Privileged RO, Unprivileged NO */
|
||||
#define RACR_AP_RO_RO (6) /* Privileged RO, Unprivileged RO */
|
||||
|
||||
#define MPU_RACR_CONFIG(TEX, C, B, S, AP, XN) \
|
||||
((B << MPU_RACR_B_SHIFT) | \
|
||||
(C << MPU_RACR_C_SHIFT) | \
|
||||
(S << MPU_RACR_S_SHIFT) | \
|
||||
(TEX << MPU_RACR_TEX_SHIFT) | \
|
||||
(AP << MPU_RACR_AP_SHIFT) | \
|
||||
(XN << MPU_RACR_XN_SHIFT))
|
||||
|
||||
/* Region Size and Enable Register */
|
||||
#define RSR_EN (1 << 0) /* Enable region */
|
||||
#define RSR_SIZE_SHIFT (1) /* Region Size = log2(size) - 1 */
|
||||
|
||||
static const uint32_t g_racr_config[] = {
|
||||
[MPU_REGION_STRONGORDERED] = MPU_RACR_CONFIG(
|
||||
0, 0, 0, /* See "TEX[2:0], C and B encodings" */
|
||||
0, /* S bit is not used for strong ordered. */
|
||||
RACR_AP_RW_RW,
|
||||
1 /* XN */
|
||||
),
|
||||
|
||||
[MPU_REGION_DEVICE] = MPU_RACR_CONFIG(
|
||||
0, 0, 1,
|
||||
0, /* S bit is not used for device memory */
|
||||
RACR_AP_RW_RW,
|
||||
1 /* XN */
|
||||
),
|
||||
|
||||
[MPU_REGION_NORMAL] = MPU_RACR_CONFIG(
|
||||
0, 1, 1, /* cacheable, WB, no WA */
|
||||
0, /* Not shared. R5 L1 cache does not cache shared
|
||||
normal regions */
|
||||
RACR_AP_RW_RW,
|
||||
0 /* non XN */
|
||||
),
|
||||
|
||||
[MPU_REGION_NORMAL_NONCACHEABLE] = MPU_RACR_CONFIG(
|
||||
1, 0, 0, /* non-cacheable */
|
||||
0,
|
||||
RACR_AP_RW_RW,
|
||||
0 /* non XN */
|
||||
),
|
||||
|
||||
[MPU_REGION_NORMAL_RO] = MPU_RACR_CONFIG(
|
||||
0, 1, 1, /* cacheable, WB, no WA */
|
||||
0, /* Not shared. R5 L1 cache does not cache shared
|
||||
normal regions */
|
||||
RACR_AP_RO_RO,
|
||||
0 /* XN */
|
||||
),
|
||||
|
||||
[MPU_REGION_NO_ACCESS] = MPU_RACR_CONFIG(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
RACR_AP_NO_NO,
|
||||
0
|
||||
),
|
||||
};
|
||||
|
||||
uint32_t all_region_index = 0;
|
||||
|
||||
static int mpu_region_nr(void)
|
||||
{
|
||||
uint32_t val = arm_read_mpuir();
|
||||
return (int)BITS_SHIFT(val, 15, 8); /* 0, 12 or 16 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear MPU region.
|
||||
*/
|
||||
void mpu_clear_region(void)
|
||||
{
|
||||
int region_nr = mpu_region_nr();
|
||||
|
||||
for (int cnt = 0; cnt < region_nr; cnt++) {
|
||||
arm_write_rgnr(cnt);
|
||||
arm_write_rsr(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add MPU region.
|
||||
*
|
||||
* @region Region index from 0 to mpu_region_nr - 1.
|
||||
* @base Base address of the region. Must align to region size.
|
||||
* @size Region size. Must be power of 2, from 32 bytes to 4GB.
|
||||
* @type Region type.
|
||||
*/
|
||||
#if CONFIG_ARMV7R_MPU_CACHE_ALIGN_CHECK
|
||||
struct region_info {
|
||||
uint32_t base;
|
||||
uint32_t end;
|
||||
//mpu_region_type type;
|
||||
};
|
||||
struct region_info region_array[16] = {0};
|
||||
int region_index = 0;
|
||||
static void add_region(uint32_t base, uint32_t size)
|
||||
{
|
||||
ASSERT(region_index >= 0 && region_index < 16);
|
||||
region_array[region_index].base = base;
|
||||
region_array[region_index].end = base + size;
|
||||
region_index++;
|
||||
}
|
||||
|
||||
bool mpu_is_belong_uncache_region(uint32_t base, uint32_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < region_index; i++) {
|
||||
uint32_t end = base + size;
|
||||
|
||||
if (base >= region_array[i].base && end <= region_array[i].end) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
void mpu_add_region(int region, uint32_t base, uint64_t size,
|
||||
mpu_region_type_e type)
|
||||
{
|
||||
ASSERT(region >= 0 && region < mpu_region_nr());
|
||||
ASSERT((size & (size - 1)) == 0 &&
|
||||
size >= 32ull &&
|
||||
size <= 4ull * 1024 * 1024 * 1024);
|
||||
ASSERT(base % size == 0);
|
||||
ASSERT(type < MPU_REGION_MAX);
|
||||
/* Calculate size field of RSR register.
|
||||
* pow(2, sz + 1) = size
|
||||
*/
|
||||
uint32_t sz = (uint32_t)log2(size) - 1;
|
||||
arm_write_rgnr(region);
|
||||
arm_write_rbar(base & MPU_RBAR_MASK);
|
||||
arm_write_racr(g_racr_config[type]);
|
||||
/* TODO - support sub regions? */
|
||||
arm_write_rsr((sz << RSR_SIZE_SHIFT) | RSR_EN);
|
||||
#if CONFIG_ARMV7R_MPU_CACHE_ALIGN_CHECK
|
||||
|
||||
//add region in nocache list
|
||||
if (type != MPU_REGION_NORMAL) {
|
||||
add_region(base, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
all_region_index++;
|
||||
}
|
||||
|
||||
uint32_t mpu_region_index(void)
|
||||
{
|
||||
return all_region_index;
|
||||
}
|
||||
/*
|
||||
* Enable or disable the MPU.
|
||||
*
|
||||
* MPU regions must have been configured before enabling the MPU.
|
||||
*/
|
||||
void mpu_enable(bool enable)
|
||||
{
|
||||
uint32_t val = arm_read_sctlr();
|
||||
|
||||
if (enable)
|
||||
/* Enable MPU. The default background region is always
|
||||
* enabled as well.
|
||||
*/
|
||||
{
|
||||
val |= SCTLR_BR | SCTLR_M;
|
||||
}
|
||||
else {
|
||||
val &= ~SCTLR_M;
|
||||
}
|
||||
|
||||
arm_write_sctlr(val);
|
||||
}
|
||||
|
||||
void mpu_region_set_type(uint32_t base, uint64_t size,
|
||||
mpu_region_type_e type)
|
||||
{
|
||||
ASSERT((size & (size - 1)) == 0 &&
|
||||
size >= 32ull &&
|
||||
size <= 4ull * 1024 * 1024 * 1024);
|
||||
ASSERT(base % size == 0);
|
||||
ASSERT(type < MPU_REGION_MAX);
|
||||
/* Calculate size field of RSR register.
|
||||
* pow(2, sz + 1) = size
|
||||
*/
|
||||
uint32_t sz = (uint32_t)log2(size) - 1;
|
||||
int region_nr = mpu_region_nr();
|
||||
|
||||
for (int cnt = 0; cnt < region_nr; cnt++) {
|
||||
uint32_t rbar, rsr;
|
||||
|
||||
arm_write_rgnr(cnt);
|
||||
rbar = arm_read_rbar();
|
||||
rsr = arm_read_rsr();
|
||||
|
||||
if (((rbar & MPU_RBAR_MASK) == base)
|
||||
&& (rsr >> RSR_SIZE_SHIFT) == sz) {
|
||||
arm_write_rsr(rsr & ~RSR_EN);
|
||||
arm_write_racr(g_racr_config[type]);
|
||||
arm_write_rsr(rsr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
109
arch/armv7-r/arm_tcm.c
Normal file
109
arch/armv7-r/arm_tcm.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* arm_tcm.c
|
||||
*
|
||||
* Copyright (c) 2019 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R TCM driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#if CONFIG_ARM_WITH_TCM
|
||||
|
||||
#include <types.h>
|
||||
#include <compiler.h>
|
||||
#include <bits.h>
|
||||
#include <param.h>
|
||||
#include <armv7-r/tcm.h>
|
||||
#include <armv7-r/register.h>
|
||||
|
||||
/**
|
||||
* @brief Clear the TCM.
|
||||
*/
|
||||
extern void tcm_clear_64bit(uint32_t base, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Get TCMA size in bytes.
|
||||
*/
|
||||
static size_t tcma_get_size(void)
|
||||
{
|
||||
uint32_t atcm_size = BITS_SHIFT(arm_read_atcmrgn(), 6, 2);
|
||||
return (1 << (atcm_size + 9));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get TCMB size in bytes.
|
||||
*/
|
||||
static size_t tcmb_get_size(void)
|
||||
{
|
||||
uint32_t btcm_size = BITS_SHIFT(arm_read_btcmrgn(), 6, 2);
|
||||
return (1 << (btcm_size + 9));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the TCMA.
|
||||
*/
|
||||
void tcma_enable(uint32_t atcm_base, bool enable_ecc)
|
||||
{
|
||||
size_t atcm_size;
|
||||
uint32_t actlr = arm_read_actlr();
|
||||
|
||||
/* Disable ECC by default */
|
||||
actlr &= ~ATCMPCEN;
|
||||
arm_write_actlr(actlr);
|
||||
|
||||
/* Get TCM size. */
|
||||
atcm_size = tcma_get_size();
|
||||
|
||||
/* Update TCM base address. */
|
||||
if (atcm_size != 0) {
|
||||
arm_write_atcmrgn(atcm_base | 1);
|
||||
}
|
||||
|
||||
if (enable_ecc) {
|
||||
/* Write to the TCM in 64-bit aligned quantities to initialize
|
||||
* ECC codes.
|
||||
*/
|
||||
tcm_clear_64bit(atcm_base, atcm_size);
|
||||
|
||||
/* Enable ECC. */
|
||||
actlr |= ATCMPCEN;
|
||||
arm_write_actlr(actlr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the TCMB.
|
||||
*/
|
||||
void tcmb_enable(uint32_t btcm_base, bool enable_ecc)
|
||||
{
|
||||
size_t btcm_size;
|
||||
uint32_t actlr = arm_read_actlr();
|
||||
|
||||
/* Disable ECC by default */
|
||||
actlr &= ~(B0TCMPCEN | B1TCMPCEN);
|
||||
arm_write_actlr(actlr);
|
||||
|
||||
/* Get TCM size. */
|
||||
btcm_size = tcmb_get_size();
|
||||
|
||||
/* Update TCM base address. */
|
||||
if (btcm_size != 0) {
|
||||
arm_write_btcmrgn(btcm_base | 1);
|
||||
}
|
||||
|
||||
if (enable_ecc) {
|
||||
/* Write to the TCM in 64-bit aligned quantities to initialize
|
||||
* ECC codes.
|
||||
*/
|
||||
tcm_clear_64bit(btcm_base, btcm_size);
|
||||
|
||||
/* Enable ECC. */
|
||||
actlr |= B0TCMPCEN | B1TCMPCEN;
|
||||
arm_write_actlr(actlr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
57
arch/armv7-r/gcc/arm_atomic.S
Normal file
57
arch/armv7-r/gcc/arm_atomic.S
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* arm_atomic.s
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM atomic function.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
|
||||
.text
|
||||
|
||||
FUNCTION(arch_atomic_swap)
|
||||
.Lloop_atomic_swap:
|
||||
ldrex r12, [r0]
|
||||
strex r2, r1, [r0]
|
||||
cmp r2, #0
|
||||
bne .Lloop_atomic_swap
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
.arm
|
||||
|
||||
FUNCTION(arch_atomic_add)
|
||||
.Lloop_atomic_add:
|
||||
ldrex r12, [r0]
|
||||
add r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .Lloop_atomic_add
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
FUNCTION(arch_atomic_and)
|
||||
.Lloop_atomic_and:
|
||||
ldrex r12, [r0]
|
||||
and r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .Lloop_atomic_and
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
FUNCTION(arch_atomic_or)
|
||||
.Lloop_atomic_or:
|
||||
ldrex r12, [r0]
|
||||
orr r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .Lloop_atomic_or
|
||||
mov r0, r12
|
||||
bx lr
|
||||
317
arch/armv7-r/gcc/arm_cache.S
Normal file
317
arch/armv7-r/gcc/arm_cache.S
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/cache.h>
|
||||
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
|
||||
.text
|
||||
|
||||
.arm
|
||||
|
||||
/* void arch_disable_cache(uint flags) */
|
||||
FUNCTION(arch_disable_cache)
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
|
||||
mov r7, r0 // save flags
|
||||
|
||||
mrs r8, cpsr // save the old interrupt state
|
||||
cpsid iaf // interrupts disabled
|
||||
|
||||
.Ldcache_disable:
|
||||
tst r7, #DCACHE
|
||||
beq .Licache_disable
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
tst r0, #(1<<2) // is the dcache already disabled?
|
||||
beq .Ldcache_already_disabled
|
||||
|
||||
bic r0, #(1<<2)
|
||||
mcr p15, 0, r0, c1, c0, 0 // disable dcache
|
||||
|
||||
// flush and invalidate the dcache
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl flush_invalidate_cache_v7
|
||||
|
||||
b .Ldcache_disable_L2
|
||||
|
||||
.Ldcache_already_disabled:
|
||||
// make sure all of the caches are invalidated
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl invalidate_cache_v7
|
||||
|
||||
.Ldcache_disable_L2:
|
||||
|
||||
#if CONFIG_ARCH_L2CACHE
|
||||
// disable the L2, if present
|
||||
mrc p15, 0, r0, c1, c0, 1 // aux cr1
|
||||
bic r0, #(1<<1)
|
||||
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
|
||||
#endif
|
||||
|
||||
.Licache_disable:
|
||||
tst r7, #ICACHE
|
||||
beq .Ldone_disable
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
bic r0, #(1<<12)
|
||||
mcr p15, 0, r0, c1, c0, 0 // disable icache
|
||||
|
||||
.Ldone_disable:
|
||||
// make sure the icache is always invalidated
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
msr cpsr, r8
|
||||
ldmfd sp!, {r4-r11, pc}
|
||||
|
||||
/* void arch_enable_cache(uint flags) */
|
||||
FUNCTION(arch_enable_cache)
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
mov r7, r0 // save flags
|
||||
|
||||
mrs r8, cpsr // save the old interrupt state
|
||||
cpsid iaf // interrupts disabled
|
||||
|
||||
.Ldcache_enable:
|
||||
tst r7, #DCACHE
|
||||
beq .Licache_enable
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
tst r0, #(1<<2) // is the dcache already enabled?
|
||||
bne .Licache_enable
|
||||
|
||||
// invalidate L1 and L2
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl invalidate_cache_v7
|
||||
|
||||
#if CONFIG_ARCH_L2CACHE
|
||||
// enable the L2, if present
|
||||
mrc p15, 0, r0, c1, c0, 1 // aux cr1
|
||||
orr r0, #(1<<1)
|
||||
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
|
||||
#endif
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
orr r0, #(1<<2)
|
||||
mcr p15, 0, r0, c1, c0, 0 // enable dcache
|
||||
|
||||
.Licache_enable:
|
||||
tst r7, #ICACHE
|
||||
beq .Ldone_enable
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
orr r0, #(1<<12)
|
||||
mcr p15, 0, r0, c1, c0, 0 // enable icache
|
||||
|
||||
.Ldone_enable:
|
||||
isb
|
||||
msr cpsr, r8
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
// flush & invalidate cache routine, trashes r0-r6, r9-r11
|
||||
flush_invalidate_cache_v7:
|
||||
/* from ARMv7 manual, B2-17 */
|
||||
dmb
|
||||
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
|
||||
ANDS R3, R0, #0x7000000
|
||||
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
|
||||
BEQ .Lfinished
|
||||
MOV R10, #0
|
||||
.Loop1:
|
||||
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
|
||||
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
|
||||
AND R1, R1, #7 // get those 3 bits alone
|
||||
CMP R1, #2
|
||||
BLT .Lskip // no cache or only instruction cache at this level
|
||||
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
|
||||
isb // ISB to sync the change to the CacheSizeID reg
|
||||
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
|
||||
AND R2, R1, #0x7 // extract the line length field
|
||||
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
|
||||
LDR R4, =0x3FF
|
||||
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
|
||||
CLZ R5, R4 // R5 is the bit position of the way size increment
|
||||
LDR R6, =0x00007FFF
|
||||
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
|
||||
.Loop2:
|
||||
MOV R9, R4 // R9 working copy of the max way size (right aligned)
|
||||
.Loop3:
|
||||
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
|
||||
ORR R11, R11, R6, LSL R2 // factor in the index number
|
||||
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
|
||||
SUBS R9, R9, #1 // decrement the way number
|
||||
BGE .Loop3
|
||||
SUBS R6, R6, #1 // decrement the index
|
||||
BGE .Loop2
|
||||
.Lskip:
|
||||
ADD R10, R10, #2 // increment the cache number
|
||||
CMP R3, R10
|
||||
BGT .Loop1
|
||||
|
||||
.Lfinished:
|
||||
mov r10, #0
|
||||
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
|
||||
dsb
|
||||
isb
|
||||
|
||||
bx lr
|
||||
|
||||
// invalidate cache routine, trashes r0-r6, r9-r11
|
||||
invalidate_cache_v7:
|
||||
/* from ARMv7 manual, B2-17 */
|
||||
dmb
|
||||
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
|
||||
ANDS R3, R0, #0x7000000
|
||||
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
|
||||
BEQ .Lfinished_invalidate
|
||||
MOV R10, #0
|
||||
.Loop1_invalidate:
|
||||
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
|
||||
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
|
||||
AND R1, R1, #7 // get those 3 bits alone
|
||||
CMP R1, #2
|
||||
BLT .Lskip_invalidate // no cache or only instruction cache at this level
|
||||
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
|
||||
isb // ISB to sync the change to the CacheSizeID reg
|
||||
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
|
||||
AND R2, R1, #0x7 // extract the line length field
|
||||
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
|
||||
LDR R4, =0x3FF
|
||||
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
|
||||
CLZ R5, R4 // R5 is the bit position of the way size increment
|
||||
LDR R6, =0x00007FFF
|
||||
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
|
||||
.Loop2_invalidate:
|
||||
MOV R9, R4 // R9 working copy of the max way size (right aligned)
|
||||
.Loop3_invalidate:
|
||||
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
|
||||
ORR R11, R11, R6, LSL R2 // factor in the index number
|
||||
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
|
||||
SUBS R9, R9, #1 // decrement the way number
|
||||
BGE .Loop3_invalidate
|
||||
SUBS R6, R6, #1 // decrement the index
|
||||
BGE .Loop2_invalidate
|
||||
.Lskip_invalidate:
|
||||
ADD R10, R10, #2 // increment the cache number
|
||||
CMP R3, R10
|
||||
BGT .Loop1_invalidate
|
||||
|
||||
.Lfinished_invalidate:
|
||||
dsb
|
||||
mov r10, #0
|
||||
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
|
||||
isb
|
||||
|
||||
bx lr
|
||||
|
||||
/* void arch_flush_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_clean_cache_range)
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mov r3, r0 // save the start address
|
||||
add r2, r0, r1 // calculate the end address
|
||||
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
|
||||
0:
|
||||
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
|
||||
add r0, #CONFIG_ARCH_CACHE_LINE
|
||||
cmp r0, r2
|
||||
blo 0b
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_clean_invalidate_cache_range)
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mov r3, r0 // save the start address
|
||||
add r2, r0, r1 // calculate the end address
|
||||
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
|
||||
0:
|
||||
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate dcache to PoC by MVA
|
||||
add r0, r0, #CONFIG_ARCH_CACHE_LINE
|
||||
cmp r0, r2
|
||||
blo 0b
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_clean_invalidate_dcache_all(void); */
|
||||
FUNCTION(arch_clean_invalidate_dcache_all)
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mrc p15, 1, r0, c0, c0, 0 /* Read the Cache Size Identification Register */
|
||||
ldr r3, =0x7fff /* Isolate the NumSets field (bits 13-27) */
|
||||
and r0, r3, r0, lsr #13 /* r0=NumSets (number of sets - 1) */
|
||||
|
||||
mov r1, #0 /* r1 = way loop counter */
|
||||
way_loop:
|
||||
|
||||
mov r3, #0 /* r3 = set loop counter */
|
||||
set_loop:
|
||||
mov r2, r1, lsl #30 /* r2 = way loop counter << 30 */
|
||||
orr r2, r3, lsl #5 /* r2 = set/way cache operation format */
|
||||
mcr p15, 0, r2, c7, c14, 2 /* Data Cache Clean Invalidate by Set/Way */
|
||||
add r3, r3, #1 /* Increment set counter */
|
||||
cmp r0, r3 /* Last set? */
|
||||
bge set_loop /* Keep looping if not */
|
||||
|
||||
add r1, r1, #1 /* Increment the way counter */
|
||||
cmp r1, #4 /* Last way? (four ways assumed) */
|
||||
bne way_loop /* Keep looping if not */
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_invalidate_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_invalidate_cache_range)
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mov r3, r0 // save the start address
|
||||
add r2, r0, r1 // calculate the end address
|
||||
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
|
||||
0:
|
||||
mcr p15, 0, r0, c7, c6, 1 // invalidate dcache to PoC by MVA
|
||||
add r0, r0, #CONFIG_ARCH_CACHE_LINE
|
||||
cmp r0, r2
|
||||
blo 0b
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_sync_cache_range(addr_t start, size_t len); */
|
||||
FUNCTION(arch_sync_cache_range)
|
||||
push { r14 }
|
||||
bl arch_clean_cache_range
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
pop { pc }
|
||||
|
||||
#endif
|
||||
275
arch/armv7-r/gcc/arm_exceptions.S
Normal file
275
arch/armv7-r/gcc/arm_exceptions.S
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/cache.h>
|
||||
|
||||
/* macros to align and unalign the stack on 8 byte boundary for ABI compliance */
|
||||
.macro stack_align, tempreg
|
||||
/* make sure the stack is aligned */
|
||||
mov \tempreg, sp
|
||||
tst sp, #4
|
||||
subeq sp, #4
|
||||
push { \tempreg }
|
||||
|
||||
/* tempreg holds the original stack */
|
||||
.endm
|
||||
|
||||
.macro stack_restore, tempreg
|
||||
/* restore the potentially unaligned stack */
|
||||
pop { \tempreg }
|
||||
mov sp, \tempreg
|
||||
.endm
|
||||
|
||||
/* save and disable the vfp unit */
|
||||
.macro vfp_save, temp1
|
||||
/* save old fpexc */
|
||||
vmrs \temp1, fpexc
|
||||
|
||||
push { \temp1 }
|
||||
|
||||
/* hard disable the vfp unit */
|
||||
bic \temp1, #(1<<30)
|
||||
vmsr fpexc, \temp1
|
||||
.endm
|
||||
|
||||
/* restore the vfp enable/disable state */
|
||||
.macro vfp_restore, temp1
|
||||
/* restore fpexc */
|
||||
pop { \temp1 }
|
||||
|
||||
vmsr fpexc, \temp1
|
||||
.endm
|
||||
|
||||
/* Save callee trashed registers.
|
||||
* At exit r0 contains a pointer to the register frame.
|
||||
*/
|
||||
.macro save
|
||||
/* save spsr and r14 onto the svc stack */
|
||||
srsdb #0x13!
|
||||
|
||||
/* switch to svc mode, interrupts disabled */
|
||||
cpsid i,#0x13
|
||||
|
||||
/* save callee trashed regs and lr */
|
||||
push { r0-r4, r12, lr }
|
||||
|
||||
/* save user space sp/lr */
|
||||
sub sp, #8
|
||||
stmia sp, { r13, r14 }^
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
/* save and disable the vfp unit */
|
||||
vfp_save r0
|
||||
#endif
|
||||
|
||||
/* make sure the stack is 8 byte aligned */
|
||||
stack_align r0
|
||||
|
||||
/* r0 now holds the pointer to the original iframe (before alignment) */
|
||||
.endm
|
||||
|
||||
.macro save_offset, offset
|
||||
sub lr, \offset
|
||||
save
|
||||
.endm
|
||||
|
||||
.macro restore
|
||||
/* undo the stack alignment we did before */
|
||||
stack_restore r0
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
/* restore the old state of the vfp unit */
|
||||
vfp_restore r0
|
||||
#endif
|
||||
|
||||
/* restore user space sp/lr */
|
||||
ldmia sp, { r13, r14 }^
|
||||
add sp, #8
|
||||
|
||||
pop { r0-r4, r12, lr }
|
||||
|
||||
/* return to whence we came from */
|
||||
rfeia sp!
|
||||
.endm
|
||||
|
||||
/* Save all registers.
|
||||
* At exit r0 contains a pointer to the register frame.
|
||||
*/
|
||||
.macro saveall
|
||||
/* save spsr and r14 onto the svc stack */
|
||||
srsdb #0x13!
|
||||
|
||||
/* switch to svc mode, interrupts disabled */
|
||||
cpsid i,#0x13
|
||||
|
||||
/* save all regs */
|
||||
push { r0-r12, lr }
|
||||
|
||||
/* save user space sp/lr */
|
||||
sub sp, #8
|
||||
stmia sp, { r13, r14 }^
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
/* save and disable the vfp unit */
|
||||
vfp_save r0
|
||||
#endif
|
||||
|
||||
/* make sure the stack is 8 byte aligned */
|
||||
stack_align r0
|
||||
|
||||
/* r0 now holds the pointer to the original iframe (before alignment) */
|
||||
.endm
|
||||
|
||||
.macro saveall_offset, offset
|
||||
sub lr, \offset
|
||||
saveall
|
||||
.endm
|
||||
|
||||
.macro restoreall
|
||||
/* undo the stack alignment we did before */
|
||||
stack_restore r0
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
/* restore the old state of the vfp unit */
|
||||
vfp_restore r0
|
||||
#endif
|
||||
|
||||
/* restore user space sp/lr */
|
||||
ldmia sp, { r13, r14 }^
|
||||
add sp, #8
|
||||
|
||||
pop { r0-r12, r14 }
|
||||
|
||||
/* return to whence we came from */
|
||||
rfeia sp!
|
||||
.endm
|
||||
|
||||
.arm
|
||||
|
||||
FUNCTION(arm_save_mode_regs)
|
||||
mrs r1, cpsr
|
||||
|
||||
stmia r0, { r13, r14 }^ /* usr */
|
||||
add r0, #8
|
||||
|
||||
cps #0x11 /* fiq */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x12 /* irq */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x13 /* svc */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x17 /* abt */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x1b /* und */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x1f /* sys */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
msr cpsr_c, r1
|
||||
|
||||
bx lr
|
||||
|
||||
FUNCTION(Arm_Undefined_Handler)
|
||||
save
|
||||
/* r0 now holds pointer to iframe */
|
||||
|
||||
bl arm_undefined_handler
|
||||
|
||||
restore
|
||||
|
||||
FUNCTION(Arm_Prefetch_Handler)
|
||||
saveall_offset #4
|
||||
/* r0 now holds pointer to iframe */
|
||||
|
||||
bl arm_prefetch_abort_handler
|
||||
|
||||
restoreall
|
||||
|
||||
FUNCTION(Arm_Abort_Handler)
|
||||
saveall_offset #8
|
||||
/* r0 now holds pointer to iframe */
|
||||
|
||||
bl arm_data_abort_handler
|
||||
|
||||
restoreall
|
||||
|
||||
FUNCTION(Arm_SWI_Handler)
|
||||
/* not support */
|
||||
ldr r0,=Arm_SWI_Handler
|
||||
bx r0
|
||||
|
||||
FUNCTION(Arm_IRQ_Handler)
|
||||
sub lr, lr, #4
|
||||
|
||||
srsdb #0x13!
|
||||
|
||||
cpsid i,#0x13
|
||||
|
||||
push {r0-r4, r12, lr}
|
||||
|
||||
sub sp, #8
|
||||
stmia sp, {r13, r14}^
|
||||
|
||||
mov r2, sp
|
||||
tst sp, #4
|
||||
subeq sp, #4
|
||||
push {r2}
|
||||
|
||||
push {r0, lr}
|
||||
|
||||
bl arm_irq_handler
|
||||
|
||||
pop {r0, lr}
|
||||
|
||||
pop {r2}
|
||||
mov sp, r2
|
||||
|
||||
ldmia sp, {r13, r14}^
|
||||
add sp, #8
|
||||
|
||||
pop {r0-r4, r12, lr}
|
||||
|
||||
rfeia sp!
|
||||
|
||||
FUNCTION(Arm_FIQ_Handler)
|
||||
push {r0-r3, r12, lr}
|
||||
blx arm_fiq_handler
|
||||
pop {r0-r3, r12, lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
FUNCTION(arm_reserved)
|
||||
b .
|
||||
|
||||
44
arch/armv7-r/gcc/arm_fullcontextrestore.S
Normal file
44
arch/armv7-r/gcc/arm_fullcontextrestore.S
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* arm_fullcontextrestore.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM full context restore.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/svcall.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_fullcontextrestore
|
||||
****************************************************************************/
|
||||
|
||||
.globl arm_fullcontextrestore
|
||||
.type arm_fullcontextrestore, function
|
||||
|
||||
arm_fullcontextrestore:
|
||||
|
||||
cps #0x1F /* Enter sys mode */
|
||||
|
||||
/* Perform the System call with R0=1 and R1=regs */
|
||||
|
||||
mov r1, r0 /* R1: regs */
|
||||
mov r0, #SYS_restore_context /* R0: restore context */
|
||||
svc 0 /* Force synchronous SVCall (or Hard Fault) */
|
||||
|
||||
/* This call should not return */
|
||||
|
||||
bx lr /* Unnecessary ... will not return */
|
||||
.size arm_fullcontextrestore, .-arm_fullcontextrestore
|
||||
.end
|
||||
41
arch/armv7-r/gcc/arm_saveusercontext.S
Normal file
41
arch/armv7-r/gcc/arm_saveusercontext.S
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* arm_saveusercontext.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM save user context.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/svcall.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_saveusercontext
|
||||
****************************************************************************/
|
||||
|
||||
.globl arm_saveusercontext
|
||||
.type arm_saveusercontext, function
|
||||
|
||||
arm_saveusercontext:
|
||||
|
||||
/* Perform the System call with R0=0 and R1=regs */
|
||||
|
||||
mov r1, r0 /* R1: regs */
|
||||
mov r0, #SYS_save_context /* R0: save context (also return value) */
|
||||
svc 0 /* Force synchronous SVCall (or Hard Fault) */
|
||||
|
||||
bx lr
|
||||
|
||||
.size arm_saveusercontext, .-arm_saveusercontext
|
||||
.end
|
||||
42
arch/armv7-r/gcc/arm_switchcontext.S
Normal file
42
arch/armv7-r/gcc/arm_switchcontext.S
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* arm_switchcontext.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM switch context.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/svcall.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_switchcontext
|
||||
****************************************************************************/
|
||||
|
||||
.globl arm_switchcontext
|
||||
.type arm_switchcontext, function
|
||||
|
||||
arm_switchcontext:
|
||||
|
||||
/* Perform the System call with R0=2 */
|
||||
|
||||
mov r0, #SYS_switch_context /* R0: context switch */
|
||||
svc 0 /* Force synchronous SVCall (or Hard Fault) */
|
||||
|
||||
/* We will get here only after the rerturn from the context switch */
|
||||
|
||||
bx lr
|
||||
|
||||
.size arm_switchcontext, .-arm_switchcontext
|
||||
.end
|
||||
122
arch/armv7-r/gcc/arm_tcm_asm.S
Normal file
122
arch/armv7-r/gcc/arm_tcm_asm.S
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* arm_tcm.S
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R TCM driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/tcm.h>
|
||||
|
||||
#if CONFIG_ARM_WITH_TCM
|
||||
|
||||
.text
|
||||
|
||||
.macro tcm_enable, idx, addr_reg, temp_reg
|
||||
orr \temp_reg, \addr_reg, #1
|
||||
mcr p15, 0, \temp_reg, c9, c1, \idx
|
||||
.endm
|
||||
|
||||
.macro tcm_enable_ecc, temp_reg, val
|
||||
mrc p15, 0, \temp_reg, c1, c0, 1
|
||||
orr \temp_reg, \temp_reg, #(\val)
|
||||
mcr p15, 0, \temp_reg, c1, c0, 1
|
||||
.endm
|
||||
|
||||
.macro tcm_disable_ecc, temp_reg, val
|
||||
mrc p15, 0, \temp_reg, c1, c0, 1
|
||||
bic \temp_reg, \temp_reg, #(\val)
|
||||
mcr p15, 0, \temp_reg, c1, c0, 1
|
||||
.endm
|
||||
|
||||
.macro tcm_get_size, idx, size_reg, temp_reg
|
||||
mrc p15, 0, \size_reg, c9, c1, \idx
|
||||
ubfx \size_reg, \size_reg, #2, #5
|
||||
adds \size_reg, #9
|
||||
movs \temp_reg, #1
|
||||
lsls \size_reg, \temp_reg, \size_reg
|
||||
.endm
|
||||
|
||||
.macro tcm_clear, addr_reg, size_reg, temp_reg1, temp_reg2
|
||||
mov \temp_reg1, #0
|
||||
mov \temp_reg2, #0
|
||||
add \size_reg, \addr_reg, \size_reg
|
||||
.Ltcm_loop\@:
|
||||
cmp \addr_reg, \size_reg
|
||||
bhs .Ltcm_loop_end\@
|
||||
stmia \addr_reg!, {\temp_reg1-\temp_reg2}
|
||||
b .Ltcm_loop\@
|
||||
.Ltcm_loop_end\@:
|
||||
.endm
|
||||
|
||||
.arm
|
||||
|
||||
/* This function not store registers,
|
||||
* only used before stack setup.
|
||||
*/
|
||||
FUNCTION(tcma_enable_early)
|
||||
|
||||
/* disable ecc */
|
||||
tcm_disable_ecc r4, ATCMPCEN
|
||||
|
||||
/* read tcma size, r2 save size */
|
||||
tcm_get_size 1, r2, r4
|
||||
|
||||
/* enable tcma, r0 save addr */
|
||||
tcm_enable 1, r0, r4
|
||||
|
||||
/* check enable ecc */
|
||||
cmp r1, #1
|
||||
bne .Lout
|
||||
|
||||
/* clear tcma */
|
||||
tcm_clear r0, r2, r6, r7
|
||||
|
||||
/* enalbe ecc */
|
||||
tcm_enable_ecc r4, ATCMPCEN
|
||||
|
||||
b .Lout
|
||||
|
||||
/* This function not store registers,
|
||||
* only used before stack setup.
|
||||
*/
|
||||
FUNCTION(tcmb_enable_early)
|
||||
|
||||
/* disable ecc */
|
||||
tcm_disable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
|
||||
|
||||
/* read tcma size, r2 save size */
|
||||
tcm_get_size 0, r2, r4
|
||||
|
||||
/* enable tcma, r0 save addr */
|
||||
tcm_enable 0, r0, r4
|
||||
|
||||
/* check enable ecc */
|
||||
cmp r1, #1
|
||||
bne .Lout
|
||||
|
||||
/* clear tcma */
|
||||
tcm_clear r0, r2, r6, r7
|
||||
|
||||
/* enalbe ecc */
|
||||
tcm_enable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
|
||||
|
||||
b .Lout
|
||||
|
||||
/* Clear the TCM, each store must be 64 bits aligned. */
|
||||
FUNCTION(tcm_clear_64bit)
|
||||
|
||||
push {r6, r7}
|
||||
tcm_clear r0, r1, r6, r7
|
||||
pop {r6, r7}
|
||||
|
||||
.Lout:
|
||||
bx lr
|
||||
|
||||
#endif
|
||||
133
arch/armv7-r/gcc/context_saverestore.s
Normal file
133
arch/armv7-r/gcc/context_saverestore.s
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* context_saverestore.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
.macro portMPU_RegisterSave
|
||||
|
||||
MOV r0, #0
|
||||
mpu_save_loop:
|
||||
MCR p15, 0, r0, c6, c2, 0
|
||||
MRC p15, 0, r2, c6, c1, 0
|
||||
STR r2, [r1], #4
|
||||
MRC p15, 0, r2, c6, c1, 4
|
||||
STR r2, [r1], #4
|
||||
MRC p15, 0, r2, c6, c1, 2
|
||||
STR r2, [r1], #4
|
||||
ADD r0, r0, #1
|
||||
CMP r0, #16
|
||||
BNE mpu_save_loop
|
||||
MRC p15, 0, r2, c1, c0, 0
|
||||
STR r2, [r1], #4
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portMPU_RegisterRestore
|
||||
|
||||
MRC p15, 0, r2, c1, c0, 0
|
||||
LDR r0, =(SCTLR_BR | SCTLR_M)
|
||||
BIC r2, r2, r0
|
||||
MCR p15, 0, r2, c1, c0, 0
|
||||
|
||||
MOV r0, #0
|
||||
mpu_restore_loop:
|
||||
MCR p15, 0, r0, c6, c2, 0
|
||||
LDR r2, [r1], #4
|
||||
MCR p15, 0, r2, c6, c1, 0
|
||||
LDR r2, [r1], #4
|
||||
MCR p15, 0, r2, c6, c1, 4
|
||||
LDR r2, [r1], #4
|
||||
MCR p15, 0, r2, c6, c1, 2
|
||||
ADD r0, r0, #1
|
||||
CMP r0, #16
|
||||
BNE mpu_restore_loop
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 0
|
||||
LDR r2, =(SCTLR_BR | SCTLR_M)
|
||||
ORR r0, r0, r2
|
||||
LDR r2, [r1], #4
|
||||
TST r2, #SCTLR_M
|
||||
MCRNE p15, 0, r0, c1, c0, 0
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portCPU_RegisterSave
|
||||
|
||||
PUSH {r0-r3, r12}
|
||||
|
||||
STMIA r1, {r0-r12}
|
||||
STR lr, [r1, #(4*REG_R15)]
|
||||
MRS r2, SPSR
|
||||
STR r2, [r1, #(4*REG_CPSR)]
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
ADD r3, r1, #(4*REG_S0)
|
||||
VSTMIA r3!, {s0-s31}
|
||||
VMRS r2, fpscr
|
||||
STR r2, [r3], #4
|
||||
#endif
|
||||
|
||||
CPS #SYS_MODE
|
||||
ADD r3, r1, #(4*REG_R13)
|
||||
STMIA r3!, {sp, lr}
|
||||
|
||||
CPS #SVC_MODE
|
||||
ADD r1, r1, #XCPTCONTEXT_SIZE
|
||||
portMPU_RegisterSave
|
||||
|
||||
PUSH {lr}
|
||||
LDR r0, arch_clean_invalidate_dcache_all_const
|
||||
BLX r0
|
||||
POP {lr}
|
||||
|
||||
POP {r0-r3, r12}
|
||||
MOVS pc, lr
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portCPU_RegisterRestore
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
ADD r3, r1, #(4*REG_S0)
|
||||
VLDMIA r3!, {s0-s31}
|
||||
LDR r2, [r3], #4
|
||||
VMSR fpscr, r2
|
||||
#endif
|
||||
|
||||
ADD r4, r1, #(4*REG_R15)
|
||||
LDMIA r4, {r2, r3}
|
||||
MOV lr, r2
|
||||
MSR SPSR_cxsf, r3
|
||||
|
||||
CPS #SYS_MODE
|
||||
ADD r4, r1, #(4*REG_R13)
|
||||
LDMIA r4, {r2, r3}
|
||||
MOV sp, r2
|
||||
MOV lr, r3
|
||||
|
||||
PUSH {lr}
|
||||
MOV lr, r1
|
||||
|
||||
ADD r1, r1, #XCPTCONTEXT_SIZE
|
||||
portMPU_RegisterRestore
|
||||
|
||||
LDMIA lr, {r0-r12}
|
||||
POP {lr}
|
||||
|
||||
CPS #SVC_MODE
|
||||
MOVS pc, lr
|
||||
|
||||
.endm
|
||||
63
arch/armv7-r/iar/arm_atomic.S
Normal file
63
arch/armv7-r/iar/arm_atomic.S
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* arm_atomic.s
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM atomic function.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
* 2021-09-08 Wanghao.Xu Export function symbols
|
||||
*/
|
||||
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
|
||||
PUBLIC arch_atomic_swap
|
||||
PUBLIC arch_atomic_add
|
||||
PUBLIC arch_atomic_and
|
||||
PUBLIC arch_atomic_or
|
||||
|
||||
SECTION .text:CODE(2)
|
||||
|
||||
arch_atomic_swap:
|
||||
.Lloop_atomic_swap:
|
||||
ldrex r12, [r0]
|
||||
strex r2, r1, [r0]
|
||||
cmp r2, #0
|
||||
bne .Lloop_atomic_swap
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
arch_atomic_add:
|
||||
.Lloop_atomic_add:
|
||||
ldrex r12, [r0]
|
||||
add r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .Lloop_atomic_add
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
arch_atomic_and:
|
||||
.Lloop_atomic_and:
|
||||
ldrex r12, [r0]
|
||||
and r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .Lloop_atomic_and
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
arch_atomic_or:
|
||||
.Lloop_atomic_or:
|
||||
ldrex r12, [r0]
|
||||
orr r2, r12, r1
|
||||
strex r3, r2, [r0]
|
||||
cmp r3, #0
|
||||
bne .Lloop_atomic_or
|
||||
mov r0, r12
|
||||
bx lr
|
||||
|
||||
END
|
||||
324
arch/armv7-r/iar/arm_cache.S
Normal file
324
arch/armv7-r/iar/arm_cache.S
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
INCLUDE armv7-r/cache.h
|
||||
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
|
||||
PUBLIC arch_disable_cache
|
||||
PUBLIC arch_enable_cache
|
||||
PUBLIC arch_clean_cache_range
|
||||
PUBLIC arch_clean_invalidate_cache_range
|
||||
PUBLIC arch_clean_invalidate_dcache_all
|
||||
PUBLIC arch_invalidate_cache_range
|
||||
PUBLIC arch_sync_cache_range
|
||||
|
||||
SECTION .text:CODE(2)
|
||||
|
||||
/* void arch_disable_cache(uint flags) */
|
||||
arch_disable_cache:
|
||||
stmfd sp!, {r4-r11, lr}
|
||||
|
||||
mov r7, r0 // save flags
|
||||
|
||||
mrs r8, cpsr // save the old interrupt state
|
||||
cpsid iaf // interrupts disabled
|
||||
|
||||
.Ldcache_disable:
|
||||
tst r7, #DCACHE
|
||||
beq .Licache_disable
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
tst r0, #(1<<2) // is the dcache already disabled?
|
||||
beq .Ldcache_already_disabled
|
||||
|
||||
bic r0, #(1<<2)
|
||||
mcr p15, 0, r0, c1, c0, 0 // disable dcache
|
||||
|
||||
// flush and invalidate the dcache
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl flush_invalidate_cache_v7
|
||||
|
||||
b .Ldcache_disable_L2
|
||||
|
||||
.Ldcache_already_disabled:
|
||||
// make sure all of the caches are invalidated
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl invalidate_cache_v7
|
||||
|
||||
.Ldcache_disable_L2:
|
||||
|
||||
#if CONFIG_ARCH_L2CACHE
|
||||
// disable the L2, if present
|
||||
mrc p15, 0, r0, c1, c0, 1 // aux cr1
|
||||
bic r0, #(1<<1)
|
||||
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
|
||||
#endif
|
||||
|
||||
.Licache_disable:
|
||||
tst r7, #ICACHE
|
||||
beq .Ldone_disable
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
bic r0, #(1<<12)
|
||||
mcr p15, 0, r0, c1, c0, 0 // disable icache
|
||||
|
||||
.Ldone_disable:
|
||||
// make sure the icache is always invalidated
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
msr cpsr_cxsf, r8
|
||||
ldmfd sp!, {r4-r11, pc}
|
||||
|
||||
/* void arch_enable_cache(uint flags) */
|
||||
arch_enable_cache:
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
mov r7, r0 // save flags
|
||||
|
||||
mrs r8, cpsr // save the old interrupt state
|
||||
cpsid iaf // interrupts disabled
|
||||
|
||||
.Ldcache_enable:
|
||||
tst r7, #DCACHE
|
||||
beq .Licache_enable
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
tst r0, #(1<<2) // is the dcache already enabled?
|
||||
bne .Licache_enable
|
||||
|
||||
// invalidate L1 and L2
|
||||
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
|
||||
bl invalidate_cache_v7
|
||||
|
||||
#if CONFIG_ARCH_L2CACHE
|
||||
// enable the L2, if present
|
||||
mrc p15, 0, r0, c1, c0, 1 // aux cr1
|
||||
orr r0, #(1<<1)
|
||||
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
|
||||
#endif
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
orr r0, #(1<<2)
|
||||
mcr p15, 0, r0, c1, c0, 0 // enable dcache
|
||||
|
||||
.Licache_enable:
|
||||
tst r7, #ICACHE
|
||||
beq .Ldone_enable
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 // cr1
|
||||
orr r0, #(1<<12)
|
||||
mcr p15, 0, r0, c1, c0, 0 // enable icache
|
||||
|
||||
.Ldone_enable:
|
||||
isb
|
||||
msr cpsr_cxsf, r8
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
// flush & invalidate cache routine, trashes r0-r6, r9-r11
|
||||
flush_invalidate_cache_v7:
|
||||
/* from ARMv7 manual, B2-17 */
|
||||
dmb
|
||||
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
|
||||
ANDS R3, R0, #0x7000000
|
||||
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
|
||||
BEQ .Lfinished
|
||||
MOV R10, #0
|
||||
.Loop1:
|
||||
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
|
||||
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
|
||||
AND R1, R1, #7 // get those 3 bits alone
|
||||
CMP R1, #2
|
||||
BLT .Lskip // no cache or only instruction cache at this level
|
||||
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
|
||||
isb // ISB to sync the change to the CacheSizeID reg
|
||||
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
|
||||
AND R2, R1, #0x7 // extract the line length field
|
||||
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
|
||||
LDR R4, =0x3FF
|
||||
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
|
||||
CLZ R5, R4 // R5 is the bit position of the way size increment
|
||||
LDR R6, =0x00007FFF
|
||||
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
|
||||
.Loop2:
|
||||
MOV R9, R4 // R9 working copy of the max way size (right aligned)
|
||||
.Loop3:
|
||||
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
|
||||
ORR R11, R11, R6, LSL R2 // factor in the index number
|
||||
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
|
||||
SUBS R9, R9, #1 // decrement the way number
|
||||
BGE .Loop3
|
||||
SUBS R6, R6, #1 // decrement the index
|
||||
BGE .Loop2
|
||||
.Lskip:
|
||||
ADD R10, R10, #2 // increment the cache number
|
||||
CMP R3, R10
|
||||
BGT .Loop1
|
||||
|
||||
.Lfinished:
|
||||
mov r10, #0
|
||||
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
|
||||
dsb
|
||||
isb
|
||||
|
||||
bx lr
|
||||
|
||||
// invalidate cache routine, trashes r0-r6, r9-r11
|
||||
invalidate_cache_v7:
|
||||
/* from ARMv7 manual, B2-17 */
|
||||
dmb
|
||||
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
|
||||
ANDS R3, R0, #0x7000000
|
||||
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
|
||||
BEQ .Lfinished_invalidate
|
||||
MOV R10, #0
|
||||
.Loop1_invalidate:
|
||||
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
|
||||
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
|
||||
AND R1, R1, #7 // get those 3 bits alone
|
||||
CMP R1, #2
|
||||
BLT .Lskip_invalidate // no cache or only instruction cache at this level
|
||||
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
|
||||
isb // ISB to sync the change to the CacheSizeID reg
|
||||
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
|
||||
AND R2, R1, #0x7 // extract the line length field
|
||||
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
|
||||
LDR R4, =0x3FF
|
||||
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
|
||||
CLZ R5, R4 // R5 is the bit position of the way size increment
|
||||
LDR R6, =0x00007FFF
|
||||
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
|
||||
.Loop2_invalidate:
|
||||
MOV R9, R4 // R9 working copy of the max way size (right aligned)
|
||||
.Loop3_invalidate:
|
||||
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
|
||||
ORR R11, R11, R6, LSL R2 // factor in the index number
|
||||
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
|
||||
SUBS R9, R9, #1 // decrement the way number
|
||||
BGE .Loop3_invalidate
|
||||
SUBS R6, R6, #1 // decrement the index
|
||||
BGE .Loop2_invalidate
|
||||
.Lskip_invalidate:
|
||||
ADD R10, R10, #2 // increment the cache number
|
||||
CMP R3, R10
|
||||
BGT .Loop1_invalidate
|
||||
|
||||
.Lfinished_invalidate:
|
||||
dsb
|
||||
mov r10, #0
|
||||
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
|
||||
isb
|
||||
|
||||
bx lr
|
||||
|
||||
/* void arch_flush_cache_range(addr_t start, size_t len); */
|
||||
arch_clean_cache_range:
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mov r3, r0 // save the start address
|
||||
add r2, r0, r1 // calculate the end address
|
||||
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
|
||||
.Loop_clean:
|
||||
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
|
||||
add r0, #CONFIG_ARCH_CACHE_LINE
|
||||
cmp r0, r2
|
||||
blo .Loop_clean
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
|
||||
arch_clean_invalidate_cache_range:
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mov r3, r0 // save the start address
|
||||
add r2, r0, r1 // calculate the end address
|
||||
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
|
||||
.Loop_clean_invalidate:
|
||||
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate dcache to PoC by MVA
|
||||
add r0, r0, #CONFIG_ARCH_CACHE_LINE
|
||||
cmp r0, r2
|
||||
blo .Loop_clean_invalidate
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_clean_invalidate_dcache_all(void); */
|
||||
arch_clean_invalidate_dcache_all:
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mrc p15, 1, r0, c0, c0, 0 /* Read the Cache Size Identification Register */
|
||||
ldr r3, =0x7fff /* Isolate the NumSets field (bits 13-27) */
|
||||
and r0, r3, r0, lsr #13 /* r0=NumSets (number of sets - 1) */
|
||||
|
||||
mov r1, #0 /* r1 = way loop counter */
|
||||
way_loop:
|
||||
|
||||
mov r3, #0 /* r3 = set loop counter */
|
||||
set_loop:
|
||||
mov r2, r1, lsl #30 /* r2 = way loop counter << 30 */
|
||||
orr r2, r3, lsl #5 /* r2 = set/way cache operation format */
|
||||
mcr p15, 0, r2, c7, c14, 2 /* Data Cache Clean Invalidate by Set/Way */
|
||||
add r3, r3, #1 /* Increment set counter */
|
||||
cmp r0, r3 /* Last set? */
|
||||
bge set_loop /* Keep looping if not */
|
||||
|
||||
add r1, r1, #1 /* Increment the way counter */
|
||||
cmp r1, #4 /* Last way? (four ways assumed) */
|
||||
bne way_loop /* Keep looping if not */
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_invalidate_cache_range(addr_t start, size_t len); */
|
||||
arch_invalidate_cache_range:
|
||||
#if CONFIG_ARM_WITH_CP15
|
||||
mov r3, r0 // save the start address
|
||||
add r2, r0, r1 // calculate the end address
|
||||
bic r0, #(CONFIG_ARCH_CACHE_LINE-1) // align the start with a cache line
|
||||
.Loop_invalidate:
|
||||
mcr p15, 0, r0, c7, c6, 1 // invalidate dcache to PoC by MVA
|
||||
add r0, r0, #CONFIG_ARCH_CACHE_LINE
|
||||
cmp r0, r2
|
||||
blo .Loop_invalidate
|
||||
|
||||
dsb
|
||||
#endif
|
||||
bx lr
|
||||
|
||||
/* void arch_sync_cache_range(addr_t start, size_t len); */
|
||||
arch_sync_cache_range:
|
||||
push { r14 }
|
||||
bl arch_clean_cache_range
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
|
||||
|
||||
pop { pc }
|
||||
|
||||
#endif
|
||||
|
||||
END
|
||||
292
arch/armv7-r/iar/arm_exceptions.S
Normal file
292
arch/armv7-r/iar/arm_exceptions.S
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Travis Geiselbrecht
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
|
||||
EXTERN arm_undefined_handler
|
||||
EXTERN arm_prefetch_abort_handler
|
||||
EXTERN arm_data_abort_handler
|
||||
EXTERN arm_irq_handler
|
||||
EXTERN arm_fiq_handler
|
||||
|
||||
PUBLIC Arm_Undefined_Handler
|
||||
PUBLIC Arm_SWI_Handler
|
||||
PUBLIC Arm_Prefetch_Handler
|
||||
PUBLIC Arm_Abort_Handler
|
||||
PUBLIC Arm_IRQ_Handler
|
||||
PUBLIC Arm_FIQ_Handler
|
||||
|
||||
PUBLIC arm_save_mode_regs
|
||||
PUBLIC arm_reserved
|
||||
|
||||
SECTION .text:CODE:ROOT(2)
|
||||
|
||||
; macros to align and unalign the stack on 8 byte boundary for ABI compliance
|
||||
stack_align macro tempreg
|
||||
; make sure the stack is aligned
|
||||
mov tempreg, sp
|
||||
tst sp, #4
|
||||
subeq sp, #4
|
||||
push { tempreg }
|
||||
|
||||
; tempreg holds the original stack
|
||||
endm
|
||||
|
||||
stack_restore macro tempreg
|
||||
; restore the potentially unaligned stack
|
||||
pop { tempreg }
|
||||
mov sp, tempreg
|
||||
endm
|
||||
|
||||
; save and disable the vfp unit
|
||||
vfp_save macro temp1
|
||||
; save old fpexc
|
||||
vmrs temp1, fpexc
|
||||
|
||||
push { temp1 }
|
||||
|
||||
; hard disable the vfp unit
|
||||
bic temp1, #(1<<30)
|
||||
vmsr fpexc, temp1
|
||||
endm
|
||||
|
||||
; restore the vfp enable/disable state
|
||||
vfp_restore macro temp1
|
||||
; restore fpexc
|
||||
pop { temp1 }
|
||||
|
||||
vmsr fpexc, temp1
|
||||
endm
|
||||
|
||||
; Save callee trashed registers.
|
||||
; At exit r0 contains a pointer to the register frame.
|
||||
|
||||
save macro
|
||||
; save spsr and r14 onto the svc stack
|
||||
srsdb #0x13!
|
||||
|
||||
; switch to svc mode, interrupts disabled
|
||||
cpsid i,#0x13
|
||||
|
||||
; save callee trashed regs and lr
|
||||
push { r0-r4, r12, lr }
|
||||
|
||||
; save user space sp/lr
|
||||
sub sp, #8
|
||||
stmia sp, { r13, r14 }^
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
; save and disable the vfp unit
|
||||
vfp_save r0
|
||||
#endif
|
||||
|
||||
; make sure the stack is 8 byte aligned
|
||||
stack_align r0
|
||||
|
||||
; r0 now holds the pointer to the original iframe (before alignment)
|
||||
endm
|
||||
|
||||
save_offset macro offset
|
||||
sub lr, offset
|
||||
save
|
||||
|
||||
endm
|
||||
|
||||
restore macro
|
||||
; undo the stack alignment we did before
|
||||
stack_restore r0
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
; restore the old state of the vfp unit
|
||||
vfp_restore r0
|
||||
#endif
|
||||
|
||||
; restore user space sp/lr
|
||||
ldmia sp, { r13, r14 }^
|
||||
add sp, #8
|
||||
|
||||
pop { r0-r4, r12, lr }
|
||||
|
||||
; return to whence we came from
|
||||
rfeia sp!
|
||||
endm
|
||||
|
||||
; Save all registers.
|
||||
; At exit r0 contains a pointer to the register frame.
|
||||
|
||||
saveall macro
|
||||
; save spsr and r14 onto the svc stack
|
||||
srsdb #0x13!
|
||||
|
||||
; switch to svc mode, interrupts disabled
|
||||
cpsid i,#0x13
|
||||
|
||||
; save all regs
|
||||
push { r0-r12, lr }
|
||||
|
||||
; save user space sp/lr
|
||||
sub sp, #8
|
||||
stmia sp, { r13, r14 }^
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
; save and disable the vfp unit
|
||||
vfp_save r0
|
||||
#endif
|
||||
|
||||
; make sure the stack is 8 byte aligned
|
||||
stack_align r0
|
||||
|
||||
; r0 now holds the pointer to the original iframe (before alignment)
|
||||
endm
|
||||
|
||||
saveall_offset macro offset
|
||||
sub lr, offset
|
||||
saveall
|
||||
endm
|
||||
|
||||
restoreall macro
|
||||
; undo the stack alignment we did before
|
||||
stack_restore r0
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
; restore the old state of the vfp unit
|
||||
vfp_restore r0
|
||||
#endif
|
||||
|
||||
; restore user space sp/lr
|
||||
ldmia sp, { r13, r14 }^
|
||||
add sp, #8
|
||||
|
||||
pop { r0-r12, r14 }
|
||||
|
||||
; return to whence we came from
|
||||
rfeia sp!
|
||||
endm
|
||||
|
||||
arm_save_mode_regs:
|
||||
mrs r1, cpsr
|
||||
|
||||
stmia r0, { r13, r14 }^ /* usr */
|
||||
add r0, #8
|
||||
|
||||
cps #0x11 /* fiq */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x12 /* irq */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x13 /* svc */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x17 /* abt */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x1b /* und */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
cps #0x1f /* sys */
|
||||
str r13, [r0], #4
|
||||
str r14, [r0], #4
|
||||
|
||||
msr cpsr_c, r1
|
||||
|
||||
bx lr
|
||||
|
||||
Arm_Undefined_Handler:
|
||||
save
|
||||
; r0 now holds pointer to iframe
|
||||
|
||||
bl arm_undefined_handler
|
||||
|
||||
restore
|
||||
|
||||
Arm_Prefetch_Handler:
|
||||
saveall_offset #4
|
||||
; r0 now holds pointer to iframe
|
||||
|
||||
bl arm_prefetch_abort_handler
|
||||
|
||||
restoreall
|
||||
|
||||
Arm_Abort_Handler:
|
||||
saveall_offset #8
|
||||
; r0 now holds pointer to iframe
|
||||
|
||||
bl arm_data_abort_handler
|
||||
|
||||
restoreall
|
||||
|
||||
Arm_SWI_Handler:
|
||||
/* not support */
|
||||
ldr r0,=Arm_SWI_Handler
|
||||
bx r0
|
||||
|
||||
Arm_IRQ_Handler:
|
||||
sub lr, lr, #4
|
||||
|
||||
srsdb #0x13!
|
||||
|
||||
cpsid i,#0x13
|
||||
|
||||
push {r0-r4, r12, lr}
|
||||
|
||||
sub sp, #8
|
||||
stmia sp, {r13, r14}^
|
||||
|
||||
mov r2, sp
|
||||
tst sp, #4
|
||||
subeq sp, #4
|
||||
push {r2}
|
||||
|
||||
push {r0, lr}
|
||||
|
||||
bl arm_irq_handler
|
||||
|
||||
pop {r0, lr}
|
||||
|
||||
pop {r2}
|
||||
mov sp, r2
|
||||
|
||||
ldmia sp, {r13, r14}^
|
||||
add sp, #8
|
||||
|
||||
pop {r0-r4, r12, lr}
|
||||
|
||||
rfeia sp!
|
||||
|
||||
Arm_FIQ_Handler:
|
||||
push {r0-r3, r12, lr}
|
||||
blx arm_fiq_handler
|
||||
pop {r0-r3, r12, lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
arm_reserved:
|
||||
b .
|
||||
|
||||
END
|
||||
43
arch/armv7-r/iar/arm_fullcontextrestore.S
Normal file
43
arch/armv7-r/iar/arm_fullcontextrestore.S
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* arm_fullcontextrestore.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM full context restore.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
INCLUDE armv7-r/svcall.h
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
PUBLIC arm_fullcontextrestore
|
||||
|
||||
SECTION .text:CODE(2)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_fullcontextrestore
|
||||
****************************************************************************/
|
||||
|
||||
arm_fullcontextrestore:
|
||||
|
||||
cps #0x1F /* Enter sys mode */
|
||||
|
||||
/* Perform the System call with R0=1 and R1=regs */
|
||||
|
||||
mov r1, r0 /* R1: regs */
|
||||
mov r0, #SYS_restore_context /* R0: restore context */
|
||||
svc 0 /* Force synchronous SVCall (or Hard Fault) */
|
||||
|
||||
/* This call should not return */
|
||||
|
||||
bx lr /* Unnecessary ... will not return */
|
||||
|
||||
END
|
||||
39
arch/armv7-r/iar/arm_saveusercontext.S
Normal file
39
arch/armv7-r/iar/arm_saveusercontext.S
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* arm_saveusercontext.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM save user context.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
INCLUDE armv7-r/svcall.h
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
PUBLIC arm_saveusercontext
|
||||
|
||||
SECTION .text:CODE(2)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_saveusercontext
|
||||
****************************************************************************/
|
||||
|
||||
arm_saveusercontext:
|
||||
|
||||
/* Perform the System call with R0=0 and R1=regs */
|
||||
|
||||
mov r1, r0 /* R1: regs */
|
||||
mov r0, #SYS_save_context /* R0: save context (also return value) */
|
||||
svc 0 /* Force synchronous SVCall (or Hard Fault) */
|
||||
|
||||
bx lr
|
||||
|
||||
END
|
||||
40
arch/armv7-r/iar/arm_switchcontext.S
Normal file
40
arch/armv7-r/iar/arm_switchcontext.S
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* arm_switchcontext.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM switch context.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
INCLUDE armv7-r/svcall.h
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
PUBLIC arm_switchcontext
|
||||
|
||||
SECTION .text:CODE(2)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_switchcontext
|
||||
****************************************************************************/
|
||||
|
||||
arm_switchcontext:
|
||||
|
||||
/* Perform the System call with R0=2 */
|
||||
|
||||
mov r0, #SYS_switch_context /* R0: context switch */
|
||||
svc 0 /* Force synchronous SVCall (or Hard Fault) */
|
||||
|
||||
/* We will get here only after the rerturn from the context switch */
|
||||
|
||||
bx lr
|
||||
|
||||
END
|
||||
127
arch/armv7-r/iar/arm_tcm_asm.S
Normal file
127
arch/armv7-r/iar/arm_tcm_asm.S
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* arm_tcm.S
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R TCM driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
INCLUDE config.h
|
||||
INCLUDE compiler.h
|
||||
INCLUDE armv7-r/tcm.h
|
||||
|
||||
#if CONFIG_ARM_WITH_TCM
|
||||
|
||||
PUBLIC tcma_enable_early
|
||||
PUBLIC tcmb_enable_early
|
||||
|
||||
SECTION .text:CODE(2)
|
||||
|
||||
tcm_enable MACRO idx addr_reg temp_reg
|
||||
orr temp_reg, addr_reg, #1
|
||||
mcr p15, 0, temp_reg, c9, c1, idx
|
||||
ENDM
|
||||
|
||||
tcm_enable_ecc MACRO temp_reg val
|
||||
mrc p15, 0, temp_reg, c1, c0, 1
|
||||
orr temp_reg, temp_reg, #(val)
|
||||
mcr p15, 0, temp_reg, c1, c0, 1
|
||||
ENDM
|
||||
|
||||
tcm_disable_ecc MACRO temp_reg val
|
||||
mrc p15, 0, temp_reg, c1, c0, 1
|
||||
bic temp_reg, temp_reg, #(val)
|
||||
mcr p15, 0, temp_reg, c1, c0, 1
|
||||
ENDM
|
||||
|
||||
tcm_get_size MACRO idx size_reg temp_reg
|
||||
mrc p15, 0, size_reg, c9, c1, idx
|
||||
ubfx size_reg, size_reg, #2, #5
|
||||
adds size_reg, #9
|
||||
movs temp_reg, #1
|
||||
lsls size_reg, temp_reg, size_reg
|
||||
ENDM
|
||||
|
||||
tcm_clear MACRO addr_reg size_reg temp_reg1 temp_reg2
|
||||
local .Ltcm_loop
|
||||
local .Ltcm_loop_end
|
||||
mov temp_reg1, #0
|
||||
mov temp_reg2, #0
|
||||
add size_reg, addr_reg, size_reg
|
||||
.Ltcm_loop:
|
||||
cmp addr_reg, size_reg
|
||||
bhs .Ltcm_loop_end
|
||||
stmia addr_reg!, {temp_reg1-temp_reg2}
|
||||
b .Ltcm_loop
|
||||
.Ltcm_loop_end:
|
||||
ENDM
|
||||
|
||||
/* This function not store registers,
|
||||
* only used before stack setup.
|
||||
*/
|
||||
tcma_enable_early:
|
||||
|
||||
/* disable ecc */
|
||||
tcm_disable_ecc r4, ATCMPCEN
|
||||
|
||||
/* read tcma size, r2 save size */
|
||||
tcm_get_size 1, r2, r4
|
||||
|
||||
/* enable tcma, r0 save addr */
|
||||
tcm_enable 1, r0, r4
|
||||
|
||||
/* check enable ecc */
|
||||
cmp r1, #1
|
||||
bne .Lout
|
||||
|
||||
/* clear tcma */
|
||||
tcm_clear r0, r2, r6, r7
|
||||
|
||||
/* enalbe ecc */
|
||||
tcm_enable_ecc r4, ATCMPCEN
|
||||
|
||||
b .Lout
|
||||
|
||||
/* This function not store registers,
|
||||
* only used before stack setup.
|
||||
*/
|
||||
tcmb_enable_early:
|
||||
|
||||
/* disable ecc */
|
||||
tcm_disable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
|
||||
|
||||
/* read tcma size, r2 save size */
|
||||
tcm_get_size 0, r2, r4
|
||||
|
||||
/* enable tcma, r0 save addr */
|
||||
tcm_enable 0, r0, r4
|
||||
|
||||
/* check enable ecc */
|
||||
cmp r1, #1
|
||||
bne .Lout
|
||||
|
||||
/* clear tcma */
|
||||
tcm_clear r0, r2, r6, r7
|
||||
|
||||
/* enalbe ecc */
|
||||
tcm_enable_ecc r4, (B0TCMPCEN | B1TCMPCEN)
|
||||
|
||||
b .Lout
|
||||
|
||||
/* Clear the TCM, each store must be 64 bits aligned. */
|
||||
tcm_clear_64bit:
|
||||
|
||||
push {r6, r7}
|
||||
tcm_clear r0, r1, r6, r7
|
||||
pop {r6, r7}
|
||||
|
||||
.Lout:
|
||||
bx lr
|
||||
|
||||
#endif
|
||||
|
||||
END
|
||||
134
arch/armv7-r/iar/context_saverestore.s
Normal file
134
arch/armv7-r/iar/context_saverestore.s
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* context_saverestore.S
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
portMPU_RegisterSave MACRO
|
||||
|
||||
MOV r0, #0
|
||||
mpu_save_loop:
|
||||
MCR p15, 0, r0, c6, c2, 0
|
||||
MRC p15, 0, r2, c6, c1, 0
|
||||
STR r2, [r1], #4
|
||||
MRC p15, 0, r2, c6, c1, 4
|
||||
STR r2, [r1], #4
|
||||
MRC p15, 0, r2, c6, c1, 2
|
||||
STR r2, [r1], #4
|
||||
ADD r0, r0, #1
|
||||
CMP r0, #16
|
||||
BNE mpu_save_loop
|
||||
MRC p15, 0, r2, c1, c0, 0
|
||||
STR r2, [r1], #4
|
||||
|
||||
ENDM
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
portMPU_RegisterRestore MACRO
|
||||
|
||||
MRC p15, 0, r2, c1, c0, 0
|
||||
LDR r0, =(SCTLR_BR | SCTLR_M)
|
||||
BIC r2, r2, r0
|
||||
MCR p15, 0, r2, c1, c0, 0
|
||||
|
||||
MOV r0, #0
|
||||
mpu_restore_loop:
|
||||
MCR p15, 0, r0, c6, c2, 0
|
||||
LDR r2, [r1], #4
|
||||
MCR p15, 0, r2, c6, c1, 0
|
||||
LDR r2, [r1], #4
|
||||
MCR p15, 0, r2, c6, c1, 4
|
||||
LDR r2, [r1], #4
|
||||
MCR p15, 0, r2, c6, c1, 2
|
||||
ADD r0, r0, #1
|
||||
CMP r0, #16
|
||||
BNE mpu_restore_loop
|
||||
|
||||
MRC p15, 0, r0, c1, c0, 0
|
||||
LDR r2, =(SCTLR_BR | SCTLR_M)
|
||||
ORR r0, r0, r2
|
||||
LDR r2, [r1], #4
|
||||
TST r2, #SCTLR_M
|
||||
MCRNE p15, 0, r0, c1, c0, 0
|
||||
|
||||
ENDM
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
portCPU_RegisterSave MACRO
|
||||
|
||||
PUSH {r0-r3, r12}
|
||||
|
||||
STMIA r1, {r0-r12}
|
||||
STR lr, [r1, #(4*REG_R15)]
|
||||
MRS r2, SPSR
|
||||
STR r2, [r1, #(4*REG_CPSR)]
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
ADD r3, r1, #(4*REG_S0)
|
||||
VSTMIA r3!, {s0-s31}
|
||||
VMRS r2, fpscr
|
||||
STR r2, [r3], #4
|
||||
#endif
|
||||
|
||||
CPS #SYS_MODE
|
||||
ADD r3, r1, #(4*REG_R13)
|
||||
STMIA r3!, {sp, lr}
|
||||
|
||||
CPS #SVC_MODE
|
||||
ADD r1, r1, #XCPTCONTEXT_SIZE
|
||||
portMPU_RegisterSave
|
||||
|
||||
PUSH {lr}
|
||||
LDR r0, arch_clean_invalidate_dcache_all_const
|
||||
BLX r0
|
||||
POP {lr}
|
||||
|
||||
POP {r0-r3, r12}
|
||||
MOVS pc, lr
|
||||
|
||||
ENDM
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
portCPU_RegisterRestore MACRO
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
ADD r3, r1, #(4*REG_S0)
|
||||
VLDMIA r3!, {s0-s31}
|
||||
LDR r2, [r3], #4
|
||||
VMSR fpscr, r2
|
||||
#endif
|
||||
|
||||
ADD r4, r1, #(4*REG_R15)
|
||||
LDMIA r4, {r2, r3}
|
||||
MOV lr, r2
|
||||
MSR SPSR_cxsf, r3
|
||||
|
||||
CPS #SYS_MODE
|
||||
ADD r4, r1, #(4*REG_R13)
|
||||
LDMIA r4, {r2, r3}
|
||||
MOV sp, r2
|
||||
MOV lr, r3
|
||||
|
||||
PUSH {lr}
|
||||
MOV lr, r1
|
||||
|
||||
ADD r1, r1, #XCPTCONTEXT_SIZE
|
||||
portMPU_RegisterRestore
|
||||
|
||||
LDMIA lr, {r0-r12}
|
||||
POP {lr}
|
||||
|
||||
CPS #SVC_MODE
|
||||
MOVS pc, lr
|
||||
|
||||
ENDM
|
||||
|
||||
77
arch/include/armv7-r/arm.h
Normal file
77
arch/include/armv7-r/arm.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* arm.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARMV7R common register interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef ARMV7R_ARM_H
|
||||
#define ARMV7R_ARM_H
|
||||
|
||||
#define MODE_USR 0x10
|
||||
#define MODE_FIQ 0x11
|
||||
#define MODE_IRQ 0x12
|
||||
#define MODE_SVC 0x13
|
||||
#define MODE_ABT 0x17
|
||||
#define MODE_UND 0x1B
|
||||
#define MODE_SYS 0x1F
|
||||
|
||||
#define MODE_MASK 0x1F
|
||||
|
||||
/* SCTLR */
|
||||
|
||||
#define SCTLR_M (1 << 0)
|
||||
#define SCTLR_A (1 << 1)
|
||||
#define SCTLR_C (1 << 2)
|
||||
#define SCTLR_CCP15BEN (1 << 5)
|
||||
#define SCTLR_B (1 << 7)
|
||||
#define SCTLR_SW (1 << 10)
|
||||
#define SCTLR_Z (1 << 11)
|
||||
#define SCTLR_I (1 << 12)
|
||||
#define SCTLR_V (1 << 13)
|
||||
#define SCTLR_RR (1 << 14)
|
||||
#define SCTLR_BR (1 << 17)
|
||||
#define SCTLR_DZ (1 << 19)
|
||||
#define SCTLR_FI (1 << 21)
|
||||
#define SCTLR_U (1 << 22)
|
||||
#define SCTLR_VE (1 << 24)
|
||||
#define SCTLR_EE (1 << 25)
|
||||
#define SCTLR_NMFI (1 << 27)
|
||||
#define SCTLR_TE (1 << 30)
|
||||
#define SCTLR_IE (1 << 31)
|
||||
|
||||
/* PSR */
|
||||
|
||||
#define PSR_MODE_SHIFT (0)
|
||||
#define PSR_MODE_MASK (0x1f << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_USR (MODE_USR << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_FIQ (MODE_FIQ << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_IRQ (MODE_IRQ << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_SVC (MODE_SVC << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_ABT (MODE_ABT << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_UND (MODE_UND << PSR_MODE_SHIFT)
|
||||
#define PSR_MODE_SYS (MODE_SYS << PSR_MODE_SHIFT)
|
||||
#define PSR_T_BIT (1 << 5)
|
||||
#define PSR_F_BIT (1 << 6)
|
||||
#define PSR_I_BIT (1 << 7)
|
||||
#define PSR_A_BIT (1 << 8)
|
||||
#define PSR_E_BIT (1 << 9)
|
||||
#define PSR_IT27_SHIFT (10)
|
||||
#define PSR_IT27_MASK (0x3f << PSR_IT27_SHIFT)
|
||||
#define PSR_GE_SHIFT (16)
|
||||
#define PSR_GE_MASK (15 << PSR_GE_SHIFT)
|
||||
#define PSR_J_BIT (1 << 24)
|
||||
#define PSR_IT01_SHIFT (25)
|
||||
#define PSR_IT01_MASK (3 << PSR_IT01_SHIFT)
|
||||
#define PSR_Q_BIT (1 << 27)
|
||||
#define PSR_V_BIT (1 << 28)
|
||||
#define PSR_C_BIT (1 << 29)
|
||||
#define PSR_Z_BIT (1 << 30)
|
||||
#define PSR_N_BIT (1 << 31)
|
||||
|
||||
#endif
|
||||
62
arch/include/armv7-r/atomic.h
Normal file
62
arch/include/armv7-r/atomic.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* atomic.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM atomic interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_ATOMIC_H
|
||||
#define INCLUDE_ARCH_ATOMIC_H
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <compiler.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
/*
|
||||
* atomic swap.
|
||||
*
|
||||
* @ptr address of data A.
|
||||
* @val value of data B.
|
||||
* @return old value of data A.
|
||||
*/
|
||||
int arch_atomic_swap(int *ptr, int val);
|
||||
|
||||
/*
|
||||
* atomic add.
|
||||
*
|
||||
* @ptr address of data A.
|
||||
* @val value of data B.
|
||||
* @return old value of data A.
|
||||
*/
|
||||
int arch_atomic_add(int *ptr, int val);
|
||||
|
||||
/*
|
||||
* atomic and.
|
||||
*
|
||||
* @ptr address of data A.
|
||||
* @val value of data B.
|
||||
* @return old value of data A.
|
||||
*/
|
||||
int arch_atomic_and(int *ptr, int val);
|
||||
|
||||
/*
|
||||
* atomic or.
|
||||
*
|
||||
* @ptr address of data A.
|
||||
* @val value of data B.
|
||||
* @return old value of data A.
|
||||
*/
|
||||
int arch_atomic_or(int *ptr, int val);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
22
arch/include/armv7-r/barriers.h
Normal file
22
arch/include/armv7-r/barriers.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* barriers.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARMV7R barriers interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_ARMV7R_BARRIERS_H
|
||||
#define INCLUDE_ARCH_ARMV7R_BARRIERS_H
|
||||
|
||||
#include <compiler.h>
|
||||
|
||||
#define DSB __ASM volatile("dsb" ::: "memory")
|
||||
#define DMB __ASM volatile("dmb" ::: "memory")
|
||||
#define ISB __ASM volatile("isb" ::: "memory")
|
||||
|
||||
#endif
|
||||
113
arch/include/armv7-r/cache.h
Normal file
113
arch/include/armv7-r/cache.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* cache.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM cache interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_CACHE_H
|
||||
#define INCLUDE_ARCH_CACHE_H
|
||||
|
||||
#define ICACHE 1
|
||||
#define DCACHE 2
|
||||
#define UCACHE (ICACHE|DCACHE)
|
||||
|
||||
#define __CACHE_ALIGN __ALIGNED(CONFIG_ARCH_CACHE_LINE)
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <types.h>
|
||||
#include <compiler.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
/*
|
||||
* enable caches.
|
||||
*
|
||||
* @flags cache type.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_enable_cache(uint8_t flags);
|
||||
#else
|
||||
#define arch_enable_cache(flags)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* disable caches.
|
||||
*
|
||||
* @flags cache type.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_disable_cache(uint8_t flags);
|
||||
#else
|
||||
#define arch_disable_cache(flags)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clean dcache.
|
||||
*
|
||||
* @start start address.
|
||||
* @len clean data length.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_clean_cache_range(addr_t start, size_t len);
|
||||
#else
|
||||
#define arch_clean_cache_range(start, len)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clean and invalidate dcache.
|
||||
*
|
||||
* @start start address.
|
||||
* @len clean data length.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_clean_invalidate_cache_range(addr_t start, size_t len);
|
||||
#else
|
||||
#define arch_clean_invalidate_cache_range(start, len)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clean and invalidate dcache all
|
||||
*
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_clean_invalidate_dcache_all(void);
|
||||
#else
|
||||
#define arch_clean_invalidate_dcache_all()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* invalidate dcache.
|
||||
*
|
||||
* @start start address.
|
||||
* @len clean data length.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_invalidate_cache_range(addr_t start, size_t len);
|
||||
#else
|
||||
#define arch_invalidate_cache_range(start, len)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sync dcache.
|
||||
*
|
||||
* @start start address.
|
||||
* @len clean data length.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_CACHE
|
||||
void arch_sync_cache_range(addr_t start, size_t len);
|
||||
#else
|
||||
#define arch_sync_cache_range(start, len)
|
||||
#endif
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
64
arch/include/armv7-r/exceptions.h
Normal file
64
arch/include/armv7-r/exceptions.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* exceptions.h
|
||||
*
|
||||
* Copyright (c) 2021 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARMV7R exceptions interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_ARMV7R_EXCEPTIONS_H
|
||||
#define INCLUDE_ARCH_ARMV7R_EXCEPTIONS_H
|
||||
|
||||
struct arm_iframe {
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
uint32_t fpexc;
|
||||
#endif
|
||||
uint32_t usp;
|
||||
uint32_t ulr;
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r4;
|
||||
uint32_t r12;
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t spsr;
|
||||
};
|
||||
|
||||
struct arm_fault_frame {
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
uint32_t fpexc;
|
||||
#endif
|
||||
uint32_t usp;
|
||||
uint32_t ulr;
|
||||
uint32_t r[13];
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t spsr;
|
||||
};
|
||||
|
||||
struct arm_mode_regs {
|
||||
uint32_t usr_r13, usr_r14;
|
||||
uint32_t fiq_r13, fiq_r14;
|
||||
uint32_t irq_r13, irq_r14;
|
||||
uint32_t svc_r13, svc_r14;
|
||||
uint32_t abt_r13, abt_r14;
|
||||
uint32_t und_r13, und_r14;
|
||||
uint32_t sys_r13, sys_r14;
|
||||
};
|
||||
|
||||
void arm_save_mode_regs(struct arm_mode_regs *regs);
|
||||
void Arm_Undefined_Handler(void);
|
||||
void Arm_Prefetch_Handler(void);
|
||||
void Arm_Abort_Handler(void);
|
||||
void Arm_SWI_Handler(void);
|
||||
void Arm_IRQ_Handler(void);
|
||||
void Arm_FIQ_Handler(void);
|
||||
void arm_reserved(void);
|
||||
|
||||
#endif
|
||||
44
arch/include/armv7-r/fpu.h
Normal file
44
arch/include/armv7-r/fpu.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* fpu.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM fpu interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_FPU_H
|
||||
#define INCLUDE_ARCH_FPU_H
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <compiler.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
/*
|
||||
* fpu enable.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
void arm_fpu_enable(void);
|
||||
#else
|
||||
#define arm_fpu_enable()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fpu disable.
|
||||
*/
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
void arm_fpu_disable(void);
|
||||
#else
|
||||
#define arm_fpu_disable()
|
||||
#endif
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
114
arch/include/armv7-r/irq.h
Normal file
114
arch/include/armv7-r/irq.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* irq.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM irq interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_IRQ_H
|
||||
#define INCLUDE_ARCH_IRQ_H
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <compiler.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
/*
|
||||
* irq state type.
|
||||
*/
|
||||
typedef unsigned int irq_state_t;
|
||||
|
||||
/*
|
||||
* irq enable.
|
||||
*/
|
||||
static inline void arch_irq_enable(void)
|
||||
{
|
||||
CF;
|
||||
__ASM volatile("cpsie i");
|
||||
}
|
||||
|
||||
/*
|
||||
* irq disable.
|
||||
*/
|
||||
static inline void arch_irq_disable(void)
|
||||
{
|
||||
__ASM volatile("cpsid i");
|
||||
CF;
|
||||
}
|
||||
|
||||
/*
|
||||
* irq save.
|
||||
*
|
||||
* @return old irq state.
|
||||
*/
|
||||
static inline irq_state_t arch_irq_save(void)
|
||||
{
|
||||
unsigned int cpsr;
|
||||
|
||||
__ASM volatile
|
||||
(
|
||||
"\tmrs %0, cpsr\n"
|
||||
"\tcpsid i\n"
|
||||
: "=r" (cpsr)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
/*
|
||||
* irq restore.
|
||||
*
|
||||
* @flags old irq state.
|
||||
*/
|
||||
static inline void arch_irq_restore(irq_state_t flags)
|
||||
{
|
||||
__ASM volatile
|
||||
(
|
||||
"msr cpsr_c, %0"
|
||||
:
|
||||
: "r" (flags)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* is irq masked.
|
||||
*
|
||||
* @return masked or not.
|
||||
*/
|
||||
bool arch_irq_is_masked(void);
|
||||
|
||||
/*
|
||||
* is irq mode.
|
||||
*
|
||||
* @return irq mode or not.
|
||||
*/
|
||||
bool arch_in_irq_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Enable vectored interrupt mode.
|
||||
*/
|
||||
void arch_vectored_irq_enable(bool en);
|
||||
|
||||
/**
|
||||
* @brief Whether core is in FIQ mode or not
|
||||
*
|
||||
* @return true FIQ mode
|
||||
* @return false otherwise
|
||||
*/
|
||||
bool arch_in_fiq_mode(void);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
106
arch/include/armv7-r/mpu.h
Normal file
106
arch/include/armv7-r/mpu.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* mpu.h
|
||||
*
|
||||
* Copyright (c) 2019 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R MPU driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
#ifndef INCLUDE_ARCH_ARMV7R_MPU_H
|
||||
#define INCLUDE_ARCH_ARMV7R_MPU_H
|
||||
|
||||
/*
|
||||
* Memory types supported by the MPU driver.
|
||||
*/
|
||||
typedef enum mpu_region_type {
|
||||
/* Strong ordered
|
||||
* - non-bufferable, non-cachable, shareable, RW, XN
|
||||
*/
|
||||
MPU_REGION_STRONGORDERED,
|
||||
|
||||
/* Device memory
|
||||
* - bufferable, non-cachable, shareable, RW, XN
|
||||
*/
|
||||
MPU_REGION_DEVICE,
|
||||
|
||||
/* Normal memory
|
||||
* - bufferable, outer and inner write-back & write allocate,
|
||||
* shareble, RW, non XN
|
||||
*/
|
||||
MPU_REGION_NORMAL,
|
||||
|
||||
/* Normal non-cacheable memory
|
||||
* - bufferable, outer and inner non-cacheable, shareble, RW,
|
||||
* non XN
|
||||
*/
|
||||
MPU_REGION_NORMAL_NONCACHEABLE,
|
||||
|
||||
/* Normal ready-only memory
|
||||
* - bufferable, outer and inner wb, no wa, no shareble, RO,
|
||||
* non XN
|
||||
*/
|
||||
MPU_REGION_NORMAL_RO,
|
||||
|
||||
/* Not accessable.
|
||||
*/
|
||||
MPU_REGION_NO_ACCESS,
|
||||
|
||||
MPU_REGION_MAX,
|
||||
} mpu_region_type_e;
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <compiler.h>
|
||||
#include <stdbool.h>
|
||||
#include <types.h>
|
||||
|
||||
typedef struct mpu_config {
|
||||
addr_t addr;
|
||||
uint64_t size;
|
||||
mpu_region_type_e type;
|
||||
} mpu_config_t;
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
#if CONFIG_ARCH_WITH_MPU
|
||||
void mpu_clear_region(void);
|
||||
#else
|
||||
#define mpu_clear_region()
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARCH_WITH_MPU
|
||||
void mpu_add_region(int region, uint32_t base, uint64_t size,
|
||||
mpu_region_type_e type);
|
||||
#else
|
||||
#define mpu_add_region(region, base, size, type)
|
||||
#endif
|
||||
|
||||
uint32_t mpu_region_index(void);
|
||||
|
||||
#if CONFIG_ARCH_WITH_MPU
|
||||
void mpu_enable(bool enable);
|
||||
#else
|
||||
#define mpu_enable(enable)
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARCH_WITH_MPU
|
||||
bool mpu_is_belong_uncache_region(uint32_t base, uint32_t size);
|
||||
#else
|
||||
#define mpu_is_belong_uncache_region(base, size)
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARCH_WITH_MPU
|
||||
void mpu_region_set_type(uint32_t base, uint64_t size,
|
||||
mpu_region_type_e type);
|
||||
#else
|
||||
#define mpu_region_set_type(base, size, type)
|
||||
#endif
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif
|
||||
206
arch/include/armv7-r/pmu.h
Normal file
206
arch/include/armv7-r/pmu.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* pmu.h
|
||||
*
|
||||
* Copyright (c) 2019 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R Performance Monitor driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_PMU_H
|
||||
#define INCLUDE_ARCH_PMU_H
|
||||
|
||||
#include <types.h>
|
||||
#include <armv7-r/register.h>
|
||||
|
||||
typedef enum pmu_evt_cntr {
|
||||
PMU_EVT_COUNTER1 = 0,
|
||||
PMU_EVT_COUNTER2 = 1,
|
||||
PMU_EVT_COUNTER3 = 2,
|
||||
} pmu_evt_cntr_e;
|
||||
|
||||
typedef enum pmu_evt {
|
||||
PMU_EVT_SOFTWARE_INCREMENT = 0x0,
|
||||
PMU_EVT_ICACHE_MISS = 0x1,
|
||||
PMU_EVT_DCACHE_MISS = 0x3,
|
||||
PMU_EVT_DCACHE_ACCESS = 0x4,
|
||||
PMU_EVT_DATA_READ = 0x6,
|
||||
PMU_EVT_DATA_WRITE = 0x7,
|
||||
PMU_EVT_INSTRUCTION_EXECUTED = 0x8,
|
||||
PMU_EVT_DUAL_ISSUED_INSTUCTIONS = 0x5e,
|
||||
PMU_EVT_EXECPTION_TAKEN = 0x9,
|
||||
PMU_EVT_EXECPTION_RETURN = 0xa,
|
||||
PMU_EVT_CHANGE_CONTEXT_ID = 0xb,
|
||||
PMU_EVT_SW_CHANGE_PC = 0xc,
|
||||
PMU_EVT_BRANCH_IMMEDIATE = 0xd,
|
||||
PMU_EVT_PROCEDURE_RETURN = 0xe,
|
||||
PMU_EVT_UNALIGNED_ACCESS = 0xf,
|
||||
PMU_EVT_BRANCH_NOT_PREDICTED = 0x10,
|
||||
PMU_EVT_CYCLE_CNT = 0x11,
|
||||
PMU_EVT_BRANCH_PREDICTED = 0x12,
|
||||
PMU_EVT_STALL_INSTRUCTION = 0x40,
|
||||
PMU_EVT_STALL_DATA_DEPENDENCY = 0x41,
|
||||
PMU_EVT_DCACHE_WRITE_BACK = 0x42,
|
||||
PMU_EVT_EXT_MEMORY_REQ = 0x43,
|
||||
PMU_EVT_STALL_LSU_BUSY = 0x44,
|
||||
PMU_EVT_DRAIN_STORE_BUFFER = 0x45,
|
||||
PMU_EVT_FIQ_DISABLE_CYCLES = 0x46,
|
||||
PMU_EVT_IRQ_DISABLE_CYCLES = 0x47,
|
||||
PMU_EVT_ETMEXTOUTM0 = 0x48,
|
||||
PMU_EVT_ETMEXTOUTM1 = 0x49,
|
||||
PMU_EVT_ICACHE_TAG_ECCERR = 0x4a,
|
||||
PMU_EVT_ICACHE_DATA_ECCERR = 0x4b,
|
||||
PMU_EVT_DCACHE_TAG_ECCERR = 0x4c,
|
||||
PMU_EVT_DCACHE_DATA_ECCERR = 0x4d,
|
||||
PMU_EVT_TCM_ECCERR_PFU = 0x4e,
|
||||
PMU_EVT_TCM_ECCERR_LSU = 0x4f,
|
||||
PMU_EVT_STORE_BUFFER_MERGE = 0x50,
|
||||
PMU_EVT_LSU_STALL_BY_STORE_BUFFER = 0x51,
|
||||
PMU_EVT_LSU_STALL_BY_STORE_QUEUE = 0x52,
|
||||
PMU_EVT_INT_DIV = 0x53,
|
||||
PMU_EVT_STALL_CYCLE_BY_INT_DIV = 0x54,
|
||||
PMU_EVT_PLD_LINEFILL = 0x55,
|
||||
PMU_EVT_PLD_NO_LINEFILL = 0x56,
|
||||
PMU_EVT_NON_CACHEABLE_AXI_ACCESS = 0x57,
|
||||
PMU_EVT_ICACHE_ACCESS = 0x58,
|
||||
PMU_EVT_STORE_BUFFER_SLOT_ATTR_CONFLICT = 0x59,
|
||||
PMU_EVT_DUAL_ISSUE_CASE_A = 0x5a,
|
||||
PMU_EVT_DUAL_ISSUE_CASE_B1_B2_F2_F2D = 0x5b,
|
||||
PMU_EVT_DUAL_ISSUE_CASE_OTHER = 0x5c,
|
||||
PMU_EVT_DOUBLE_PRECISION_FLOAT_EXEC = 0x5d,
|
||||
PMU_EVT_DCACHE_DATA_FATAL_ECCERR = 0x60,
|
||||
PMU_EVT_DCACHE_TAG_FATAL_ECCERR = 0x61,
|
||||
PMU_EVT_PROCESSOR_LIVELOCK = 0x62,
|
||||
PMU_EVT_ATCM_MB_ECCERR = 0x64,
|
||||
PMU_EVT_B0TCM_MB_ECCERR = 0x65,
|
||||
PMU_EVT_B1TCM_MB_ECCERR = 0x66,
|
||||
PMU_EVT_ATCM_SB_ECCERR = 0x67,
|
||||
PMU_EVT_B0TCM_SB_ECCERR = 0x68,
|
||||
PMU_EVT_B1TCM_SB_ECCERR = 0x69,
|
||||
PMU_EVT_TCM_CORRECTABLE_ECCERR_LSU = 0x6a,
|
||||
PMU_EVT_TCM_CORRECTABLE_ECCERR_PFU = 0x6b,
|
||||
PMU_EVT_TCM_FATAL_ECCERR_AXI_SLAVE = 0x6c,
|
||||
PMU_EVT_TCM_CORRECTABLE_ECCERR_AXI_SLAVE = 0x6d,
|
||||
PMU_EVT_CORRECTABLE_EVENTS = 0x6e,
|
||||
PMU_EVT_FATAL_EVENTS = 0x6f,
|
||||
PMU_EVT_CORRECTABLE_BUS_FAULTS = 0x70,
|
||||
PMU_EVT_FATAL_BUS_FAULTS = 0x71,
|
||||
PMU_EVT_ACP_DCACHE_ACCESS = 0x72,
|
||||
PMU_EVT_ACP_DCACHE_INVALIDATE = 0x73,
|
||||
} pmu_evt_e;
|
||||
|
||||
#define PMCR_E (1 << 0) /* pmu enable */
|
||||
#define PMCR_P (1 << 1) /* event counter reset */
|
||||
#define PMCR_C (1 << 2) /* cycle counter reset */
|
||||
#define PMCR_D (1 << 3) /* count every 64 clock cycles */
|
||||
|
||||
#if CONFIG_ARM_WITH_PMU
|
||||
|
||||
/* Enable the PMU. All counters are cleared. */
|
||||
static inline void pmu_enable(void)
|
||||
{
|
||||
uint32_t val = arm_read_pmcr();
|
||||
val |= PMCR_P | PMCR_C | PMCR_E;
|
||||
arm_write_pmcr(val);
|
||||
}
|
||||
|
||||
/* Diable the PMU. All counters are cleared. */
|
||||
static inline void pmu_disable(void)
|
||||
{
|
||||
uint32_t val = arm_read_pmcr();
|
||||
val &= ~(PMCR_P | PMCR_C | PMCR_E);
|
||||
arm_write_pmcr(val);
|
||||
}
|
||||
|
||||
/* Get cycle counter enable status */
|
||||
static inline bool pmu_cycle_cntr_status(void)
|
||||
{
|
||||
uint32_t val = arm_read_pmcntenset();
|
||||
|
||||
return !!(val & (1U << 31));
|
||||
}
|
||||
|
||||
/* Start cycle counter. Set div64 = true to count every
|
||||
* 64 clock cycles.
|
||||
*/
|
||||
static inline void pmu_start_cycle_cntr(bool div64)
|
||||
{
|
||||
uint32_t val = arm_read_pmcr();
|
||||
|
||||
if (div64)
|
||||
val |= PMCR_D;
|
||||
else
|
||||
val &= ~PMCR_D;
|
||||
|
||||
arm_write_pmcr(val);
|
||||
arm_write_pmcntenset(1U << 31);
|
||||
}
|
||||
|
||||
/* Stop cycle counter. */
|
||||
static inline void pmu_stop_cycle_cntr(void)
|
||||
{
|
||||
arm_write_pmcntenclr(1U << 31);
|
||||
}
|
||||
|
||||
/* Stop and clear the cycle counter. */
|
||||
static inline void pmu_stop_clear_cycle_cntr(void)
|
||||
{
|
||||
pmu_stop_cycle_cntr();
|
||||
arm_write_pmccntr(0);
|
||||
}
|
||||
|
||||
/* Get cycle counter value. */
|
||||
static inline uint32_t pmu_get_cycle_cntr(void)
|
||||
{
|
||||
return arm_read_pmccntr();
|
||||
}
|
||||
|
||||
/* Bind event counter to specific event and start it. */
|
||||
static inline void pmu_start_evt_cntr(pmu_evt_cntr_e cntr,
|
||||
pmu_evt_e evt)
|
||||
{
|
||||
arm_write_pmselr(cntr);
|
||||
arm_write_pmxevtyper(evt);
|
||||
arm_write_pmcntenset(1 << cntr);
|
||||
}
|
||||
|
||||
/* Stop event counter without clearing. */
|
||||
static inline void pmu_stop_evt_cntr(pmu_evt_cntr_e cntr)
|
||||
{
|
||||
arm_write_pmcntenclr(1 << cntr);
|
||||
}
|
||||
|
||||
/* Stop and clear the event counter. */
|
||||
static inline void pmu_stop_clear_evt_cntr(pmu_evt_cntr_e cntr)
|
||||
{
|
||||
pmu_stop_evt_cntr(cntr);
|
||||
arm_write_pmselr(cntr);
|
||||
arm_write_pmxevcntr(0);
|
||||
}
|
||||
|
||||
/* Get event counter value. */
|
||||
static inline uint32_t pmu_get_evt_cntr(pmu_evt_cntr_e cntr)
|
||||
{
|
||||
arm_write_pmselr(cntr);
|
||||
return arm_read_pmxevcntr();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define pmu_enable()
|
||||
#define pmu_disable()
|
||||
#define pmu_start_cycle_cntr(div64)
|
||||
#define pmu_stop_cycle_cntr()
|
||||
#define pmu_stop_clear_cycle_cntr()
|
||||
#define pmu_get_cycle_cntr()
|
||||
#define pmu_start_evt_cntr()
|
||||
#define pmu_stop_evt_cntr()
|
||||
#define pmu_stop_clear_evt_cntr()
|
||||
#define pmu_get_evt_cntr()
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_ARM_PMU_H */
|
||||
269
arch/include/armv7-r/register.h
Normal file
269
arch/include/armv7-r/register.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* register.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM cp register interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARCH_REGISTER_H
|
||||
#define INCLUDE_ARCH_REGISTER_H
|
||||
|
||||
#define REG_R0 (0)
|
||||
#define REG_R1 (1)
|
||||
#define REG_R2 (2)
|
||||
#define REG_R3 (3)
|
||||
#define REG_R4 (4)
|
||||
#define REG_R5 (5)
|
||||
#define REG_R6 (6)
|
||||
#define REG_R7 (7)
|
||||
#define REG_R8 (8)
|
||||
#define REG_R9 (9)
|
||||
#define REG_R10 (10)
|
||||
#define REG_R11 (11)
|
||||
#define REG_R12 (12)
|
||||
#define REG_R13 (13)
|
||||
#define REG_R14 (14)
|
||||
#define REG_R15 (15)
|
||||
#define REG_CPSR (16)
|
||||
|
||||
#define ARM_CONTEXT_REGS (17)
|
||||
|
||||
/* If the MCU supports a floating point unit, then it will be necessary
|
||||
* to save the state of the FPU status register and data registers on
|
||||
* each context switch. These registers are not saved during interrupt
|
||||
* level processing, however. So, as a consequence, floating point
|
||||
* operations may NOT be performed in interrupt handlers.
|
||||
*
|
||||
* The FPU provides an extension register file containing 32 single-
|
||||
* precision registers. These can be viewed as:
|
||||
*
|
||||
* - Sixteen 64-bit double word registers, D0-D15
|
||||
* - Thirty-two 32-bit single-word registers, S0-S31
|
||||
* S<2n> maps to the least significant half of D<n>
|
||||
* S<2n+1> maps to the most significant half of D<n>.
|
||||
*/
|
||||
|
||||
#if CONFIG_ARCH_WITH_FPU
|
||||
# define REG_D0 (ARM_CONTEXT_REGS+0) /* D0 */
|
||||
# define REG_S0 (ARM_CONTEXT_REGS+0) /* S0 */
|
||||
# define REG_S1 (ARM_CONTEXT_REGS+1) /* S1 */
|
||||
# define REG_D1 (ARM_CONTEXT_REGS+2) /* D1 */
|
||||
# define REG_S2 (ARM_CONTEXT_REGS+2) /* S2 */
|
||||
# define REG_S3 (ARM_CONTEXT_REGS+3) /* S3 */
|
||||
# define REG_D2 (ARM_CONTEXT_REGS+4) /* D2 */
|
||||
# define REG_S4 (ARM_CONTEXT_REGS+4) /* S4 */
|
||||
# define REG_S5 (ARM_CONTEXT_REGS+5) /* S5 */
|
||||
# define REG_D3 (ARM_CONTEXT_REGS+6) /* D3 */
|
||||
# define REG_S6 (ARM_CONTEXT_REGS+6) /* S6 */
|
||||
# define REG_S7 (ARM_CONTEXT_REGS+7) /* S7 */
|
||||
# define REG_D4 (ARM_CONTEXT_REGS+8) /* D4 */
|
||||
# define REG_S8 (ARM_CONTEXT_REGS+8) /* S8 */
|
||||
# define REG_S9 (ARM_CONTEXT_REGS+9) /* S9 */
|
||||
# define REG_D5 (ARM_CONTEXT_REGS+10) /* D5 */
|
||||
# define REG_S10 (ARM_CONTEXT_REGS+10) /* S10 */
|
||||
# define REG_S11 (ARM_CONTEXT_REGS+11) /* S11 */
|
||||
# define REG_D6 (ARM_CONTEXT_REGS+12) /* D6 */
|
||||
# define REG_S12 (ARM_CONTEXT_REGS+12) /* S12 */
|
||||
# define REG_S13 (ARM_CONTEXT_REGS+13) /* S13 */
|
||||
# define REG_D7 (ARM_CONTEXT_REGS+14) /* D7 */
|
||||
# define REG_S14 (ARM_CONTEXT_REGS+14) /* S14 */
|
||||
# define REG_S15 (ARM_CONTEXT_REGS+15) /* S15 */
|
||||
# define REG_D8 (ARM_CONTEXT_REGS+16) /* D8 */
|
||||
# define REG_S16 (ARM_CONTEXT_REGS+16) /* S16 */
|
||||
# define REG_S17 (ARM_CONTEXT_REGS+17) /* S17 */
|
||||
# define REG_D9 (ARM_CONTEXT_REGS+18) /* D9 */
|
||||
# define REG_S18 (ARM_CONTEXT_REGS+18) /* S18 */
|
||||
# define REG_S19 (ARM_CONTEXT_REGS+19) /* S19 */
|
||||
# define REG_D10 (ARM_CONTEXT_REGS+20) /* D10 */
|
||||
# define REG_S20 (ARM_CONTEXT_REGS+20) /* S20 */
|
||||
# define REG_S21 (ARM_CONTEXT_REGS+21) /* S21 */
|
||||
# define REG_D11 (ARM_CONTEXT_REGS+22) /* D11 */
|
||||
# define REG_S22 (ARM_CONTEXT_REGS+22) /* S22 */
|
||||
# define REG_S23 (ARM_CONTEXT_REGS+23) /* S23 */
|
||||
# define REG_D12 (ARM_CONTEXT_REGS+24) /* D12 */
|
||||
# define REG_S24 (ARM_CONTEXT_REGS+24) /* S24 */
|
||||
# define REG_S25 (ARM_CONTEXT_REGS+25) /* S25 */
|
||||
# define REG_D13 (ARM_CONTEXT_REGS+26) /* D13 */
|
||||
# define REG_S26 (ARM_CONTEXT_REGS+26) /* S26 */
|
||||
# define REG_S27 (ARM_CONTEXT_REGS+27) /* S27 */
|
||||
# define REG_D14 (ARM_CONTEXT_REGS+28) /* D14 */
|
||||
# define REG_S28 (ARM_CONTEXT_REGS+28) /* S28 */
|
||||
# define REG_S29 (ARM_CONTEXT_REGS+29) /* S29 */
|
||||
# define REG_D15 (ARM_CONTEXT_REGS+30) /* D15 */
|
||||
# define REG_S30 (ARM_CONTEXT_REGS+30) /* S30 */
|
||||
# define REG_S31 (ARM_CONTEXT_REGS+31) /* S31 */
|
||||
# define REG_FPSCR (ARM_CONTEXT_REGS+32) /* Floating point status and control */
|
||||
# define FPU_CONTEXT_REGS (33)
|
||||
#else
|
||||
# define FPU_CONTEXT_REGS (0)
|
||||
#endif
|
||||
|
||||
/* The total number of registers saved by software */
|
||||
|
||||
#define XCPTCONTEXT_REGS (ARM_CONTEXT_REGS + FPU_CONTEXT_REGS)
|
||||
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <types.h>
|
||||
#include <compiler.h>
|
||||
#include <armv7-r/barriers.h>
|
||||
|
||||
static inline uint32_t read_cpsr(void)
|
||||
{
|
||||
uint32_t cpsr;
|
||||
__ASM volatile("mrs %0, cpsr" : "=r" (cpsr));
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
#define ARM_CP_REG_FUNCS(cp, reg, op1, c1, c2, op2) \
|
||||
static inline uint32_t arm_read_##reg(void) { \
|
||||
uint32_t val; \
|
||||
__ASM volatile("mrc " #cp ", " #op1 ", %0, " #c1 "," #c2 "," #op2 : "=r" (val)); \
|
||||
return val; \
|
||||
} \
|
||||
\
|
||||
static inline void arm_write_##reg(uint32_t val) { \
|
||||
__ASM volatile("mcr " #cp ", " #op1 ", %0, " #c1 "," #c2 "," #op2 :: "r" (val)); \
|
||||
ISB; \
|
||||
}
|
||||
|
||||
#define ARM_CP15_REG_FUNCS(reg, op1, c1, c2, op2) \
|
||||
ARM_CP_REG_FUNCS(p15, reg, op1, c1, c2, op2)
|
||||
|
||||
#define ARM_CP14_REG_FUNCS(reg, op1, c1, c2, op2) \
|
||||
ARM_CP_REG_FUNCS(p14, reg, op1, c1, c2, op2)
|
||||
|
||||
#define ARM_CP10_REG_FUNCS(reg, op1, c1, c2, op2) \
|
||||
ARM_CP_REG_FUNCS(p10, reg, op1, c1, c2, op2)
|
||||
|
||||
ARM_CP15_REG_FUNCS(sctlr, 0, c1, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(actlr, 0, c1, c0, 1);
|
||||
ARM_CP15_REG_FUNCS(cpacr, 0, c1, c0, 2);
|
||||
|
||||
ARM_CP15_REG_FUNCS(ttbr, 0, c2, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(ttbr0, 0, c2, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(ttbr1, 0, c2, c0, 1);
|
||||
ARM_CP15_REG_FUNCS(ttbcr, 0, c2, c0, 2);
|
||||
ARM_CP15_REG_FUNCS(dacr, 0, c3, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(dfsr, 0, c5, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(ifsr, 0, c5, c0, 1);
|
||||
ARM_CP15_REG_FUNCS(dfar, 0, c6, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(wfar, 0, c6, c0, 1);
|
||||
ARM_CP15_REG_FUNCS(ifar, 0, c6, c0, 2);
|
||||
|
||||
ARM_CP15_REG_FUNCS(fcseidr, 0, c13, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(contextidr, 0, c13, c0, 1);
|
||||
ARM_CP15_REG_FUNCS(tpidrurw, 0, c13, c0, 2);
|
||||
ARM_CP15_REG_FUNCS(tpidruro, 0, c13, c0, 3);
|
||||
ARM_CP15_REG_FUNCS(tpidrprw, 0, c13, c0, 4);
|
||||
|
||||
ARM_CP15_REG_FUNCS(midr, 0, c0, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(mpidr, 0, c0, c0, 5);
|
||||
ARM_CP15_REG_FUNCS(vbar, 0, c12, c0, 0);
|
||||
ARM_CP15_REG_FUNCS(cbar, 4, c15, c0, 0);
|
||||
|
||||
ARM_CP15_REG_FUNCS(ats1cpr, 0, c7, c8, 0);
|
||||
ARM_CP15_REG_FUNCS(ats1cpw, 0, c7, c8, 1);
|
||||
ARM_CP15_REG_FUNCS(ats1cur, 0, c7, c8, 2);
|
||||
ARM_CP15_REG_FUNCS(ats1cuw, 0, c7, c8, 3);
|
||||
ARM_CP15_REG_FUNCS(ats12nsopr, 0, c7, c8, 4);
|
||||
ARM_CP15_REG_FUNCS(ats12nsopw, 0, c7, c8, 5);
|
||||
ARM_CP15_REG_FUNCS(ats12nsour, 0, c7, c8, 6);
|
||||
ARM_CP15_REG_FUNCS(ats12nsouw, 0, c7, c8, 7);
|
||||
ARM_CP15_REG_FUNCS(par, 0, c7, c4, 0);
|
||||
|
||||
/* Branch predictor invalidate */
|
||||
ARM_CP15_REG_FUNCS(bpiall, 0, c7, c5, 6);
|
||||
ARM_CP15_REG_FUNCS(bpimva, 0, c7, c5, 7);
|
||||
ARM_CP15_REG_FUNCS(bpiallis, 0, c7, c1, 6);
|
||||
|
||||
/* tlb registers */
|
||||
ARM_CP15_REG_FUNCS(tlbiallis, 0, c8, c3, 0);
|
||||
ARM_CP15_REG_FUNCS(tlbimvais, 0, c8, c3, 1);
|
||||
ARM_CP15_REG_FUNCS(tlbiasidis, 0, c8, c3, 2);
|
||||
ARM_CP15_REG_FUNCS(tlbimvaais, 0, c8, c3, 3);
|
||||
ARM_CP15_REG_FUNCS(itlbiall, 0, c8, c5, 0);
|
||||
ARM_CP15_REG_FUNCS(itlbimva, 0, c8, c5, 1);
|
||||
ARM_CP15_REG_FUNCS(itlbiasid, 0, c8, c5, 2);
|
||||
ARM_CP15_REG_FUNCS(dtlbiall, 0, c8, c6, 0);
|
||||
ARM_CP15_REG_FUNCS(dtlbimva, 0, c8, c6, 1);
|
||||
ARM_CP15_REG_FUNCS(dtlbiasid, 0, c8, c6, 2);
|
||||
ARM_CP15_REG_FUNCS(tlbiall, 0, c8, c7, 0);
|
||||
ARM_CP15_REG_FUNCS(tlbimva, 0, c8, c7, 1);
|
||||
ARM_CP15_REG_FUNCS(tlbiasid, 0, c8, c7, 2);
|
||||
ARM_CP15_REG_FUNCS(tlbimvaa, 0, c8, c7, 3);
|
||||
|
||||
ARM_CP15_REG_FUNCS(l2ctlr, 1, c9, c0, 2);
|
||||
ARM_CP15_REG_FUNCS(l2ectlr, 1, c9, c0, 3);
|
||||
|
||||
/* mpu registers (using unified memory regions) */
|
||||
ARM_CP15_REG_FUNCS(mpuir, 0, c0, c0, 4);
|
||||
ARM_CP15_REG_FUNCS(rbar, 0, c6, c1, 0);
|
||||
ARM_CP15_REG_FUNCS(rsr, 0, c6, c1, 2);
|
||||
ARM_CP15_REG_FUNCS(racr, 0, c6, c1, 4);
|
||||
ARM_CP15_REG_FUNCS(rgnr, 0, c6, c2, 0);
|
||||
|
||||
/* performance monitor registers */
|
||||
ARM_CP15_REG_FUNCS(pmcr, 0, c9, c12, 0);
|
||||
ARM_CP15_REG_FUNCS(pmcntenset, 0, c9, c12, 1);
|
||||
ARM_CP15_REG_FUNCS(pmcntenclr, 0, c9, c12, 2);
|
||||
ARM_CP15_REG_FUNCS(pmovsr, 0, c9, c12, 3);
|
||||
ARM_CP15_REG_FUNCS(pmswinc, 0, c9, c12, 4);
|
||||
ARM_CP15_REG_FUNCS(pmselr, 0, c9, c12, 5);
|
||||
ARM_CP15_REG_FUNCS(pmccntr, 0, c9, c13, 0);
|
||||
ARM_CP15_REG_FUNCS(pmxevtyper, 0, c9, c13, 1);
|
||||
ARM_CP15_REG_FUNCS(pmxevcntr, 0, c9, c13, 2);
|
||||
|
||||
/* TCM registers */
|
||||
ARM_CP15_REG_FUNCS(tcmtr, 0, c0, c0, 2);
|
||||
ARM_CP15_REG_FUNCS(btcmrgn, 0, c9, c1, 0);
|
||||
ARM_CP15_REG_FUNCS(atcmrgn, 0, c9, c1, 1);
|
||||
|
||||
/* debug registers */
|
||||
ARM_CP14_REG_FUNCS(dbddidr, 0, c0, c0, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdrar, 0, c1, c0, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdsar, 0, c2, c0, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdscr, 0, c0, c1, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdtrtxint, 0, c0, c5, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdtrrxint, 0, c0, c5, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgwfar, 0, c0, c6, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgvcr, 0, c0, c7, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgecr, 0, c0, c9, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdsccr, 0, c0, c10, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdsmcr, 0, c0, c11, 0);
|
||||
ARM_CP14_REG_FUNCS(dbgdtrrxext, 0, c0, c0, 2);
|
||||
ARM_CP14_REG_FUNCS(dbgdscrext, 0, c0, c2, 2);
|
||||
ARM_CP14_REG_FUNCS(dbgdtrtxext, 0, c0, c3, 2);
|
||||
ARM_CP14_REG_FUNCS(dbgdrcr, 0, c0, c4, 2);
|
||||
ARM_CP14_REG_FUNCS(dbgvr0, 0, c0, c0, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgvr1, 0, c0, c1, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgvr2, 0, c0, c2, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgbcr0, 0, c0, c0, 5);
|
||||
ARM_CP14_REG_FUNCS(dbgbcr1, 0, c0, c1, 5);
|
||||
ARM_CP14_REG_FUNCS(dbgbcr2, 0, c0, c2, 5);
|
||||
ARM_CP14_REG_FUNCS(dbgwvr0, 0, c0, c0, 6);
|
||||
ARM_CP14_REG_FUNCS(dbgwvr1, 0, c0, c1, 6);
|
||||
ARM_CP14_REG_FUNCS(dbgwcr0, 0, c0, c0, 7);
|
||||
ARM_CP14_REG_FUNCS(dbgwcr1, 0, c0, c1, 7);
|
||||
ARM_CP14_REG_FUNCS(dbgoslar, 0, c1, c0, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgoslsr, 0, c1, c1, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgossrr, 0, c1, c2, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgprcr, 0, c1, c4, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgprsr, 0, c1, c5, 4);
|
||||
ARM_CP14_REG_FUNCS(dbgclaimset, 0, c7, c8, 6);
|
||||
ARM_CP14_REG_FUNCS(dbgclaimclr, 0, c7, c9, 6);
|
||||
ARM_CP14_REG_FUNCS(dbgauthstatus, 0, c7, c14, 6);
|
||||
ARM_CP14_REG_FUNCS(dbgdevid, 0, c7, c2, 7);
|
||||
|
||||
/* fpu registers */
|
||||
ARM_CP10_REG_FUNCS(fpexc, 7, c8, c0, 0);
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#endif /* INCLUDE_ARCH_REGISTER_H */
|
||||
118
arch/include/armv7-r/spinlock.h
Normal file
118
arch/include/armv7-r/spinlock.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* spinlock.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: ARM spinlock interface.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_ARM_SPINLOCK_H
|
||||
#define INCLUDE_ARM_SPINLOCK_H
|
||||
|
||||
#include <armv7-r/barriers.h>
|
||||
|
||||
#define SPIN_LOCK_INITIAL_VALUE (0)
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
/* spin lock type */
|
||||
typedef unsigned long spin_lock_t;
|
||||
|
||||
#ifdef CONFIG_MULTI_CORE_SMP
|
||||
#else
|
||||
static inline int __arch_spin_lock_testset(spin_lock_t *spinlock, int value)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
__ASM volatile
|
||||
(
|
||||
"1:\n"
|
||||
"\tldrex %0, [%1]\n"
|
||||
"\tcmp %0, %2\n"
|
||||
"\tbeq 2f\n"
|
||||
"\tstrex %0, %2, [%1]\n"
|
||||
"\tcmp %0, %2\n"
|
||||
"\tbeq 1b\n"
|
||||
"\tdmb ish\n"
|
||||
"2:\n"
|
||||
: "=&r" (result)
|
||||
: "r" (spinlock), "r" (value)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* arch spinlock init.
|
||||
*
|
||||
* @spinlock spinlock address.
|
||||
*/
|
||||
#ifdef CONFIG_MULTI_CORE_SMP
|
||||
void arch_spin_lock_init(spin_lock_t *spinlock);
|
||||
#else
|
||||
static inline void arch_spin_lock_init(spin_lock_t *spinlock)
|
||||
{
|
||||
*spinlock = SPIN_LOCK_INITIAL_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* arch spin lock.
|
||||
*
|
||||
* @spinlock spinlock address.
|
||||
*/
|
||||
#ifdef CONFIG_MULTI_CORE_SMP
|
||||
void arch_spin_lock(spin_lock_t *spinlock);
|
||||
#else
|
||||
static inline void arch_spin_lock(spin_lock_t *spinlock)
|
||||
{
|
||||
/* spin until lock is acquired */
|
||||
while (__arch_spin_lock_testset(spinlock, 1)) {
|
||||
DSB;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* arch spin trylock.
|
||||
*
|
||||
* @spinlock spinlock address.
|
||||
*/
|
||||
#ifdef CONFIG_MULTI_CORE_SMP
|
||||
int arch_spin_trylock(spin_lock_t *spinlock);
|
||||
#else
|
||||
static inline int arch_spin_trylock(spin_lock_t *spinlock)
|
||||
{
|
||||
return __arch_spin_lock_testset(spinlock, 1) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* arch spin unlock.
|
||||
*
|
||||
* @spinlock spinlock address.
|
||||
*/
|
||||
#ifdef CONFIG_MULTI_CORE_SMP
|
||||
void arch_spin_unlock(spin_lock_t *spinlock);
|
||||
#else
|
||||
static inline void arch_spin_unlock(spin_lock_t *spinlock)
|
||||
{
|
||||
DMB;
|
||||
*spinlock = 0;
|
||||
DSB;
|
||||
}
|
||||
#endif
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
39
arch/include/armv7-r/svcall.h
Normal file
39
arch/include/armv7-r/svcall.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* svcall.h
|
||||
*
|
||||
* Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: SV call header file.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef ARM_V7R_SVCALL_H_
|
||||
#define ARM_V7R_SVCALL_H_
|
||||
|
||||
/* Cortex-R system calls ************************************************************/
|
||||
|
||||
/* SYS call 0:
|
||||
*
|
||||
* int arm_saveusercontext(uint32_t *saveregs);
|
||||
*/
|
||||
|
||||
#define SYS_save_context (0)
|
||||
|
||||
/* SYS call 1:
|
||||
*
|
||||
* void arm_fullcontextrestore(uint32_t *restoreregs) noreturn_function;
|
||||
*/
|
||||
|
||||
#define SYS_restore_context (1)
|
||||
|
||||
/* SYS call 2:
|
||||
*
|
||||
* void arm_switchcontext(void);
|
||||
*/
|
||||
|
||||
#define SYS_switch_context (2)
|
||||
|
||||
#endif /* ARM_V7R_SVCALL_H_ */
|
||||
55
arch/include/armv7-r/tcm.h
Normal file
55
arch/include/armv7-r/tcm.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* tcm.h
|
||||
*
|
||||
* Copyright (c) 2019 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: Cortex V7R TCM driver.
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
#ifndef INCLUDE_ARCH_ARMV7R_TCM_H
|
||||
#define INCLUDE_ARCH_ARMV7R_TCM_H
|
||||
|
||||
#define ATCMPCEN (1ul << 25)
|
||||
#define B0TCMPCEN (1ul << 26)
|
||||
#define B1TCMPCEN (1ul << 27)
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <types.h>
|
||||
#include <compiler.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
/*
|
||||
* tcma enable.
|
||||
*
|
||||
* @atcm_base tcma base address.
|
||||
* @enable_ecc enable tcm ecc.
|
||||
*/
|
||||
#if CONFIG_ARM_WITH_TCM
|
||||
void tcma_enable(uint32_t tcm_base, bool enable_ecc);
|
||||
#else
|
||||
#define tcma_enable(tcm_base, enable_ecc)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* tcmb enable.
|
||||
*
|
||||
* @atcm_base tcmb base address.
|
||||
* @enable_ecc enable tcm ecc.
|
||||
*/
|
||||
#if CONFIG_ARM_WITH_TCM
|
||||
void tcmb_enable(uint32_t tcm_base, bool enable_ecc);
|
||||
#else
|
||||
#define tcmb_enable(tcm_base, enable_ecc)
|
||||
#endif
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user