SAMA5D4: Add partial support for secure interrupt controller (SAIC)
This commit is contained in:
parent
aecddf9b52
commit
0a2133b57f
@ -55,4 +55,13 @@ config ARMV7A_OABI_TOOLCHAIN
|
||||
default n
|
||||
depends on ARMV7A_TOOLCHAIN_BUILDROOT
|
||||
---help---
|
||||
Most of the older buildroot toolchains are OABI and are named arm-nuttx-elf- vs. arm-nuttx-eabi-
|
||||
Most of the older buildroot toolchains are OABI and are named
|
||||
arm-nuttx-elf- vs. arm-nuttx-eabi-
|
||||
|
||||
config ARMV7A_DECODEFIQ
|
||||
bool "FIQ Handler"
|
||||
default n
|
||||
---help---
|
||||
Select this option if your platform supports the function
|
||||
arm_decodefiq(). This is used primarily to support secure TrustZone
|
||||
interrupts received on the FIQ vector.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/************************************************************************************
|
||||
* arch/arm/src/armv7-a/arm_vectors.S
|
||||
*
|
||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -469,7 +469,8 @@ arm_vectorundefinsn:
|
||||
* Name: arm_vectorfiq
|
||||
*
|
||||
* Description:
|
||||
* Shouldn't happen
|
||||
* Shouldn't happen unless a arm_decodefiq() is provided. FIQ is primarily used
|
||||
* with the TrustZone feature in order to handler secure interrupts.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
@ -477,7 +478,11 @@ arm_vectorundefinsn:
|
||||
.type arm_vectorfiq, %function
|
||||
|
||||
arm_vectorfiq:
|
||||
#ifdef CONFIG_ARMV7A_DECODEFIQ
|
||||
# error Missing logic
|
||||
#else
|
||||
subs pc, lr, #4
|
||||
#endif
|
||||
.size arm_vectorfiq, . - arm_vectorfiq
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -101,6 +101,10 @@ config SAMA5_HAVE_TC2
|
||||
bool
|
||||
default n
|
||||
|
||||
config SAMA5_HAVE_TRUSTZONE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SAMA5_HAVE_TWI3
|
||||
bool
|
||||
default n
|
||||
@ -135,6 +139,7 @@ config ARCH_CHIP_SAMA5D4
|
||||
select SAMA5_HAVE_SPI2
|
||||
select SAMA5_HAVE_TC1
|
||||
select SAMA5_HAVE_TC2
|
||||
select SAMA5_HAVE_TRUSTZONE
|
||||
select SAMA5_HAVE_TWI3
|
||||
select ARCH_NAND_HWECC
|
||||
|
||||
@ -522,6 +527,12 @@ config SAMA5_VDEC
|
||||
|
||||
endmenu # SAMA5 Peripheral Support
|
||||
|
||||
config SAMA5_SECURE
|
||||
bool "Enable secure features"
|
||||
default n
|
||||
depends on SAMA5_HAVE_TRUSTZONE && EXPERIMENTAL
|
||||
select ARMV7A_DECODEFIQ if SAMA5_HAVE_SAIC
|
||||
|
||||
config SAMA5_PIO_IRQ
|
||||
bool "PIO pin interrupts"
|
||||
---help---
|
||||
|
@ -108,7 +108,7 @@
|
||||
#define SAM_AIC_WPMR (SAM_AIC_VBASE+SAM_AIC_WPMR_OFFSET)
|
||||
#define SAM_AIC_WPSR (SAM_AIC_VBASE+SAM_AIC_WPSR_OFFSET)
|
||||
|
||||
#ifdef SAMA5_HAVE_SAIC
|
||||
#ifdef CONFIG_SAMA5_HAVE_SAIC
|
||||
# define SAM_SAIC_SSR (SAM_SAIC_VBASE+SAM_AIC_SSR_OFFSET)
|
||||
# define SAM_SAIC_SMR (SAM_SAIC_VBASE+SAM_AIC_SMR_OFFSET)
|
||||
# define SAM_SAIC_SVR (SAM_SAIC_VBASE+SAM_AIC_SVR_OFFSET)
|
||||
|
@ -203,6 +203,7 @@
|
||||
# define SAM_MATRIX_SRTSR11_OFFSET 0x02ac /* Security Region Top Slave 11 Register */
|
||||
# define SAM_MATRIX_SRTSR12_OFFSET 0x02b0 /* Security Region Top Slave 12 Register */
|
||||
|
||||
# define SAM_MATRIX_SPSELR_OFFSET(n) (0x02c0 + ((n) << 2))
|
||||
# define SAM_MATRIX_SPSELR1_OFFSET 0x02c0 /* Security Peripheral Select 1 Register */
|
||||
# define SAM_MATRIX_SPSELR2_OFFSET 0x02c4 /* Security Peripheral Select 2 Register */
|
||||
# define SAM_MATRIX_SPSELR3_OFFSET 0x02c8 /* Security Peripheral Select 3 Register */
|
||||
@ -290,10 +291,7 @@
|
||||
#endif /* ATSAMA5D3 */
|
||||
|
||||
#ifdef ATSAMA5D4
|
||||
/* HMATRIX0 (H64MX)
|
||||
*
|
||||
*
|
||||
*/
|
||||
/* HMATRIX0 (H64MX) */
|
||||
|
||||
# define SAM_MATRIX0_MCFG(n)) (SAM_MATRIX64_VBASE+SAM_MATRIX_MCFG_OFFSET(n))
|
||||
# define SAM_MATRIX0_MCFG0 (SAM_MATRIX64_VBASE+SAM_MATRIX_MCFG0_OFFSET)
|
||||
@ -414,6 +412,7 @@
|
||||
# define SAM_MATRIX0_SRTSR11 (SAM_MATRIX64_VBASE+SAM_MATRIX_SRTSR11_OFFSET)
|
||||
# define SAM_MATRIX0_SRTSR12 (SAM_MATRIX64_VBASE+SAM_MATRIX_SRTSR12_OFFSET)
|
||||
|
||||
# define SAM_MATRIX0_SPSELR(n) (SAM_MATRIX64_VBASE+SAM_MATRIX_SPSELR_OFFSET(n))
|
||||
# define SAM_MATRIX0_SPSELR1 (SAM_MATRIX64_VBASE+SAM_MATRIX_SPSELR1_OFFSET)
|
||||
# define SAM_MATRIX0_SPSELR2 (SAM_MATRIX64_VBASE+SAM_MATRIX_SPSELR2_OFFSET)
|
||||
# define SAM_MATRIX0_SPSELR3 (SAM_MATRIX64_VBASE+SAM_MATRIX_SPSELR3_OFFSET)
|
||||
@ -539,6 +538,7 @@
|
||||
# define SAM_MATRIX1_SRTSR11 (SAM_MATRIX32_VBASE+SAM_MATRIX_SRTSR11_OFFSET)
|
||||
# define SAM_MATRIX1_SRTSR12 (SAM_MATRIX32_VBASE+SAM_MATRIX_SRTSR12_OFFSET)
|
||||
|
||||
# define SAM_MATRIX1_SPSELR(n) (SAM_MATRIX32_VBASE+SAM_MATRIX_SPSELR_OFFSET(n))
|
||||
# define SAM_MATRIX1_SPSELR1 (SAM_MATRIX32_VBASE+SAM_MATRIX_SPSELR1_OFFSET)
|
||||
# define SAM_MATRIX1_SPSELR2 (SAM_MATRIX32_VBASE+SAM_MATRIX_SPSELR2_OFFSET)
|
||||
# define SAM_MATRIX1_SPSELR3 (SAM_MATRIX32_VBASE+SAM_MATRIX_SPSELR3_OFFSET)
|
||||
|
@ -107,47 +107,57 @@ static const uint8_t g_srctype[SCRTYPE_NTYPES] =
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_DEBUG_IRQ)
|
||||
static void sam_dumpaic(const char *msg, int irq)
|
||||
static void sam_dumpaic(const char *msg, uintptr_t base, int irq)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = irqsave();
|
||||
lldbg("AIC (%s, irq=%d):\n", msg, irq);
|
||||
lldbg("AIC (%s, base=%08x irq=%d):\n", msg, base, irq);
|
||||
|
||||
/* Select the register set associated with this irq */
|
||||
|
||||
putreg32(irq, SAM_AIC_SSR);
|
||||
putreg32(irq, base + SAM_AIC_SSR_OFFSET);
|
||||
|
||||
/* Then dump all of the (readable) register contents */
|
||||
|
||||
lldbg(" SSR: %08x SMR: %08x SVR: %08x IVR: %08x\n",
|
||||
getreg32(SAM_AIC_SSR), getreg32(SAM_AIC_SMR),
|
||||
getreg32(SAM_AIC_SVR), getreg32(SAM_AIC_IVR));
|
||||
getreg32(base + SAM_AIC_SSR_OFFSET),
|
||||
getreg32(base + SAM_AIC_SMR_OFFSET),
|
||||
getreg32(base + SAM_AIC_SVR_OFFSET),
|
||||
getreg32(base + SAM_AIC_IVR_OFFSET));
|
||||
lldbg(" FVR: %08x ISR: %08x\n",
|
||||
getreg32(SAM_AIC_FVR), getreg32(SAM_AIC_ISR));
|
||||
getreg32(base + SAM_AIC_FVR_OFFSET),
|
||||
getreg32(base + SAM_AIC_ISR_OFFSET));
|
||||
lldbg(" IPR: %08x %08x %08x %08x\n",
|
||||
getreg32(SAM_AIC_IPR0), getreg32(SAM_AIC_IPR1),
|
||||
getreg32(SAM_AIC_IPR2), getreg32(SAM_AIC_IPR3));
|
||||
getreg32(base + SAM_AIC_IPR0_OFFSET),
|
||||
getreg32(base + SAM_AIC_IPR1_OFFSET),
|
||||
getreg32(base + SAM_AIC_IPR2_OFFSET),
|
||||
getreg32(base + SAM_AIC_IPR3_OFFSET));
|
||||
|
||||
/* SAMA5D4 does not have the FFSR register */
|
||||
|
||||
#ifdef SAM_AIC_FFSR
|
||||
lldbg(" IMR: %08x CISR: %08x SPU: %08x FFSR: %08x\n",
|
||||
getreg32(SAM_AIC_IMR), getreg32(SAM_AIC_CISR),
|
||||
getreg32(SAM_AIC_SPU), getreg32(SAM_AIC_FFSR));
|
||||
getreg32(base + SAM_AIC_IMR_OFFSET),
|
||||
getreg32(base + SAM_AIC_CISR_OFFSET),
|
||||
getreg32(base + SAM_AIC_SPU_OFFSET),
|
||||
getreg32(base + SAM_AIC_FFSR_OFFSET));
|
||||
#else
|
||||
lldbg(" IMR: %08x CISR: %08x SPU: %08x\n",
|
||||
getreg32(SAM_AIC_IMR), getreg32(SAM_AIC_CISR),
|
||||
getreg32(SAM_AIC_SPU));
|
||||
getreg32(base + SAM_AIC_IMR_OFFSET),
|
||||
getreg32(base + SAM_AIC_CISR_OFFSET),
|
||||
getreg32(base + SAM_AIC_SPU_OFFSET));
|
||||
#endif
|
||||
|
||||
lldbg(" DCR: %08x WPMR: %08x WPSR: %08x\n",
|
||||
getreg32(SAM_AIC_DCR), getreg32(SAM_AIC_WPMR),
|
||||
getreg32(SAM_AIC_WPSR));
|
||||
getreg32(base + SAM_AIC_DCR_OFFSET),
|
||||
getreg32(base + SAM_AIC_WPMR_OFFSET),
|
||||
getreg32(base + SAM_AIC_WPSR_OFFSET));
|
||||
|
||||
irqrestore(flags);
|
||||
}
|
||||
#else
|
||||
# define sam_dumpaic(msg, irq)
|
||||
# define sam_dumpaic(msg, base, irq)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -232,6 +242,143 @@ static uint32_t *sam_fiqhandler(int irq, uint32_t *regs)
|
||||
return regs; /* Won't get here */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_aic_ish64mx
|
||||
*
|
||||
* Description:
|
||||
* Return true if the peripheral is H64 Matrix.
|
||||
*
|
||||
* Input Parameter:
|
||||
* PID = IRQ number
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
static inline bool sam_aic_ish64mx(uint32_t irq)
|
||||
{
|
||||
return (irq == SAM_IRQ_ARM ||
|
||||
irq == SAM_IRQ_XDMAC0 ||
|
||||
/* irq == SAM_IRQ_CPKCC || */
|
||||
irq == SAM_IRQ_AESB ||
|
||||
irq == SAM_IRQ_MPDDRC ||
|
||||
irq == SAM_IRQ_VDEC ||
|
||||
irq == SAM_IRQ_XDMAC1 ||
|
||||
irq == SAM_IRQ_LCDC ||
|
||||
irq == SAM_IRQ_ISI ||
|
||||
irq == SAM_IRQ_L2CC);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_aic_issecure
|
||||
*
|
||||
* Description:
|
||||
* Return true if the peripheral secure.
|
||||
*
|
||||
* Input Parameter:
|
||||
* PID = IRQ number
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
static bool sam_aic_issecure(uint32_t irq)
|
||||
{
|
||||
uintptr_t regaddr;
|
||||
uint32_t bit;
|
||||
int regndx;
|
||||
|
||||
/* Get the register index and bit mask */
|
||||
|
||||
regndx = (irq >> 5);
|
||||
bit = ((uint32_t)1 << (irq & 0x1f));
|
||||
|
||||
/* Get the SPSELR register address */
|
||||
|
||||
if (sam_aic_ish64mx(irq))
|
||||
{
|
||||
/* H64MX. Use Matrix 0 */
|
||||
|
||||
regaddr = SAM_MATRIX0_SPSELR(regndx);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* H32MX. Use Matrix 1 */
|
||||
|
||||
regaddr = SAM_MATRIX1_SPSELR(regndx);
|
||||
}
|
||||
|
||||
/* Return true if the bit corresponding to this IRQ is zero */
|
||||
|
||||
return (getreg32(regaddr) & bit) == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_aic_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the AIC or the SAIC.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sam_aic_initialize(uintptr_t base)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Unprotect SMR, SVR, SPU and DCR register */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY, base + SAM_AIC_WPMR_OFFSET);
|
||||
|
||||
/* Configure the FIQ and the IRQs. */
|
||||
|
||||
for (i = 0; i < SAM_IRQ_NINT; i++)
|
||||
{
|
||||
/* Select the interrupt registers */
|
||||
|
||||
putreg32(i, base + SAM_AIC_SSR_OFFSET);
|
||||
|
||||
/* Disable the interrupt */
|
||||
|
||||
putreg32(AIC_IDCR_INTD, base + SAM_AIC_IDCR_OFFSET);
|
||||
|
||||
/* Set the (unused) FIQ/IRQ handler */
|
||||
|
||||
if (i == SAM_PID_FIQ)
|
||||
{
|
||||
putreg32((uint32_t)sam_fiqhandler, base + SAM_AIC_SVR_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
putreg32((uint32_t)arm_doirq, base + SAM_AIC_SVR_OFFSET);
|
||||
}
|
||||
|
||||
/* Set the default interrupt priority */
|
||||
|
||||
putreg32(SAM_DEFAULT_PRIOR, base + SAM_AIC_SMR_OFFSET);
|
||||
|
||||
/* Clear any pending interrupt */
|
||||
|
||||
putreg32(AIC_ICCR_INTCLR, base + SAM_AIC_ICCR_OFFSET);
|
||||
}
|
||||
|
||||
/* Set the (unused) spurious interrupt handler */
|
||||
|
||||
putreg32((uint32_t)sam_spurious, base + SAM_AIC_SPU_OFFSET);
|
||||
|
||||
/* Perform 8 interrupt acknowledgements by writing any value to the
|
||||
* EOICR register.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 8 ; i++)
|
||||
{
|
||||
putreg32(AIC_EOICR_ENDIT, base + SAM_AIC_EOICR_OFFSET);
|
||||
}
|
||||
|
||||
/* Restore protection and the interrupt state */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, base + SAM_AIC_WPMR_OFFSET);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -251,7 +398,6 @@ void up_irqinitialize(void)
|
||||
#if defined(CONFIG_SAMA5_BOOT_ISRAM) || defined(CONFIG_SAMA5_BOOT_CS0FLASH)
|
||||
size_t vectorsize;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
/* The following operations need to be atomic, but since this function is
|
||||
* called early in the initialization sequence, we expect to have exclusive
|
||||
@ -268,58 +414,16 @@ void up_irqinitialize(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Unprotect SMR, SVR, SPU and DCR register */
|
||||
/* Initialize the Advanced Interrupt Controller (AIC) */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY, SAM_AIC_WPMR);
|
||||
sam_aic_initialize(SAM_AIC_VBASE);
|
||||
|
||||
/* Configure the FIQ and the IRQs. */
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
/* Initialize the Secure Advanced Interrupt Controller (SAIC) */
|
||||
|
||||
for (i = 0; i < SAM_IRQ_NINT; i++)
|
||||
{
|
||||
/* Select the interrupt registers */
|
||||
sam_aic_initialize(SAM_SAIC_VBASE);
|
||||
|
||||
putreg32(i, SAM_AIC_SSR);
|
||||
|
||||
/* Disable the interrupt */
|
||||
|
||||
putreg32(AIC_IDCR_INTD, SAM_AIC_IDCR);
|
||||
|
||||
/* Set the (unused) FIQ/IRQ handler */
|
||||
|
||||
if (i == SAM_PID_FIQ)
|
||||
{
|
||||
putreg32((uint32_t)sam_fiqhandler, SAM_AIC_SVR);
|
||||
}
|
||||
else
|
||||
{
|
||||
putreg32((uint32_t)arm_doirq, SAM_AIC_SVR);
|
||||
}
|
||||
|
||||
/* Set the default interrupt priority */
|
||||
|
||||
putreg32(SAM_DEFAULT_PRIOR, SAM_AIC_SMR);
|
||||
|
||||
/* Clear any pending interrupt */
|
||||
|
||||
putreg32(AIC_ICCR_INTCLR, SAM_AIC_ICCR);
|
||||
}
|
||||
|
||||
/* Set the (unused) spurious interrupt handler */
|
||||
|
||||
putreg32((uint32_t)sam_spurious, SAM_AIC_SPU);
|
||||
|
||||
/* Perform 8 interrupt acknowledgements by writing any value to the
|
||||
* EOICR register.
|
||||
*/
|
||||
|
||||
for (i = 0; i < 8 ; i++)
|
||||
{
|
||||
putreg32(AIC_EOICR_ENDIT, SAM_AIC_EOICR);
|
||||
}
|
||||
|
||||
/* Restore protection and the interrupt state */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_LOWVECTORS)
|
||||
/* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the
|
||||
@ -337,7 +441,7 @@ void up_irqinitialize(void)
|
||||
* 0x0000:00000. VBAR == 0x0000:0000.
|
||||
*
|
||||
* This method is used when booting from ISRAM or NOR FLASH. In
|
||||
& that case, vectors must lie at the beginning of NOFR FLASH.
|
||||
* that case, vectors must lie at the beginning of NOFR FLASH.
|
||||
*
|
||||
* 3. Set the Cortex-A5 VBAR register so that the vector table address
|
||||
* is moved to a location other than 0x0000:0000.
|
||||
@ -440,7 +544,7 @@ void up_irqinitialize(void)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_decodeirq
|
||||
* Name: arm_decodeirq, arm_decodefiq (and sam_decodeirq helper).
|
||||
*
|
||||
* Description:
|
||||
* This function is called from the IRQ vector handler in arm_vectors.S.
|
||||
@ -454,7 +558,7 @@ void up_irqinitialize(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
static uint32_t *sam_decodeirq(uintptr_t base, uint32_t *regs)
|
||||
{
|
||||
uint32_t irqid;
|
||||
uint32_t ivr;
|
||||
@ -491,14 +595,14 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
/* Write in the IVR to support Protect Mode */
|
||||
|
||||
ivr = getreg32(SAM_AIC_IVR);
|
||||
putreg32(ivr, SAM_AIC_IVR);
|
||||
ivr = getreg32(base + SAM_AIC_IVR_OFFSET);
|
||||
putreg32(ivr, base + SAM_AIC_IVR_OFFSET);
|
||||
|
||||
/* Get the IRQ number from the interrupt status register. NOTE that the
|
||||
* IRQ number is the same is the peripheral ID (PID).
|
||||
*/
|
||||
|
||||
irqid = getreg32(SAM_AIC_ISR) & AIC_ISR_MASK;
|
||||
irqid = getreg32(base + SAM_AIC_ISR_OFFSET) & AIC_ISR_MASK;
|
||||
|
||||
/* Dispatch the interrupt */
|
||||
|
||||
@ -506,19 +610,46 @@ uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
|
||||
/* Acknowledge interrupt */
|
||||
|
||||
putreg32(AIC_EOICR_ENDIT, SAM_AIC_EOICR);
|
||||
putreg32(AIC_EOICR_ENDIT, base + SAM_AIC_EOICR_OFFSET);
|
||||
return regs;
|
||||
}
|
||||
|
||||
/* This is the entry point from the ARM IRQ vector handler */
|
||||
|
||||
uint32_t *arm_decodeirq(uint32_t *regs)
|
||||
{
|
||||
return sam_decodeirq(SAM_AIC_VBASE, regs);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
/* This is the entry point from the ARM FIQ vector handler */
|
||||
|
||||
uint32_t *arm_decodefiq(uint32_t *regs)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
if ((getreg32(SAM_SAIC_CISR) & AIC_CISR_NFIQ) != 0)
|
||||
{
|
||||
return sam_fiqhandler(SAM_IRQ_FIQ, regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return sam_decodeirq(SAM_SAIC_VBASE, regs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_disable_irq
|
||||
* Name: up_disable_irq (and sam_disable_irq helper)
|
||||
*
|
||||
* Description:
|
||||
* Disable the IRQ specified by 'irq'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_disable_irq(int irq)
|
||||
static void sam_disable_irq(uintptr_t base, int irq)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
@ -530,12 +661,12 @@ void up_disable_irq(int irq)
|
||||
|
||||
/* Select the register set associated with this irq */
|
||||
|
||||
putreg32(irq, SAM_AIC_SSR);
|
||||
putreg32(irq, base + SAM_AIC_SSR_OFFSET);
|
||||
|
||||
/* Disable the interrupt */
|
||||
|
||||
putreg32(AIC_IDCR_INTD, SAM_AIC_IDCR);
|
||||
sam_dumpaic("disable", irq);
|
||||
putreg32(AIC_IDCR_INTD, base + SAM_AIC_IDCR_OFFSET);
|
||||
sam_dumpaic("disable", base, irq);
|
||||
irqrestore(flags);
|
||||
}
|
||||
#ifdef CONFIG_SAMA5_PIO_IRQ
|
||||
@ -546,18 +677,31 @@ void up_disable_irq(int irq)
|
||||
sam_pioirqdisable(irq);
|
||||
}
|
||||
#endif
|
||||
sam_dumpaic("disable", irq);
|
||||
}
|
||||
|
||||
void up_disable_irq(int irq)
|
||||
{
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
if (sam_aic_issecure(irq))
|
||||
{
|
||||
sam_disable_irq(SAM_SAIC_VBASE, irq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sam_disable_irq(SAM_AIC_VBASE, irq);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_enable_irq
|
||||
* Name: up_enable_irq (and sam_enable_irq helper)
|
||||
*
|
||||
* Description:
|
||||
* Enable the IRQ specified by 'irq'
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_enable_irq(int irq)
|
||||
static void sam_enable_irq(uintptr_t base, int irq)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
@ -569,12 +713,12 @@ void up_enable_irq(int irq)
|
||||
|
||||
/* Select the register set associated with this irq */
|
||||
|
||||
putreg32(irq, SAM_AIC_SSR);
|
||||
putreg32(irq, base + SAM_AIC_SSR_OFFSET);
|
||||
|
||||
/* Enable the interrupt */
|
||||
|
||||
putreg32(AIC_IECR_INTEN, SAM_AIC_IECR);
|
||||
sam_dumpaic("enable", irq);
|
||||
putreg32(AIC_IECR_INTEN, base + SAM_AIC_IECR_OFFSET);
|
||||
sam_dumpaic("enable", base, irq);
|
||||
irqrestore(flags);
|
||||
}
|
||||
#ifdef CONFIG_SAMA5_PIO_IRQ
|
||||
@ -587,6 +731,20 @@ void up_enable_irq(int irq)
|
||||
#endif
|
||||
}
|
||||
|
||||
void up_enable_irq(int irq)
|
||||
{
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
if (sam_aic_issecure(irq))
|
||||
{
|
||||
sam_enable_irq(SAM_SAIC_VBASE, irq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sam_enable_irq(SAM_AIC_VBASE, irq);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_maskack_irq
|
||||
*
|
||||
@ -601,7 +759,7 @@ void up_maskack_irq(int irq)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_prioritize_irq
|
||||
* Name: up_prioritize_irq (and sam_prioritize_irq helper)
|
||||
*
|
||||
* Description:
|
||||
* Set the priority of an IRQ.
|
||||
@ -612,7 +770,7 @@ void up_maskack_irq(int irq)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_IRQPRIO
|
||||
int up_prioritize_irq(int irq, int priority)
|
||||
static int sam_prioritize_irq(uint32_t base, int irq, int priority)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
@ -626,32 +784,46 @@ int up_prioritize_irq(int irq, int priority)
|
||||
|
||||
/* Select the register set associated with this irq */
|
||||
|
||||
putreg32(irq, SAM_AIC_SSR);
|
||||
putreg32(irq, base + SAM_AIC_SSR_OFFSET);
|
||||
|
||||
/* Unprotect and write the SMR register */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY, SAM_AIC_WPMR);
|
||||
putreg32(AIC_WPMR_WPKEY, base + SAM_AIC_WPMR_OFFSET);
|
||||
|
||||
/* Set the new priority, preserving the current srctype */
|
||||
|
||||
regval = getreg32(SAM_AIC_SMR);
|
||||
regval = getreg32(base + SAM_AIC_SMR_OFFSET);
|
||||
regval &= ~AIC_SMR_PRIOR_MASK;
|
||||
regval |= (uint32_t)priority << AIC_SMR_PRIOR_SHIFT;
|
||||
putreg32(regval, SAM_AIC_SMR);
|
||||
putreg32(regval, base + SAM_AIC_SMR_OFFSET);
|
||||
|
||||
/* Restore protection and the interrupt state */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR);
|
||||
sam_dumpaic("prioritize", irq);
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, base + SAM_AIC_WPMR_OFFSET);
|
||||
sam_dumpaic("prioritize", base, irq);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int up_prioritize_irq(int irq, int priority)
|
||||
{
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
if (sam_aic_issecure(irq))
|
||||
{
|
||||
sam_prioritize_irq(SAM_SAIC_VBASE, irq, priority);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sam_prioritize_irq(SAM_AIC_VBASE, irq, priority);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam_irq_srctype
|
||||
* Name: sam_irq_srctype (and _sam_irq_srctype helper)
|
||||
*
|
||||
* Description:
|
||||
* irq - Identifies the IRQ source to be configured
|
||||
@ -659,7 +831,8 @@ int up_prioritize_irq(int irq, int priority)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sam_irq_srctype(int irq, enum sam_srctype_e srctype)
|
||||
static void _sam_irq_srctype(uintptr_t base, int irq,
|
||||
enum sam_srctype_e srctype)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
@ -672,22 +845,36 @@ void sam_irq_srctype(int irq, enum sam_srctype_e srctype)
|
||||
|
||||
/* Select the register set associated with this irq */
|
||||
|
||||
putreg32(irq, SAM_AIC_SSR);
|
||||
putreg32(irq, base + SAM_AIC_SSR_OFFSET);
|
||||
|
||||
/* Unprotect and write the SMR register */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY, SAM_AIC_WPMR);
|
||||
putreg32(AIC_WPMR_WPKEY, base + SAM_AIC_WPMR_OFFSET);
|
||||
|
||||
/* Set the new srctype, preserving the current priority */
|
||||
|
||||
regval = getreg32(SAM_AIC_SMR);
|
||||
regval = getreg32(base + SAM_AIC_SMR_OFFSET);
|
||||
regval &= ~AIC_SMR_SRCTYPE_MASK;
|
||||
regval |= (uint32_t)g_srctype[srctype] << AIC_SMR_SRCTYPE_SHIFT;
|
||||
putreg32(regval, SAM_AIC_SMR);
|
||||
putreg32(regval, base + SAM_AIC_SMR_OFFSET);
|
||||
|
||||
/* Restore protection and the interrupt state */
|
||||
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, SAM_AIC_WPMR);
|
||||
sam_dumpaic("srctype", irq);
|
||||
putreg32(AIC_WPMR_WPKEY | AIC_WPMR_WPEN, base + SAM_AIC_WPMR_OFFSET);
|
||||
sam_dumpaic("srctype", base, irq);
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
void sam_irq_srctype(int irq, enum sam_srctype_e srctype)
|
||||
{
|
||||
#if defined(CONFIG_SAMA5_SECURE) && defined(CONFIG_SAMA5_HAVE_SAIC)
|
||||
if (sam_aic_issecure(irq))
|
||||
{
|
||||
_sam_irq_srctype(SAM_SAIC_VBASE, irq, srctype);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_sam_irq_srctype(SAM_AIC_VBASE, irq, srctype);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user