SAMA5D4: Add support for secure/FIQ interrupts; SAIC supports need to be be enabled unconditionally

This commit is contained in:
Gregory Nutt 2014-06-20 18:16:41 -06:00
parent 9542994616
commit 3f6b1642ca
6 changed files with 128 additions and 19 deletions

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/include/armv7-a/irq.h * arch/arm/include/armv7-a/irq.h
* *
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -277,6 +277,9 @@ static inline irqstate_t irqsave(void)
( (
"\tmrs %0, cpsr\n" "\tmrs %0, cpsr\n"
"\tcpsid i\n" "\tcpsid i\n"
#if defined(CONFIG_ARMV7A_DECODEFIQ)
"\tcpsid f\n"
#endif
: "=r" (cpsr) : "=r" (cpsr)
: :
: "memory" : "memory"
@ -295,6 +298,9 @@ static inline irqstate_t irqenable(void)
( (
"\tmrs %0, cpsr\n" "\tmrs %0, cpsr\n"
"\tcpsie i\n" "\tcpsie i\n"
#if defined(CONFIG_ARMV7A_DECODEFIQ)
"\tcpsie f\n"
#endif
: "=r" (cpsr) : "=r" (cpsr)
: :
: "memory" : "memory"

View File

@ -73,7 +73,8 @@
#ifdef __cplusplus #ifdef __cplusplus
#define EXTERN extern "C" #define EXTERN extern "C"
extern "C" { extern "C"
{
#else #else
#define EXTERN extern #define EXTERN extern
#endif #endif

View File

@ -63,6 +63,11 @@ g_undeftmp:
g_aborttmp: g_aborttmp:
.word 0 /* Saved lr */ .word 0 /* Saved lr */
.word 0 /* Saved spsr */ .word 0 /* Saved spsr */
#ifdef CONFIG_ARMV7A_DECODEFIQ
g_fiqtmp:
.word 0 /* Saved lr */
.word 0 /* Saved spsr */
#endif
/************************************************************************************ /************************************************************************************
* Assembly Macros * Assembly Macros
@ -86,6 +91,7 @@ g_aborttmp:
* *
************************************************************************************/ ************************************************************************************/
.globl arm_decodeirq
.globl arm_vectorirq .globl arm_vectorirq
.type arm_vectorirq, %function .type arm_vectorirq, %function
@ -153,7 +159,6 @@ arm_vectorirq:
/* Restore the CPSR, SVC mode registers and return */ /* Restore the CPSR, SVC mode registers and return */
.Lnoirqset:
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr, r1 msr spsr, r1
ldmia r0, {r0-r15}^ /* Return */ ldmia r0, {r0-r15}^ /* Return */
@ -175,6 +180,7 @@ arm_vectorirq:
* *
************************************************************************************/ ************************************************************************************/
.globl arm_syscall
.globl arm_vectorsvc .globl arm_vectorsvc
.type arm_vectorsvc, %function .type arm_vectorsvc, %function
@ -235,6 +241,7 @@ arm_vectorsvc:
* *
************************************************************************************/ ************************************************************************************/
.globl arm_dataabort
.globl arm_vectordata .globl arm_vectordata
.type arm_vectordata, %function .type arm_vectordata, %function
@ -317,6 +324,7 @@ arm_vectordata:
* *
************************************************************************************/ ************************************************************************************/
.globl arm_prefetchabort
.globl arm_vectorprefetch .globl arm_vectorprefetch
.type arm_vectorprefetch, %function .type arm_vectorprefetch, %function
@ -397,6 +405,7 @@ arm_vectorprefetch:
* *
************************************************************************************/ ************************************************************************************/
.globl arm_undefinedinsn
.globl arm_vectorundefinsn .globl arm_vectorundefinsn
.type arm_vectorundefinsn, %function .type arm_vectorundefinsn, %function
@ -474,12 +483,86 @@ arm_vectorundefinsn:
* *
************************************************************************************/ ************************************************************************************/
#ifdef CONFIG_ARMV7A_DECODEFIQ
.globl arm_decodefiq
#endif
.globl arm_vectorfiq .globl arm_vectorfiq
.type arm_vectorfiq, %function .type arm_vectorfiq, %function
arm_vectorfiq: arm_vectorfiq:
#ifdef CONFIG_ARMV7A_DECODEFIQ #ifdef CONFIG_ARMV7A_DECODEFIQ
# error Missing logic /* On entry we are free to use the FIQ mode registers r8 through r14 */
ldr r13, .Lfiqtmp /* Points to temp storage */
sub lr, lr, #4 /* Fixup return */
str lr, [r13] /* Save in temp storage */
mrs lr, spsr /* Get SPSR_fiq */
str lr, [r13, #4] /* Save in temp storage */
/* Then switch back to SVC mode */
bic lr, lr, #PSR_MODE_MASK /* Keep F and T bits */
orr lr, lr, #(PSR_MODE_SVC | PSR_I_BIT)
msr cpsr_c, lr /* Switch to SVC mode */
/* Create a context structure. First set aside a stack frame
* and store r0-r12 into the frame.
*/
sub sp, sp, #XCPTCONTEXT_SIZE
stmia sp, {r0-r12} /* Save the SVC mode regs */
/* Get the correct values of r13(sp) and r14(lr) in r1 and r2 */
add r1, sp, #XCPTCONTEXT_SIZE
mov r2, r14
/* Get the values for r15(pc) and CPSR in r3 and r4 */
ldr r0, .Lfiqtmp /* Points to temp storage */
ldmia r0, {r3, r4} /* Recover r1=lr_IRQ, r2=spsr_IRQ */
add r0, sp, #(4*REG_SP) /* Offset to pc, cpsr storage */
stmia r0, {r1-r4}
/* Then call the IRQ handler with interrupts disabled. */
mov fp, #0 /* Init frame pointer */
mov r0, sp /* Get r0=xcp */
#if CONFIG_ARCH_INTERRUPTSTACK > 3
ldr sp, .Lfiqstackbase /* SP = interrupt stack base */
str r0, [sp] /* Save the user stack pointer */
mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignement */
bl arm_decodefiq /* Call the handler */
ldr sp, [r4] /* Restore the user stack pointer */
#else
mov r4, sp /* Save the SP in a preserved register */
bic sp, sp, #7 /* Force 8-byte alignement */
bl arm_decodefiq /* Call the handler */
mov sp, r4 /* Restore the possibly unaligned stack pointer */
#endif
/* Upon return from arm_decodefiq, r0 holds the pointer to the register
* state save area to use to restore the registers. This may or may not
* be the same value that was passed to arm_decodefiq: It will differ if a
* context switch is required.
*/
/* Restore the CPSR, SVC mode registers and return */
ldr r1, [r0, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */
msr spsr, r1
ldmia r0, {r0-r15}^ /* Return */
.Lfiqtmp:
.word g_fiqtmp
#if CONFIG_ARCH_INTERRUPTSTACK > 3
.Lfiqstackbase:
.word g_fiqstackbase
#endif
#else #else
subs pc, lr, #4 subs pc, lr, #4
#endif #endif
@ -492,15 +575,33 @@ arm_vectorfiq:
#if CONFIG_ARCH_INTERRUPTSTACK > 3 #if CONFIG_ARCH_INTERRUPTSTACK > 3
.bss .bss
.align 4 .align 4
.globl g_intstackalloc .globl g_intstackalloc
.type g_intstackalloc, object .type g_intstackalloc, object
.globl g_intstackbase .globl g_intstackbase
.type g_intstackbase, object .type g_intstackbase, object
g_intstackalloc: g_intstackalloc:
.skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4)
g_intstackbase: g_intstackbase:
.skip 4 .skip 4
.size g_intstackbase, 4 .size g_intstackbase, 4
.size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3) .size g_intstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
#endif
#ifdef CONFIG_ARMV7A_DECODEFIQ
.globl g_fiqstackalloc
.type g_fiqstackalloc, object
.globl g_fiqstackbase
.type g_fiqstackbase, object
g_fiqstackalloc:
.skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4)
g_fiqstackbase:
.skip 4
.size g_fiqstackbase, 4
.size g_fiqstackalloc, (CONFIG_ARCH_INTERRUPTSTACK & ~3)
#endif /* CONFIG_ARMV7A_DECODEFIQ */
#endif /* CONFIG_ARCH_INTERRUPTSTACK > 3 */
.end .end

View File

@ -80,6 +80,7 @@ config SAMA5_HAVE_HSMCI2
config SAMA5_HAVE_SAIC config SAMA5_HAVE_SAIC
bool bool
default n default n
select ARMV7A_DECODEFIQ
config SAMA5_HAVE_SBM config SAMA5_HAVE_SBM
bool bool
@ -531,7 +532,8 @@ config SAMA5_SECURE
bool "Enable secure features" bool "Enable secure features"
default n default n
depends on SAMA5_HAVE_TRUSTZONE && EXPERIMENTAL depends on SAMA5_HAVE_TRUSTZONE && EXPERIMENTAL
select ARMV7A_DECODEFIQ if SAMA5_HAVE_SAIC ---help---
Does not do anything now, but may in the future
config SAMA5_PIO_IRQ config SAMA5_PIO_IRQ
bool "PIO pin interrupts" bool "PIO pin interrupts"

View File

@ -136,7 +136,7 @@ static void sam_dumpaic(const char *msg, uintptr_t base, int irq)
/* SAMA5D4 does not have the FFSR register */ /* SAMA5D4 does not have the FFSR register */
#ifdef SAM_AIC_FFSR #if defined(SAM_AIC_FFSR)
lldbg(" IMR: %08x CISR: %08x SPU: %08x FFSR: %08x\n", lldbg(" IMR: %08x CISR: %08x SPU: %08x FFSR: %08x\n",
getreg32(base + SAM_AIC_IMR_OFFSET), getreg32(base + SAM_AIC_IMR_OFFSET),
getreg32(base + SAM_AIC_CISR_OFFSET), getreg32(base + SAM_AIC_CISR_OFFSET),
@ -253,7 +253,7 @@ static uint32_t *sam_fiqhandler(int irq, uint32_t *regs)
* *
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
static inline bool sam_aic_ish64mx(uint32_t irq) static inline bool sam_aic_ish64mx(uint32_t irq)
{ {
return (irq == SAM_IRQ_ARM || return (irq == SAM_IRQ_ARM ||
@ -280,7 +280,7 @@ static inline bool sam_aic_ish64mx(uint32_t irq)
* *
****************************************************************************/ ****************************************************************************/
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
static bool sam_aic_issecure(uint32_t irq) static bool sam_aic_issecure(uint32_t irq)
{ {
uintptr_t regaddr; uintptr_t regaddr;
@ -418,7 +418,7 @@ void up_irqinitialize(void)
sam_aic_initialize(SAM_AIC_VBASE); sam_aic_initialize(SAM_AIC_VBASE);
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
/* Initialize the Secure Advanced Interrupt Controller (SAIC) */ /* Initialize the Secure Advanced Interrupt Controller (SAIC) */
sam_aic_initialize(SAM_SAIC_VBASE); sam_aic_initialize(SAM_SAIC_VBASE);
@ -621,10 +621,10 @@ uint32_t *arm_decodeirq(uint32_t *regs)
return sam_decodeirq(SAM_AIC_VBASE, regs); return sam_decodeirq(SAM_AIC_VBASE, regs);
} }
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
/* This is the entry point from the ARM FIQ vector handler */ /* This is the entry point from the ARM FIQ vector handler */
uint32_t *arm_decodefiq(uint32_t *regs) uint32_t *arm_decodefiq(FAR uint32_t *regs)
{ {
/* In order to distinguish a FIQ from a true secure interrupt we need to /* In order to distinguish a FIQ from a true secure interrupt we need to
* check the state of the FIQ line in the SAIC_CISR register. * check the state of the FIQ line in the SAIC_CISR register.
@ -632,7 +632,7 @@ uint32_t *arm_decodefiq(uint32_t *regs)
if ((getreg32(SAM_SAIC_CISR) & AIC_CISR_NFIQ) != 0) if ((getreg32(SAM_SAIC_CISR) & AIC_CISR_NFIQ) != 0)
{ {
return sam_fiqhandler(SAM_IRQ_FIQ, regs); return arm_doirq(SAM_IRQ_FIQ, regs);
} }
else else
{ {
@ -681,7 +681,7 @@ static void sam_disable_irq(uintptr_t base, int irq)
void up_disable_irq(int irq) void up_disable_irq(int irq)
{ {
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
if (sam_aic_issecure(irq)) if (sam_aic_issecure(irq))
{ {
sam_disable_irq(SAM_SAIC_VBASE, irq); sam_disable_irq(SAM_SAIC_VBASE, irq);
@ -733,7 +733,7 @@ static void sam_enable_irq(uintptr_t base, int irq)
void up_enable_irq(int irq) void up_enable_irq(int irq)
{ {
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
if (sam_aic_issecure(irq)) if (sam_aic_issecure(irq))
{ {
sam_enable_irq(SAM_SAIC_VBASE, irq); sam_enable_irq(SAM_SAIC_VBASE, irq);
@ -809,7 +809,7 @@ static int sam_prioritize_irq(uint32_t base, int irq, int priority)
int up_prioritize_irq(int irq, int priority) int up_prioritize_irq(int irq, int priority)
{ {
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
if (sam_aic_issecure(irq)) if (sam_aic_issecure(irq))
{ {
sam_prioritize_irq(SAM_SAIC_VBASE, irq, priority); sam_prioritize_irq(SAM_SAIC_VBASE, irq, priority);
@ -867,7 +867,7 @@ static void _sam_irq_srctype(uintptr_t base, int irq,
void sam_irq_srctype(int irq, enum sam_srctype_e srctype) void sam_irq_srctype(int irq, enum sam_srctype_e srctype)
{ {
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC) #if defined(CONFIG_SAMA5_HAVE_SAIC)
if (sam_aic_issecure(irq)) if (sam_aic_issecure(irq))
{ {
_sam_irq_srctype(SAM_SAIC_VBASE, irq, srctype); _sam_irq_srctype(SAM_SAIC_VBASE, irq, srctype);

View File

@ -118,7 +118,7 @@ CONFIG_ARMV7A_TOOLCHAIN_CODESOURCERYW=y
# CONFIG_ARMV7A_TOOLCHAIN_GNU_EABIL is not set # CONFIG_ARMV7A_TOOLCHAIN_GNU_EABIL is not set
# CONFIG_ARMV7A_TOOLCHAIN_GNU_EABIW is not set # CONFIG_ARMV7A_TOOLCHAIN_GNU_EABIW is not set
# CONFIG_ARMV7A_TOOLCHAIN_GNU_OABI is not set # CONFIG_ARMV7A_TOOLCHAIN_GNU_OABI is not set
# CONFIG_ARMV7A_DECODEFIQ is not set CONFIG_ARMV7A_DECODEFIQ=y
# #
# SAMA5 Configuration Options # SAMA5 Configuration Options
@ -213,7 +213,6 @@ CONFIG_SAMA5_USART3=y
# CONFIG_SAMA5_FUSE is not set # CONFIG_SAMA5_FUSE is not set
CONFIG_SAMA5_MPDDRC=y CONFIG_SAMA5_MPDDRC=y
# CONFIG_SAMA5_VDEC is not set # CONFIG_SAMA5_VDEC is not set
# CONFIG_SAMA5_SECURE is not set
# CONFIG_SAMA5_PIO_IRQ is not set # CONFIG_SAMA5_PIO_IRQ is not set
# #