Merged in ebsong/nuttx (pull request #712)
Pull request for cortex-r4 codes * arm/armv7-r: Add general interrupt controller. This is based on armv7-a gic controller code. Signed-off-by: EunBong Song <eunb.song@samsung.com> * arm/armv7-r: add invalidate dcache in arm_head.S Adding invalidate dcache as a comment in arm_head.S. Signed-off-by: EunBong Song <eunb.song@samsung.com> * arm/armv7-r: Fix some wrong configuration of program status register. PSR_E_BIT bit should be set for big endian system. PSR_A_BIT bis is set automatically as arm cortex-r4 reference manual 3.7.4. So we don't need to set this bit. Signed-off-by: EunBong Song <eunb.song@samsung.com> * arm/armv7-r: Fix some wrong MPU register definition. Change MPU_RBAR_ADDR_MASK and MPU_RACR_TEX_SHIFT mask as arm cortex-r4 reference manual. Region Base Address Register 0-4 bits are reserved. MPU Region Access control register type 3-5 bits. Signed-off-by: EunBong Song <eunb.song@samsung.com> * driver/mtd: fix compilation error. This commit fixes below compilation errors. CC: mtd/smart.c mtd/smart.c:182:22: error: 'gWearBitToLevelMap4' defined but not used [-Werror=unused-const-variable=] static const uint8_t gWearBitToLevelMap4[] = ^~~~~~~~~~~~~~~~~~~ mtd/smart.c:170:22: error: 'gWearLevelToBitMap4' defined but not used [-Werror=unused-const-variable=] static const uint8_t gWearLevelToBitMap4[] = ^~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors make[1]: *** [smart.o] Error 1 Signed-off-by: Junyeon LEE <junyeon2.lee@samsung.com> Approved-by: GregoryN <gnutt@nuttx.org>
This commit is contained in:
parent
84ede4a25a
commit
d33b0640fe
@ -5,6 +5,13 @@
|
|||||||
|
|
||||||
comment "ARMv7-R Configuration Options"
|
comment "ARMv7-R Configuration Options"
|
||||||
|
|
||||||
|
config ARMV7R_HAVE_GICv2
|
||||||
|
bool "ARMV7R_GICv2 support"
|
||||||
|
default y
|
||||||
|
---help---
|
||||||
|
Selected by the configuration tool if the architecture supports the
|
||||||
|
Generic Interrupt Controller (GIC)
|
||||||
|
|
||||||
config ARMV7R_MEMINIT
|
config ARMV7R_MEMINIT
|
||||||
bool
|
bool
|
||||||
default y if BOOT_SDRAM_DATA
|
default y if BOOT_SDRAM_DATA
|
||||||
|
529
arch/arm/src/armv7-r/arm_gicv2.c
Normal file
529
arch/arm/src/armv7-r/arm_gicv2.c
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/armv7-r/arm_gicv2.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <arch/irq.h>
|
||||||
|
|
||||||
|
#include "up_arch.h"
|
||||||
|
#include "up_internal.h"
|
||||||
|
#include "gic.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARMV7R_HAVE_GICv2
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_gic_nlines
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Return the number of interrupt lines supported by this GIC
|
||||||
|
* implementation (include both PPIs (32) and SPIs).
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The number of interrupt lines.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline unsigned int arm_gic_nlines(void)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
uint32_t field;
|
||||||
|
|
||||||
|
/* Get the number of interrupt lines. */
|
||||||
|
|
||||||
|
regval = getreg32(GIC_ICDICTR);
|
||||||
|
field = (regval & GIC_ICDICTR_ITLINES_MASK) >> GIC_ICDICTR_ITLINES_SHIFT;
|
||||||
|
return (field + 1) << 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_gic0_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform common, one-time GIC initialization on CPU0 only. Both
|
||||||
|
* arm_gic0_initialize() must be called on CPU0; arm_gic_initialize() must
|
||||||
|
* be called for all CPUs.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm_gic0_initialize(void)
|
||||||
|
{
|
||||||
|
unsigned int nlines = arm_gic_nlines();
|
||||||
|
unsigned int irq;
|
||||||
|
|
||||||
|
/* Initialize SPIs. The following should be done only by CPU0. */
|
||||||
|
|
||||||
|
/* A processor in Secure State sets:
|
||||||
|
*
|
||||||
|
* 1. Which interrupts are non-secure (ICDISR).
|
||||||
|
* REVISIT: Which bit state corresponds to secure?
|
||||||
|
* 2. Trigger mode of the SPI (ICDICFR). All fields set to 11->Edge
|
||||||
|
* sensitive.
|
||||||
|
* 3. Innterrupt Clear-Enable (ICDICER)
|
||||||
|
* 4. Priority of the SPI using the priority set register (ICDIPR).
|
||||||
|
* Priority values are 8-bit unsigned binary. A GIC supports a
|
||||||
|
* minimum of 16 and a maximum of 256 priority levels. Here all
|
||||||
|
* are set to the middle priority 128 (0x80).
|
||||||
|
* 5. Target that receives the SPI interrupt (ICDIPTR). Set all to
|
||||||
|
* CPU0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Enable GIC distributor */
|
||||||
|
putreg32(0x3, GIC_ICDDCR);
|
||||||
|
|
||||||
|
/* Registers with 1-bit per interrupt */
|
||||||
|
|
||||||
|
for (irq = GIC_IRQ_SPI; irq < nlines; irq += 32)
|
||||||
|
{
|
||||||
|
putreg32(0x00000000, GIC_ICDISR(irq)); /* SPIs secure */
|
||||||
|
putreg32(0x55555555, GIC_ICDICFR(irq)); /* SPIs level triggered */
|
||||||
|
putreg32(0x55555555, GIC_ICDICFR((irq + 16))); /* SPIs level triggered */
|
||||||
|
putreg32(0xffffffff, GIC_ICDICER(irq)); /* SPIs disabled */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Registers with 8-bits per interrupt */
|
||||||
|
|
||||||
|
for (irq = GIC_IRQ_SPI; irq < nlines; irq += 4)
|
||||||
|
{
|
||||||
|
putreg32(0x80808080, GIC_ICDIPR(irq)); /* SPI priority */
|
||||||
|
putreg32(0x01010101, GIC_ICDIPTR(irq)); /* SPI on CPU0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
/* Attach SGI interrupt handlers */
|
||||||
|
|
||||||
|
DEBUGVERIFY(irq_attach(GIC_IRQ_SGI1, arm_start_handler, NULL));
|
||||||
|
DEBUGVERIFY(irq_attach(GIC_IRQ_SGI2, arm_pause_handler, NULL));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_gic_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform common GIC initialization for the current CPU (all CPUs)
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm_gic_initialize(void)
|
||||||
|
{
|
||||||
|
uint32_t iccicr;
|
||||||
|
|
||||||
|
/* Initialize PPIs. The following steps need to be done by all CPUs */
|
||||||
|
|
||||||
|
/* Initialize SGIs and PPIs. NOTE: A processor in non-secure state cannot
|
||||||
|
* program its interrupt security registers and must get a secure processor
|
||||||
|
* to program the registers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Registers with 1-bit per interrupt */
|
||||||
|
|
||||||
|
putreg32(0x00000000, GIC_ICDISR(0)); /* SGIs and PPIs secure */
|
||||||
|
putreg32(0xf8000000, GIC_ICDICER(0)); /* PPIs disabled */
|
||||||
|
|
||||||
|
/* Registers with 8-bits per interrupt */
|
||||||
|
|
||||||
|
putreg32(0x80808080, GIC_ICDIPR(0)); /* SGI[3:0] priority */
|
||||||
|
putreg32(0x80808080, GIC_ICDIPR(4)); /* SGI[4:7] priority */
|
||||||
|
putreg32(0x80808080, GIC_ICDIPR(8)); /* SGI[8:11] priority */
|
||||||
|
putreg32(0x80808080, GIC_ICDIPR(12)); /* SGI[12:15] priority */
|
||||||
|
putreg32(0x80000000, GIC_ICDIPR(24)); /* PPI[0] priority */
|
||||||
|
putreg32(0x80808080, GIC_ICDIPR(28)); /* PPI[1:4] priority */
|
||||||
|
|
||||||
|
/* Set the binary point register.
|
||||||
|
*
|
||||||
|
* Priority values are 8-bit unsigned binary. The binary point is a 3-bit
|
||||||
|
* field; the value n (n=0-6) specifies that bits (n+1) through bit 7 are
|
||||||
|
* used in the comparison for interrupt pre-emption. A GIC supports a
|
||||||
|
* minimum of 16 and a maximum of 256 priority levels so not all binary
|
||||||
|
* point settings may be meaningul. The special value n=7 (GIC_ICCBPR_NOPREMPT)
|
||||||
|
* disables pre-emption. We disable all pre-emption here to prevent nesting
|
||||||
|
* of interrupt handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(GIC_ICCBPR_NOPREMPT, GIC_ICCBPR);
|
||||||
|
|
||||||
|
/* Program the idle priority in the PMR */
|
||||||
|
|
||||||
|
putreg32(GIC_ICCPMR_MASK, GIC_ICCPMR);
|
||||||
|
|
||||||
|
/* Configure the CPU Interface Control Register */
|
||||||
|
|
||||||
|
iccicr = getreg32(GIC_ICCICR);
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) || defined(CONFIG_ARCH_TRUSTZONE_BOTH)
|
||||||
|
/* Clear secure state ICCICR bits to be configured below */
|
||||||
|
|
||||||
|
iccicr &= ~(GIC_ICCICRS_FIQEN | GIC_ICCICRS_ACKTCTL | GIC_ICCICRS_CBPR | GIC_ICCICRS_EOIMODES | GIC_ICCICRS_EOIMODENS | GIC_ICCICRS_ENABLEGRP0 | GIC_ICCICRS_ENABLEGRP1 | GIC_ICCICRS_FIQBYPDISGRP0 | GIC_ICCICRS_IRQBYPDISGRP0 | GIC_ICCICRS_FIQBYPDISGRP1 | GIC_ICCICRS_IRQBYPDISGRP1);
|
||||||
|
|
||||||
|
#elif defined(CONFIG_ARCH_TRUSTZONE_NONSECURE)
|
||||||
|
/* Clear non-secure state ICCICR bits to be configured below */
|
||||||
|
|
||||||
|
iccicr &= ~(GIC_ICCICRS_EOIMODENS | GIC_ICCICRU_ENABLEGRP1 | GIC_ICCICRU_FIQBYPDISGRP1 | GIC_ICCICRU_IRQBYPDISGRP1);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) || defined(CONFIG_ARCH_TRUSTZONE_BOTH)
|
||||||
|
/* Set FIQn=1 if secure interrupts are to signal using nfiq_c.
|
||||||
|
*
|
||||||
|
* NOTE: Only for processors that operate in secure state.
|
||||||
|
* REVISIT: Do I need to do this?
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= GIC_ICCICRS_FIQEN;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ONFIG_ARCH_TRUSTZONE_BOTH)
|
||||||
|
/* Program the AckCtl bit to select the required interrupt acknowledge
|
||||||
|
* behavior.
|
||||||
|
*
|
||||||
|
* NOTE: Only for processors that operate in both secure and non-secure
|
||||||
|
* state.
|
||||||
|
* REVISIT: I don't yet fully understand this setting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// iccicr |= GIC_ICCICRS_ACKTCTL;
|
||||||
|
|
||||||
|
/* Program the SBPR bit to select the required binary pointer behavior.
|
||||||
|
*
|
||||||
|
* NOTE: Only for processors that operate in both secure and non-secure
|
||||||
|
* state.
|
||||||
|
* REVISIT: I don't yet fully understand this setting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// iccicr |= GIC_ICCICRS_CBPR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_TRUSTZONE_SECURE) || defined(CONFIG_ARCH_TRUSTZONE_BOTH)
|
||||||
|
/* Set EnableS=1 to enable CPU interface to signal secure interrupts.
|
||||||
|
*
|
||||||
|
* NOTE: Only for processors that operate in secure state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= GIC_ICCICRS_EOIMODES;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_TRUSTZONE_NONSECURE)
|
||||||
|
/* Set EnableNS=1 to enable the CPU to signal non-secure interrupts.
|
||||||
|
*
|
||||||
|
* NOTE: Only for processors that operate in non-secure state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= GIC_ICCICRS_EOIMODENS;
|
||||||
|
|
||||||
|
#elif defined(CONFIG_ARCH_TRUSTZONE_BOTH)
|
||||||
|
/* Set EnableNS=1 to enable the CPU to signal non-secure interrupts.
|
||||||
|
*
|
||||||
|
* NOTE: Only for processors that operate in non-secure state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= GIC_ICCICRU_EOIMODENS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TRUSTZONE_BOTH
|
||||||
|
/* If the processor operates in both security states and SBPR=0, then it
|
||||||
|
* must switch to the other security state and repeat the programming of
|
||||||
|
* the binary point register so that the binary point will be programmed
|
||||||
|
* for interrupts in both security states.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#warning Missing logic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(CONFIG_ARCH_HAVE_TRUSTZONE)
|
||||||
|
/* Enable the distributor by setting the the Enable bit in the enable
|
||||||
|
* register (no security extensions).
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= GIC_ICCICR_ENABLE;
|
||||||
|
|
||||||
|
#elif defined(CONFIG_ARCH_TRUSTZONE_SECURE)
|
||||||
|
/* Enable the Group 0 interrupts, FIQEn and disable Group 0/1
|
||||||
|
* bypass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= (GIC_ICCICRS_ENABLEGRP0 | GIC_ICCICRS_FIQBYPDISGRP0 | GIC_ICCICRS_IRQBYPDISGRP0 | GIC_ICCICRS_FIQBYPDISGRP1 | GIC_ICCICRS_IRQBYPDISGRP1);
|
||||||
|
|
||||||
|
#elif defined(CONFIG_ARCH_TRUSTZONE_BOTH)
|
||||||
|
/* Enable the Group 0/1 interrupts, FIQEn and disable Group 0/1
|
||||||
|
* bypass.
|
||||||
|
*/
|
||||||
|
|
||||||
|
iccicr |= (GIC_ICCICRS_ENABLEGRP0 | GIC_ICCICRS_ENABLEGRP1 | GIC_ICCICRS_FIQBYPDISGRP0 | GIC_ICCICRS_IRQBYPDISGRP0 | GIC_ICCICRS_FIQBYPDISGRP1 | GIC_ICCICRS_IRQBYPDISGRP1);
|
||||||
|
|
||||||
|
#else /* defined(CONFIG_ARCH_TRUSTZONE_NONSECURE) */
|
||||||
|
/* Enable the Group 1 interrupts and disable Group 1 bypass. */
|
||||||
|
|
||||||
|
iccicr |= (GIC_ICCICRU_ENABLEGRP1 | GIC_ICCICRU_FIQBYPDISGRP1 | GIC_ICCICRU_IRQBYPDISGRP1);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Write the final ICCICR value */
|
||||||
|
|
||||||
|
putreg32(GIC_ICCICR_ENABLE, GIC_ICCICR);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TRUSTZONE_BOTH
|
||||||
|
/* A processor in the secure state must then switch to the non-secure
|
||||||
|
* a repeat setting of the enable bit in the enable register. This
|
||||||
|
* enables distributor to respond to interrupt in both security states.
|
||||||
|
* REVISIT: Initial implementation operates only in secure state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#warning Missing logic
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_decodeirq
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function is called from the IRQ vector handler in arm_vectors.S.
|
||||||
|
* At this point, the interrupt has been taken and the registers have
|
||||||
|
* been saved on the stack. This function simply needs to determine the
|
||||||
|
* the irq number of the interrupt and then to call arm_doirq to dispatch
|
||||||
|
* the interrupt.
|
||||||
|
*
|
||||||
|
* Input parameters:
|
||||||
|
* regs - A pointer to the register save area on the stack.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
uint32_t *arm_decodeirq(uint32_t *regs)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
int irq;
|
||||||
|
|
||||||
|
/* Read the interrupt acknowledge register and get the interrupt ID */
|
||||||
|
|
||||||
|
regval = getreg32(GIC_ICCIAR);
|
||||||
|
irq = (regval & GIC_ICCIAR_INTID_MASK) >> GIC_ICCIAR_INTID_SHIFT;
|
||||||
|
|
||||||
|
/* Ignore spurions IRQs. ICCIAR will report 1023 if there is no pending
|
||||||
|
* interrupt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DEBUGASSERT(irq < NR_IRQS || irq == 1023);
|
||||||
|
if (irq < NR_IRQS)
|
||||||
|
{
|
||||||
|
/* Dispatch the interrupt */
|
||||||
|
|
||||||
|
regs = arm_doirq(irq, regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write to the end-of-interrupt register */
|
||||||
|
|
||||||
|
putreg32(regval, GIC_ICCEOIR);
|
||||||
|
return regs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_enable_irq
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* On many architectures, there are three levels of interrupt enabling: (1)
|
||||||
|
* at the global level, (2) at the level of the interrupt controller,
|
||||||
|
* and (3) at the device level. In order to receive interrupts, they
|
||||||
|
* must be enabled at all three levels.
|
||||||
|
*
|
||||||
|
* This function implements enabling of the device specified by 'irq'
|
||||||
|
* at the interrupt controller level if supported by the architecture
|
||||||
|
* (up_irq_restore() supports the global level, the device level is hardware
|
||||||
|
* specific).
|
||||||
|
*
|
||||||
|
* Since this API is not supported on all architectures, it should be
|
||||||
|
* avoided in common implementations where possible.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void up_enable_irq(int irq)
|
||||||
|
{
|
||||||
|
/* Ignore invalid interrupt IDs. Also, in the Cortex-A9 MPCore, SGIs are
|
||||||
|
* always enabled. The corresponding bits in the ICDISERn are read as
|
||||||
|
* one, write ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (irq > GIC_IRQ_SGI15 && irq < NR_IRQS)
|
||||||
|
{
|
||||||
|
uintptr_t regaddr;
|
||||||
|
|
||||||
|
/* Write '1' to the corresponding bit in the distributor Interrupt
|
||||||
|
* Set-Enable Register (ICDISER)
|
||||||
|
*/
|
||||||
|
|
||||||
|
regaddr = GIC_ICDISER(irq);
|
||||||
|
putreg32(GIC_ICDISER_INT(irq), regaddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_disable_irq
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function implements disabling of the device specified by 'irq'
|
||||||
|
* at the interrupt controller level if supported by the architecture
|
||||||
|
* (up_irq_save() supports the global level, the device level is hardware
|
||||||
|
* specific).
|
||||||
|
*
|
||||||
|
* Since this API is not supported on all architectures, it should be
|
||||||
|
* avoided in common implementations where possible.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void up_disable_irq(int irq)
|
||||||
|
{
|
||||||
|
/* Ignore invalid interrupt IDs. Also, in the Cortex-A9 MPCore, SGIs are
|
||||||
|
* always enabled. The corresponding bits in the ICDISERn are read as
|
||||||
|
* one, write ignored.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (irq > GIC_IRQ_SGI15 && irq < NR_IRQS)
|
||||||
|
{
|
||||||
|
uintptr_t regaddr;
|
||||||
|
|
||||||
|
/* Write '1' to the corresponding bit in the distributor Interrupt
|
||||||
|
* Clear-Enable Register (ICDISER)
|
||||||
|
*/
|
||||||
|
|
||||||
|
regaddr = GIC_ICDICER(irq);
|
||||||
|
putreg32(GIC_ICDICER_INT(irq), regaddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: up_prioritize_irq
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Set the priority of an IRQ.
|
||||||
|
*
|
||||||
|
* Since this API is not supported on all architectures, it should be
|
||||||
|
* avoided in common implementations where possible.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int up_prioritize_irq(int irq, int priority)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(irq >= 0 && irq < NR_IRQS && priority >= 0 && priority <= 255);
|
||||||
|
|
||||||
|
/* Ignore invalid interrupt IDs */
|
||||||
|
|
||||||
|
if (irq >= 0 && irq < NR_IRQS)
|
||||||
|
{
|
||||||
|
uintptr_t regaddr;
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
/* Write the new priority to the corresponding field in the in the
|
||||||
|
* distributor Interrupt Priority Register (GIC_ICDIPR).
|
||||||
|
*/
|
||||||
|
|
||||||
|
regaddr = GIC_ICDIPR(irq);
|
||||||
|
regval = getreg32(regaddr);
|
||||||
|
regval &= ~GIC_ICDIPR_ID_MASK(irq);
|
||||||
|
regval |= GIC_ICDIPR_ID(irq, priority);
|
||||||
|
putreg32(regval, regaddr);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_cpu_sgi
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform a Software Generated Interrupt (SGI). If CONFIG_SMP is
|
||||||
|
* selected, then the SGI is sent to all CPUs specified in the CPU set.
|
||||||
|
* That set may include the current CPU.
|
||||||
|
*
|
||||||
|
* If CONFIG_SMP is not selected, the cpuset is ignored and SGI is sent
|
||||||
|
* only to the current CPU.
|
||||||
|
*
|
||||||
|
* Input Paramters
|
||||||
|
* sgi - The SGI interrupt ID (0-15)
|
||||||
|
* cpuset - The set of CPUs to receive the SGI
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* OK is always returned at present.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int arm_cpu_sgi(int sgi, unsigned int cpuset)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(cpuset) | GIC_ICDSGIR_TGTFILTER_LIST;
|
||||||
|
#else
|
||||||
|
regval = GIC_ICDSGIR_INTID(sgi) | GIC_ICDSGIR_CPUTARGET(0) | GIC_ICDSGIR_TGTFILTER_THIS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
putreg32(regval, GIC_ICDSGIR);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_ARMV7R_HAVE_GICv2 */
|
@ -190,6 +190,7 @@ __start:
|
|||||||
mov r0, #0
|
mov r0, #0
|
||||||
mcr CP15_BPIALL(r0) /* Invalidate entire branch prediction array */
|
mcr CP15_BPIALL(r0) /* Invalidate entire branch prediction array */
|
||||||
mcr CP15_ICIALLU(r0) /* Invalidate I-cache */
|
mcr CP15_ICIALLU(r0) /* Invalidate I-cache */
|
||||||
|
mcr CP15_DCIALLU(r0) /* Invalidate D-cache */
|
||||||
|
|
||||||
/* Configure the system control register (see sctrl.h) */
|
/* Configure the system control register (see sctrl.h) */
|
||||||
|
|
||||||
|
@ -131,9 +131,15 @@ void up_initial_state(struct tcb_s *tcb)
|
|||||||
|
|
||||||
#ifndef CONFIG_ARMV7R_DECODEFIQ
|
#ifndef CONFIG_ARMV7R_DECODEFIQ
|
||||||
|
|
||||||
cpsr |= (PSR_F_BIT | PSR_A_BIT | PSR_E_BIT);
|
cpsr |= PSR_F_BIT;
|
||||||
|
|
||||||
#endif /* !CONFIG_ARMV7R_DECODEFIQ */
|
#endif /* !CONFIG_ARMV7R_DECODEFIQ */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENDIAN_BIG
|
||||||
|
|
||||||
|
cpsr |= PSR_E_BIT;
|
||||||
|
|
||||||
|
#endif /* CONFIG_ENDIAN_BIG */
|
||||||
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||||
|
|
||||||
xcp->regs[REG_CPSR] = cpsr;
|
xcp->regs[REG_CPSR] = cpsr;
|
||||||
|
@ -151,7 +151,11 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
|
CURRENT_REGS[REG_PC] = (uint32_t)up_sigdeliver;
|
||||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT | PSR_A_BIT | PSR_E_BIT);
|
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENDIAN_BIG
|
||||||
|
CURRENT_REGS[REG_CPSR] |= PSR_E_BIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* And make sure that the saved context in the TCB is the same
|
/* And make sure that the saved context in the TCB is the same
|
||||||
* as the interrupt return context.
|
* as the interrupt return context.
|
||||||
@ -182,7 +186,11 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver;
|
||||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT | PSR_A_BIT | PSR_E_BIT);
|
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SVC | PSR_I_BIT | PSR_F_BIT);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ENDIAN_BIG
|
||||||
|
tcb->xcp.regs[REG_CPSR] |= PSR_E_BIT;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,5 +165,6 @@
|
|||||||
#define CP15_CNTVCT(r,n) _CP15(1, r, c14, c14, n) /* Virtual Count register */
|
#define CP15_CNTVCT(r,n) _CP15(1, r, c14, c14, n) /* Virtual Count register */
|
||||||
#define CP15_CNTP_CVAL(r,n) _CP15(2, r, c14, c14, n) /* PL1 Physical Timer CompareValue register */
|
#define CP15_CNTP_CVAL(r,n) _CP15(2, r, c14, c14, n) /* PL1 Physical Timer CompareValue register */
|
||||||
#define CP15_CNTV_CVAL(r,n) _CP15(3, r, c14, c14, n) /* Virtual Timer CompareValue register */
|
#define CP15_CNTV_CVAL(r,n) _CP15(3, r, c14, c14, n) /* Virtual Timer CompareValue register */
|
||||||
|
#define CP15_DCIALLU(r) _CP15(0, r, c15, c5, 0) /* Invalidate data cache */
|
||||||
|
|
||||||
#endif /* __ARCH_ARM_SRC_ARMV7_R_CP15_H */
|
#endif /* __ARCH_ARM_SRC_ARMV7_R_CP15_H */
|
||||||
|
634
arch/arm/src/armv7-r/gic.h
Normal file
634
arch/arm/src/armv7-r/gic.h
Normal file
@ -0,0 +1,634 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/armv7-r/gic.h
|
||||||
|
* Generic Interrupt Controller Version 2 Definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* Cortex??A9 MPCore, Revision: r4p1, Technical Reference Manual, ARM DDI
|
||||||
|
* 0407I (ID091612).
|
||||||
|
*
|
||||||
|
* Includes some removed registers from the r2p2 version as well. ARM DDI
|
||||||
|
* 0407F (ID050110)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ARM_SRC_ARMV7_R_GIC_H
|
||||||
|
#define __ARCH_ARM_SRC_ARMV7_R_GIC_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "nuttx/config.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "mpcore.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARMV7R_HAVE_GICv2
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
/* Generic indexing helpers *************************************************/
|
||||||
|
/* 1x32 bit field per register */
|
||||||
|
|
||||||
|
#define GIC_INDEX1(n) (n) /* 1 field per word */
|
||||||
|
#define GIC_OFFSET1(n) (GIC_INDEX1(n) << 2) /* 32-bit word offset */
|
||||||
|
#define GIC_SHIFT1(n) (0) /* No shift */
|
||||||
|
#define GIC_MASK1(n) (0xffffffff) /* Whole word */
|
||||||
|
|
||||||
|
/* 2x16 bit field per register */
|
||||||
|
|
||||||
|
#define GIC_INDEX2(n) (n >> 1) /* 2 fields per word */
|
||||||
|
#define GIC_OFFSET2(n) (GIC_INDEX2(n) << 2) /* 32-bit word offset */
|
||||||
|
#define GIC_SHIFT2(n) (((n) & 1) << 4) /* Shift 16-bits per field */
|
||||||
|
#define GIC_MASK2(n) (0xffff << GIC_SHIFT2(n)) /* 16-bit mask */
|
||||||
|
|
||||||
|
/* 4x8 bit field per register */
|
||||||
|
|
||||||
|
#define GIC_INDEX4(n) (n >> 2) /* 4 fields per word */
|
||||||
|
#define GIC_OFFSET4(n) (GIC_INDEX4(n) << 2) /* 32-bit word offset */
|
||||||
|
#define GIC_SHIFT4(n) (((n) & 3) << 3) /* Shift 8-bits per field */
|
||||||
|
#define GIC_MASK4(n) (0xff << GIC_SHIFT4(n)) /* 8-bit mask */
|
||||||
|
|
||||||
|
/* 8x4 bit field per register */
|
||||||
|
|
||||||
|
#define GIC_INDEX8(n) (n >> 3) /* 8 fields per word */
|
||||||
|
#define GIC_OFFSET8(n) (GIC_INDEX8(n) << 2) /* 32-bit word offset */
|
||||||
|
#define GIC_SHIFT8(n) (((n) & 7) << 2) /* Shift 4-bits per field */
|
||||||
|
#define GIC_MASK8(n) (15 << GIC_SHIFT8(n)) /* 4-bit mask */
|
||||||
|
|
||||||
|
/* 16x2 bit field per register */
|
||||||
|
|
||||||
|
#define GIC_INDEX16(n) (n >> 4) /* 16 fields per word */
|
||||||
|
#define GIC_OFFSET16(n) (GIC_INDEX16(n) << 2) /* 32-bit word offset */
|
||||||
|
#define GIC_SHIFT16(n) (((n) & 15) << 1) /* Shift 2-bits per field */
|
||||||
|
#define GIC_MASK16(n) (3 << GIC_SHIFT16(n)) /* 2-bit mask */
|
||||||
|
|
||||||
|
/* 32x1 bit field per register */
|
||||||
|
|
||||||
|
#define GIC_INDEX32(n) (n >> 5) /* 32 fields per word */
|
||||||
|
#define GIC_OFFSET32(n) (GIC_INDEX32(n) << 2) /* 32-bit word offset */
|
||||||
|
#define GIC_SHIFT32(n) ((n) & 31) /* Shift 1-bit per field */
|
||||||
|
#define GIC_MASK32(n) (1U << GIC_SHIFT32(n)) /* 1-bit mask */
|
||||||
|
|
||||||
|
/* GIC Register Offsets *****************************************************/
|
||||||
|
/* Interrupt Interface registers */
|
||||||
|
|
||||||
|
#define GIC_ICCICR_OFFSET 0x0000 /* CPU Interface Control Register */
|
||||||
|
#define GIC_ICCPMR_OFFSET 0x0004 /* Interrupt Priority Mask Register */
|
||||||
|
#define GIC_ICCBPR_OFFSET 0x0008 /* Binary point Register */
|
||||||
|
#define GIC_ICCIAR_OFFSET 0x000c /* Interrupt Acknowledge */
|
||||||
|
#define GIC_ICCEOIR_OFFSET 0x0010 /* End of interrupt */
|
||||||
|
#define GIC_ICCRPR_OFFSET 0x0014 /* Running interrupt */
|
||||||
|
#define GIC_ICCHPIR_OFFSET 0x0018 /* Highest pending interrupt */
|
||||||
|
#define GIC_ICCABPR_OFFSET 0x001c /* Aliased Non-secure Binary Point Register */
|
||||||
|
#define GIC_ICCIDR_OFFSET 0x00fc /* CPU Interface Implementer ID Register */
|
||||||
|
|
||||||
|
/* Distributor Registers */
|
||||||
|
|
||||||
|
#define GIC_ICDDCR_OFFSET 0x0000 /* Distributor Control Register */
|
||||||
|
#define GIC_ICDICTR_OFFSET 0x0004 /* Interrupt Controller Type Register */
|
||||||
|
#define GIC_ICDIIDR_OFFSET 0x0008 /* Distributor Implementer ID Register */
|
||||||
|
|
||||||
|
/* 0x000c-0x007c: Reserved */
|
||||||
|
/* Interrupt Security Registers: 0x0080-0x009c */
|
||||||
|
|
||||||
|
#define GIC_ICDISR_OFFSET(n) (0x0080 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* Interrupt Set-Enable Registers: 0x0100-0x011c */
|
||||||
|
|
||||||
|
#define GIC_ICDISER_OFFSET(n) (0x0100 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* Interrupt Clear-Enable Registers: 0x0180-0x019c */
|
||||||
|
|
||||||
|
#define GIC_ICDICER_OFFSET(n) (0x0180 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* Interrupt Set-Pending Registers: 0x0200-0x027c */
|
||||||
|
|
||||||
|
#define GIC_ICDISPR_OFFSET(n) (0x0200 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* Interrupt Clear-Pending Registers: 0x0280-0x02fc */
|
||||||
|
|
||||||
|
#define GIC_ICDICPR_OFFSET(n) (0x0280 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* Interrupt Active Bit Registers: 0x0300-0x31c */
|
||||||
|
|
||||||
|
#define GIC_ICDABR_OFFSET(n) (0x0300 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* 0x0380-0x03fc: Reserved */
|
||||||
|
/* Interrupt Priority Registers: 0x0400-0x04fc */
|
||||||
|
|
||||||
|
#define GIC_ICDIPR_OFFSET(n) (0x0400 + GIC_OFFSET4(n))
|
||||||
|
|
||||||
|
/* 0x0500-0x07fc: Reserved */
|
||||||
|
/* Interrupt Processor Target Registers: 0x0800-0x08fc */
|
||||||
|
|
||||||
|
#define GIC_ICDIPTR_OFFSET(n) (0x0800 + GIC_OFFSET4(n))
|
||||||
|
|
||||||
|
/* 0x0900-0x0bfc: Reserved */
|
||||||
|
/* Interrupt Configuration Registers: 0x0c00-0x0c3c */
|
||||||
|
|
||||||
|
#define GIC_ICDICFR_OFFSET(n) (0x0c00 + GIC_OFFSET16(n))
|
||||||
|
|
||||||
|
/* PPI Status Register: 0x0d00 */
|
||||||
|
|
||||||
|
#define GIC_ICDPPISR_OFFSET 0x0d00 /* PPI Status Register */
|
||||||
|
|
||||||
|
/* SPI Status Registers: 0x0d04-0x0d1c */
|
||||||
|
|
||||||
|
#define GIC_ICDSPISR_OFFSET(n) (0x0d04 + GIC_OFFSET32(n))
|
||||||
|
|
||||||
|
/* 0x0d80-0x0efc: Reserved */
|
||||||
|
/* Software Generated Interrupt Register: 0x0f00 */
|
||||||
|
|
||||||
|
#define GIC_ICDSGIR_OFFSET 0x0f00 /* Software Generated Interrupt Register */
|
||||||
|
|
||||||
|
/* 0x0f0c-0x0fcc: Reserved */
|
||||||
|
/* Peripheral Identification Registers: 0x0fd0-0xfe8 */
|
||||||
|
|
||||||
|
#define GIC_ICDPIDR_OFFSET(n) (0x0fd0 + ((n) << 2))
|
||||||
|
|
||||||
|
/* Component Identification Registers: 0x0ff0-0x0ffc */
|
||||||
|
|
||||||
|
#define GIC_ICDCIDR_OFFSET(n) (0x0ff0 + ((n) << 2))
|
||||||
|
|
||||||
|
/* 0x0f04-0x0ffc: Reserved */
|
||||||
|
|
||||||
|
/* GIC Register Addresses ***************************************************/
|
||||||
|
/* The Interrupt Controller is a single functional unit that is located in a
|
||||||
|
* Cortex-A9 MPCore design. There is one interrupt interface per Cortex-A9
|
||||||
|
* processor. Registers are memory mapped and accessed through a chip-
|
||||||
|
* specific private memory spaced (see mpcore.h).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Interrupt Interface registers */
|
||||||
|
|
||||||
|
#define GIC_ICCICR (MPCORE_ICC_VBASE+GIC_ICCICR_OFFSET)
|
||||||
|
#define GIC_ICCPMR (MPCORE_ICC_VBASE+GIC_ICCPMR_OFFSET)
|
||||||
|
#define GIC_ICCBPR (MPCORE_ICC_VBASE+GIC_ICCBPR_OFFSET)
|
||||||
|
#define GIC_ICCIAR (MPCORE_ICC_VBASE+GIC_ICCIAR_OFFSET)
|
||||||
|
#define GIC_ICCEOIR (MPCORE_ICC_VBASE+GIC_ICCEOIR_OFFSET)
|
||||||
|
#define GIC_ICCRPR (MPCORE_ICC_VBASE+GIC_ICCRPR_OFFSET)
|
||||||
|
#define GIC_ICCHPIR (MPCORE_ICC_VBASE+GIC_ICCHPIR_OFFSET)
|
||||||
|
#define GIC_ICCABPR (MPCORE_ICC_VBASE+GIC_ICCABPR_OFFSET)
|
||||||
|
#define GIC_ICCIDR (MPCORE_ICC_VBASE+GIC_ICCIDR_OFFSET)
|
||||||
|
|
||||||
|
/* Distributor Registers */
|
||||||
|
|
||||||
|
#define GIC_ICDDCR (MPCORE_ICD_VBASE+GIC_ICDDCR_OFFSET)
|
||||||
|
#define GIC_ICDICTR (MPCORE_ICD_VBASE+GIC_ICDICTR_OFFSET)
|
||||||
|
#define GIC_ICDIIDR (MPCORE_ICD_VBASE+GIC_ICDIIDR_OFFSET)
|
||||||
|
#define GIC_ICDISR(n) (MPCORE_ICD_VBASE+GIC_ICDISR_OFFSET(n))
|
||||||
|
#define GIC_ICDISER(n) (MPCORE_ICD_VBASE+GIC_ICDISER_OFFSET(n))
|
||||||
|
#define GIC_ICDICER(n) (MPCORE_ICD_VBASE+GIC_ICDICER_OFFSET(n))
|
||||||
|
#define GIC_ICDISPR(n) (MPCORE_ICD_VBASE+GIC_ICDISPR_OFFSET(n))
|
||||||
|
#define GIC_ICDICPR(n) (MPCORE_ICD_VBASE+GIC_ICDICPR_OFFSET(n))
|
||||||
|
#define GIC_ICDABR(n) (MPCORE_ICD_VBASE+GIC_ICDABR_OFFSET(n))
|
||||||
|
#define GIC_ICDIPR(n) (MPCORE_ICD_VBASE+GIC_ICDIPR_OFFSET(n))
|
||||||
|
#define GIC_ICDIPTR(n) (MPCORE_ICD_VBASE+GIC_ICDIPTR_OFFSET(n))
|
||||||
|
#define GIC_ICDICFR(n) (MPCORE_ICD_VBASE+GIC_ICDICFR_OFFSET(n))
|
||||||
|
#define GIC_ICDPPISR (MPCORE_ICD_VBASE+GIC_ICDPPISR_OFFSET)
|
||||||
|
#define GIC_ICDSPISR(n) (MPCORE_ICD_VBASE+GIC_ICDSPISR_OFFSET(n))
|
||||||
|
#define GIC_ICDSGIR (MPCORE_ICD_VBASE+GIC_ICDSGIR_OFFSET)
|
||||||
|
#define GIC_ICDPIDR(n) (MPCORE_ICD_VBASE+GIC_ICDPIDR_OFFSET(n))
|
||||||
|
#define GIC_ICDCIDR(n) (MPCORE_ICD_VBASE+GIC_ICDCIDR_OFFSET(n))
|
||||||
|
|
||||||
|
/* GIC Register Bit Definitions *********************************************/
|
||||||
|
|
||||||
|
/* Interrupt Interface registers */
|
||||||
|
/* CPU Interface Control Register -- without security extensions */
|
||||||
|
|
||||||
|
#define GIC_ICCICR_ENABLE (1 << 0) /* Bit 0: Enable the CPU interface for this GIC */
|
||||||
|
/* Bits 1-31: Reserved */
|
||||||
|
/* CPU Interface Control Register -- with security extensions, non-secure copy */
|
||||||
|
|
||||||
|
#define GIC_ICCICRU_ENABLEGRP1 (1 << 0) /* Bit 0: Enable Group 1 interrupts for the CPU */
|
||||||
|
/* Bits 1-4: Reserved */
|
||||||
|
#define GIC_ICCICRU_FIQBYPDISGRP1 (1 << 5) /* Bit 5: FIQ disabled for CPU Group 1 */
|
||||||
|
#define GIC_ICCICRU_IRQBYPDISGRP1 (1 << 6) /* Bit 6: IRQ disabled for CPU Group 1 */
|
||||||
|
/* Bits 7-8: Reserved */
|
||||||
|
#define GIC_ICCICRU_EOIMODENS (1 << 9) /* Bit 9: Control EIOIR access (non-secure) */
|
||||||
|
/* Bits 10-31: Reserved */
|
||||||
|
/* CPU Interface Control Register -- with security extensions, secure copy */
|
||||||
|
|
||||||
|
#define GIC_ICCICRS_ENABLEGRP0 (1 << 0) /* Bit 0: Enable Group 0 interrupts for the CPU */
|
||||||
|
#define GIC_ICCICRS_ENABLEGRP1 (1 << 1) /* Bit 1: Enable Group 1 interrupts for the CPU */
|
||||||
|
#define GIC_ICCICRS_ACKTCTL (1 << 2) /* Bit 2: Group 1 interrupt activation control */
|
||||||
|
#define GIC_ICCICRS_FIQEN (1 << 3) /* Bit 3: Signal Group 0 via FIQ */
|
||||||
|
#define GIC_ICCICRS_CBPR (1 << 4) /* Bit 4: Control Group 0/1 Pre-emption */
|
||||||
|
#define GIC_ICCICRS_FIQBYPDISGRP0 (1 << 5) /* Bit 5: FIQ disabled for CPU Group 0 */
|
||||||
|
#define GIC_ICCICRS_IRQBYPDISGRP0 (1 << 6) /* Bit 6: IRQ disabled for CPU Group 0 */
|
||||||
|
#define GIC_ICCICRS_FIQBYPDISGRP1 (1 << 7) /* Bit 5: FIQ disabled for CPU Group 1 */
|
||||||
|
#define GIC_ICCICRS_IRQBYPDISGRP1 (1 << 8) /* Bit 6: IRQ disabled for CPU Group 1 */
|
||||||
|
#define GIC_ICCICRS_EOIMODES (1 << 9) /* Bit 6: Control EIOIR access (secure) */
|
||||||
|
#define GIC_ICCICRS_EOIMODENS (1 << 10) /* Bit 10: Control EIOIR access (non-secure) */
|
||||||
|
/* Bits 11-31: Reserved */
|
||||||
|
/* Interrupt Priority Mask Register. Priority values are 8-bit unsigned
|
||||||
|
* binary. A GIC supports a minimum of 16 and a maximum of 256 priority
|
||||||
|
* levels. As a result, PMR settings make sense.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GIC_ICCPMR_SHIFT (0) /* Bits 0-7: Priority mask */
|
||||||
|
#define GIC_ICCPMR_MASK (0xff << GIC_ICCPMR_SHIFT)
|
||||||
|
#define GIC_ICCPMR_VALUE(n) ((uint32_t)(n) << GIC_ICCPMR_SHIFT)
|
||||||
|
/* Bits 8-31: Reserved */
|
||||||
|
/* Binary point Register and Aliased Non-secure Binary Point Register.
|
||||||
|
* Priority values are 8-bit unsigned binary. A GIC supports a minimum of
|
||||||
|
* 16 and a maximum of 256 priority levels. As a result, not all binary
|
||||||
|
* point settings make sense.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GIC_ICCBPR_SHIFT (0) /* Bits 0-2: Binary point */
|
||||||
|
#define GIC_ICCBPR_MASK (7 << GIC_ICCBPR_SHIFT)
|
||||||
|
#define GIC_ICCBPR_1_7 (0 << GIC_ICCBPR_SHIFT) /* Priority bits [7:1] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_2_7 (1 << GIC_ICCBPR_SHIFT) /* Priority bits [7:2] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_3_7 (2 << GIC_ICCBPR_SHIFT) /* Priority bits [7:2] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_4_7 (3 << GIC_ICCBPR_SHIFT) /* Priority bits [7:2] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_5_7 (4 << GIC_ICCBPR_SHIFT) /* Priority bits [7:5] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_6_7 (5 << GIC_ICCBPR_SHIFT) /* Priority bits [7:6] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_7_7 (6 << GIC_ICCBPR_SHIFT) /* Priority bit [7] compared for pre-emption */
|
||||||
|
#define GIC_ICCBPR_NOPREMPT (7 << GIC_ICCBPR_SHIFT) /* No pre-emption is performed */
|
||||||
|
/* Bits 3-31: Reserved */
|
||||||
|
/* Interrupt Acknowledge Register */
|
||||||
|
|
||||||
|
#define GIC_ICCIAR_INTID_SHIFT (0) /* Bits 0-9: Interrupt ID */
|
||||||
|
#define GIC_ICCIAR_INTID_MASK (0x3ff << GIC_ICCIAR_INTID_SHIFT)
|
||||||
|
#define GIC_ICCIAR_INTID(n) ((uint32_t)(n) << GIC_ICCIAR_INTID_SHIFT)
|
||||||
|
#define GIC_ICCIAR_CPUSRC_SHIFT (10) /* Bits 10-12: CPU source ID */
|
||||||
|
#define GIC_ICCIAR_CPUSRC_MASK (7 << GIC_ICCIAR_CPUSRC_SHIFT)
|
||||||
|
#define GIC_ICCIAR_CPUSRC(n) ((uint32_t)(n) << GIC_ICCIAR_CPUSRC_SHIFT)
|
||||||
|
/* Bits 13-31: Reserved */
|
||||||
|
/* End of Interrupt Register */
|
||||||
|
|
||||||
|
#define GIC_ICCEOIR_SPURIOUS (0x3ff)
|
||||||
|
|
||||||
|
#define GIC_ICCEOIR_INTID_SHIFT (0) /* Bits 0-9: Interrupt ID */
|
||||||
|
#define GIC_ICCEOIR_INTID_MASK (0x3ff << GIC_ICCEOIR_INTID_SHIFT)
|
||||||
|
#define GIC_ICCEOIR_INTID(n) ((uint32_t)(n) << GIC_ICCEOIR_INTID_SHIFT)
|
||||||
|
#define GIC_ICCEOIR_CPUSRC_SHIFT (10) /* Bits 10-12: CPU source ID */
|
||||||
|
#define GIC_ICCEOIR_CPUSRC_MASK (7 << GIC_ICCEOIR_CPUSRC_SHIFT)
|
||||||
|
#define GIC_ICCEOIR_CPUSRC(n) ((uint32_t)(n) << GIC_ICCEOIR_CPUSRC_SHIFT)
|
||||||
|
/* Bits 13-31: Reserved */
|
||||||
|
/* Running Interrupt Register */
|
||||||
|
|
||||||
|
/* Bits 0-3: Reserved */
|
||||||
|
#define GIC_ICCRPR_PRIO_SHIFT (4) /* Bits 4-7: Priority mask */
|
||||||
|
#define GIC_ICCRPR_PRIO_MASK (15 << GIC_ICCRPR_PRIO_SHIFT)
|
||||||
|
#define GIC_ICCRPR_PRIO_VALUE(n) ((uint32_t)(n) << GIC_ICCRPR_PRIO_SHIFT)
|
||||||
|
/* Bits 8-31: Reserved */
|
||||||
|
/* Highest Pending Interrupt Register */
|
||||||
|
|
||||||
|
#define GIC_ICCHPIR_INTID_SHIFT (0) /* Bits 0-9: Interrupt ID */
|
||||||
|
#define GIC_ICCHPIR_INTID_MASK (0x3ff << GIC_ICCHPIR_INTID_SHIFT)
|
||||||
|
#define GIC_ICCHPIR_INTID(n) ((uint32_t)(n) << GIC_ICCHPIR_INTID_SHIFT)
|
||||||
|
#define GIC_ICCHPIR_CPUSRC_SHIFT (10) /* Bits 10-12: CPU source ID */
|
||||||
|
#define GIC_ICCHPIR_CPUSRC_MASK (7 << GIC_ICCHPIR_CPUSRC_SHIFT)
|
||||||
|
#define GIC_ICCHPIR_CPUSRC(n) ((uint32_t)(n) << GIC_ICCHPIR_CPUSRC_SHIFT)
|
||||||
|
/* Bits 13-31: Reserved */
|
||||||
|
|
||||||
|
/* CPU Interface Implementer ID Register */
|
||||||
|
|
||||||
|
#define GIC_ICCIDR_IMPL_SHIFT (0) /* Bits 0-11: Implementer */
|
||||||
|
#define GIC_ICCIDR_IMPL_MASK (0xfff << GIC_ICCIDR_IMPL_SHIFT)
|
||||||
|
#define GIC_ICCIDR_REVISION_SHIFT (12) /* Bits 12-15: Revision number */
|
||||||
|
#define GIC_ICCIDR_REVISION_MASK (15 << GIC_ICCIDR_REVISION_SHIFT)
|
||||||
|
#define GIC_ICCIDR_ARCHNO_SHIFT (16) /* Bits 16-19: Architecture number */
|
||||||
|
#define GIC_ICCIDR_ARCHNO_MASK (15 << GIC_ICCIDR_ARCHNO_SHIFT)
|
||||||
|
#define GIC_ICCIDR_PARTNO_SHIFT (20) /* Bits 20-31: Part number */
|
||||||
|
#define GIC_ICCIDR_PARTNO_MASK (0xfff << GIC_ICCIDR_PARTNO_SHIFT)
|
||||||
|
|
||||||
|
/* Distributor Registers */
|
||||||
|
/* Distributor Control Register */
|
||||||
|
|
||||||
|
#define GIC_ICDDCR_NONSECENAB (1 << 0) /* Bit 0: Enable distributor for Non-secure interrupts */
|
||||||
|
#define GIC_ICDDCR_SECENABLE (1 << 1) /* Bit 1: Enable distributor for Secure interrupts */
|
||||||
|
/* Bits 2-31: Reserved */
|
||||||
|
/* Interrupt Controller Type Register */
|
||||||
|
|
||||||
|
#define GIC_ICDICTR_ITLINES_SHIFT (0) /* Bits 0-4: It lines number */
|
||||||
|
#define GIC_ICDICTR_ITLINES_MASK (0x1f << GIC_ICDICTR_ITLINES_SHIFT)
|
||||||
|
#define GIC_ICDICTR_CPUNO_SHIFT (5) /* Bits 5-7: CPU number */
|
||||||
|
#define GIC_ICDICTR_CPUNO_MASK (7 << GIC_ICDICTR_CPUNO_SHIFT)
|
||||||
|
/* Bits 8-9: Reserved */
|
||||||
|
#define GIC_ICDICTR_SECEXTNS (1 << 10) /* Bit 10: Number of security domains */
|
||||||
|
#define GIC_ICDICTR_LSPI_SHIFT (11) /* Bits 11-15: Number of Lockable Shared Peripheral Interrupts */
|
||||||
|
#define GIC_ICDICTR_LSPI_MASK (0x1f << GIC_ICDICTR_LSPI_SHIFT)
|
||||||
|
/* Bits 16-31: Reserved */
|
||||||
|
/* Distributor Implementer ID Register */
|
||||||
|
|
||||||
|
#define GIC_ICDIIDR_IMPL_SHIFT (0) /* Bits 0-11: Implementer */
|
||||||
|
#define GIC_ICDIIDR_IMPL_MASK (0xfff << GIC_ICDIIDR_IMPL_SHIFT)
|
||||||
|
#define GIC_ICDIIDR_REVISION_SHIFT (12) /* Bits 12-23: Revision number */
|
||||||
|
#define GIC_ICDIIDR_REVISION_MASK (0xfff << GIC_ICDIIDR_REVISION_SHIFT)
|
||||||
|
#define GIC_ICDIIDR_VERSION_SHIFT (24) /* Bits 24-31: Iimplementer version */
|
||||||
|
#define GIC_ICDIIDR_VERSION_MASK (0xff << GIC_ICDIIDR_VERSION_SHIFT)
|
||||||
|
|
||||||
|
/* Interrupt Security Registers: 0x0080-0x009c */
|
||||||
|
|
||||||
|
#define GIC_ICDISR_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Interrupt Set-Enable.
|
||||||
|
*
|
||||||
|
* NOTE: In the Cortex-A9 MPCore, SGIs are always enabled. The corresponding bits
|
||||||
|
* in the ICDISERn are read as one, write ignored
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GIC_ICDISER_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Interrupt Clear-Enable.
|
||||||
|
*
|
||||||
|
* NOTE: In the Cortex-A9 MPCore, SGIs are always enabled. The corresponding bits
|
||||||
|
* in the ICDICERn are read as one, write ignored
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GIC_ICDICER_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Interrupt Set-Pending */
|
||||||
|
|
||||||
|
#define GIC_ICDISPR_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Interrupt Clear-Pending */
|
||||||
|
|
||||||
|
#define GIC_ICDICPR_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Interrupt Active Bit */
|
||||||
|
|
||||||
|
#define GIC_ICDABR_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Interrupt Priority Registers */
|
||||||
|
|
||||||
|
#define GIC_ICDIPR_ID_SHIFT(n) GIC_SHIFT4(n)
|
||||||
|
#define GIC_ICDIPR_ID_MASK(n) GIC_MASK4(n)
|
||||||
|
#define GIC_ICDIPR_ID(n, p) ((uint32_t)(p) << GIC_SHIFT4(n))
|
||||||
|
|
||||||
|
/* Interrupt Processor Target Registers */
|
||||||
|
|
||||||
|
#define CPU0_TARGET (1 << 0)
|
||||||
|
#define CPU1_TARGET (1 << 1)
|
||||||
|
#define CPU2_TARGET (1 << 2)
|
||||||
|
#define CPU3_TARGET (1 << 3)
|
||||||
|
|
||||||
|
#define GIC_ICDIPTR_ID_SHIFT(n) GIC_SHIFT4(n)
|
||||||
|
#define GIC_ICDIPTR_ID_MASK(n) GIC_MASK4(n)
|
||||||
|
#define GIC_ICDIPTR_ID(n, t) ((uint32_t)(t) <<GIC_SHIFT4(n))
|
||||||
|
|
||||||
|
/* Interrupt Configuration Register */
|
||||||
|
|
||||||
|
#define INT_ICDICFR_NN 0 /* Bit n: 0= N-N Model */
|
||||||
|
#define INT_ICDICFR_1N 1 /* Bit n: 1= 1-N Model */
|
||||||
|
#define INT_ICDICFR_LEVEL 0 /* Bit n+1: 0=Level sensitive */
|
||||||
|
#define INT_ICDICFR_EDGE 2 /* Bit n+2: 1=Edge sensitive */
|
||||||
|
|
||||||
|
#define GIC_ICDICFR_ID_SHIFT(n) GIC_SHIFT16(n)
|
||||||
|
#define GIC_ICDICFR_ID_MASK(n) GIC_MASK16(n)
|
||||||
|
#define GIC_ICDICFR_ID(n, c) ((uint32_t)(c) << GIC_SHIFT16(n))
|
||||||
|
|
||||||
|
/* PPI Status Register */
|
||||||
|
|
||||||
|
#define GIC_ICDPPISR_PPI(n) (1 << ((n) + 11)) /* Bits 11-15: PPI(n) status, n=0-4 */
|
||||||
|
#define GIC_ICDPPISR_GTM (1 << 11) /* Bit 11: PPI[0], Global Timer */
|
||||||
|
#define GIC_ICDPPISR_NFIQ (1 << 12) /* Bit 12: PPI[1], FIQ, active low */
|
||||||
|
#define GIC_ICDPPISR_PTM (1 << 13) /* Bit 13: PPI[2], Private Timer */
|
||||||
|
#define GIC_ICDPPISR_PWDT (1 << 14) /* Bit 14: PPI[3], Private Watchdog */
|
||||||
|
#define GIC_ICDPPISR_NIRQ (1 << 15) /* Bit 15: PPI[3], IRQ, active low */
|
||||||
|
|
||||||
|
/* SPI Status Registers */
|
||||||
|
|
||||||
|
#define GIC_ICDSPISR_INT(n) GIC_MASK32(n)
|
||||||
|
|
||||||
|
/* Software Generated Interrupt Register */
|
||||||
|
|
||||||
|
#define GIC_ICDSGIR_INTID_SHIFT (0) /* Bits 0-9: Interrupt ID */
|
||||||
|
#define GIC_ICDSGIR_INTID_MASK (0x3ff << GIC_ICDSGIR_INTID_SHIFT)
|
||||||
|
#define GIC_ICDSGIR_INTID(n) ((uint32_t)(n) << GIC_ICDSGIR_INTID_SHIFT)
|
||||||
|
/* Bits 10-15: Reserved */
|
||||||
|
#define GIC_ICDSGIR_CPUTARGET_SHIFT (16) /* Bits 16-23: CPU target */
|
||||||
|
#define GIC_ICDSGIR_CPUTARGET_MASK (0xff << GIC_ICDSGIR_CPUTARGET_SHIFT)
|
||||||
|
#define GIC_ICDSGIR_CPUTARGET(n) ((uint32_t)(n) << GIC_ICDSGIR_CPUTARGET_SHIFT)
|
||||||
|
/* Bits 26-31: Reserved */
|
||||||
|
#define GIC_ICDSGIR_TGTFILTER_SHIFT (24) /* Bits 24-25: Target filter */
|
||||||
|
#define GIC_ICDSGIR_TGTFILTER_MASK (3 << GIC_ICDSGIR_TGTFILTER_SHIFT)
|
||||||
|
#define GIC_ICDSGIR_TGTFILTER_LIST (0 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* Interrupt sent to CPUs CPU target list */
|
||||||
|
#define GIC_ICDSGIR_TGTFILTER_OTHER (1 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* Interrupt is sent to all but requesting CPU */
|
||||||
|
#define GIC_ICDSGIR_TGTFILTER_THIS (2 << GIC_ICDSGIR_TGTFILTER_SHIFT) /* Interrupt is sent to requesting CPU only */
|
||||||
|
|
||||||
|
/* Interrupt IDs ************************************************************/
|
||||||
|
/* The Global Interrupt Controller (GIC) collects up to 224 interrupt
|
||||||
|
* requests and provides a memory mapped interface to each of the CPU core.
|
||||||
|
*
|
||||||
|
* The first 32 interrupts are used for interrupts that are private to the
|
||||||
|
* CPUs interface. Other shared interrupts besides the also hooked up to
|
||||||
|
* the GIC in the same order. The shared interrupt sources are MCU-
|
||||||
|
* specific and documented in MCU-specific header files.
|
||||||
|
*
|
||||||
|
* Each interrupt can be configured as a normal or a secure interrupt.
|
||||||
|
* Software force registers and software priority masking are also
|
||||||
|
* supported. The following table describes the private RM interrupt
|
||||||
|
* sources.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Private Peripheral Interrupts (PPI) **************************************/
|
||||||
|
/* Each Cortex-A9 processor has private interrupts, ID0-ID15, that can only
|
||||||
|
* be triggered by software. These interrupts are aliased so that there is
|
||||||
|
* no requirement for a requesting Cortex-A9 processor to determine its own
|
||||||
|
* CPU ID when it deals with SGIs. The priority of an SGI depends on the
|
||||||
|
* value set by the receiving Cortex-A9 processor in the banked SGI priority
|
||||||
|
* registers, not the priority set by the sending Cortex-A9 processor.
|
||||||
|
*
|
||||||
|
* NOTE: If CONFIG_SMP is enabled then SGI1 and SGI2 are used for inter-CPU
|
||||||
|
* task management.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GIC_IRQ_SGI0 0 /* Sofware Generated Interrupt (SGI) 0 */
|
||||||
|
#define GIC_IRQ_SGI1 1 /* Sofware Generated Interrupt (SGI) 1 */
|
||||||
|
#define GIC_IRQ_SGI2 2 /* Sofware Generated Interrupt (SGI) 2 */
|
||||||
|
#define GIC_IRQ_SGI3 3 /* Sofware Generated Interrupt (SGI) 3 */
|
||||||
|
#define GIC_IRQ_SGI4 4 /* Sofware Generated Interrupt (SGI) 4 */
|
||||||
|
#define GIC_IRQ_SGI5 5 /* Sofware Generated Interrupt (SGI) 5 */
|
||||||
|
#define GIC_IRQ_SGI6 6 /* Sofware Generated Interrupt (SGI) 6 */
|
||||||
|
#define GIC_IRQ_SGI7 7 /* Sofware Generated Interrupt (SGI) 7 */
|
||||||
|
#define GIC_IRQ_SGI8 8 /* Sofware Generated Interrupt (SGI) 8 */
|
||||||
|
#define GIC_IRQ_SGI9 9 /* Sofware Generated Interrupt (SGI) 9 */
|
||||||
|
#define GIC_IRQ_SGI10 10 /* Sofware Generated Interrupt (SGI) 10 */
|
||||||
|
#define GIC_IRQ_SGI11 11 /* Sofware Generated Interrupt (SGI) 11 */
|
||||||
|
#define GIC_IRQ_SGI12 12 /* Sofware Generated Interrupt (SGI) 12 */
|
||||||
|
#define GIC_IRQ_SGI13 13 /* Sofware Generated Interrupt (SGI) 13 */
|
||||||
|
#define GIC_IRQ_SGI14 14 /* Sofware Generated Interrupt (SGI) 14 */
|
||||||
|
#define GIC_IRQ_SGI15 15 /* Sofware Generated Interrupt (SGI) 15 */
|
||||||
|
|
||||||
|
#define GIC_IRQ_GTM 27 /* Global Timer (GTM) PPI(0) */
|
||||||
|
#define GIC_IRQ_FIQ 28 /* Fast Interrupt Request (nFIQ) PPI(1) */
|
||||||
|
#define GIC_IRQ_PTM 29 /* Private Timer (PTM) PPI(2) */
|
||||||
|
#define GIC_IRQ_WDT 30 /* Watchdog Timer (WDT) PPI(3) */
|
||||||
|
#define GIC_IRQ_IRQ 31 /* Interrupt Request (nIRQ) PPI(4) */
|
||||||
|
|
||||||
|
/* Shared Peripheral Interrupts (SPI) follow */
|
||||||
|
|
||||||
|
#define GIC_IRQ_SPI 32 /* First SPI interrupt ID */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EXTERN extern "C"
|
||||||
|
extern "C" {
|
||||||
|
#else
|
||||||
|
#define EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_gic0_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform common, one-time GIC initialization on CPU0 only. Both
|
||||||
|
* arm_gic0_initialize() must be called on CPU0; arm_gic_initialize() must
|
||||||
|
* be called for all CPUs.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm_gic0_initialize(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_gic_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform common GIC initialization for the current CPU (all CPUs)
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void arm_gic_initialize(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_decodeirq
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function is called from the IRQ vector handler in arm_vectors.S.
|
||||||
|
* At this point, the interrupt has been taken and the registers have
|
||||||
|
* been saved on the stack. This function simply needs to determine the
|
||||||
|
* the irq number of the interrupt and then to call arm_doirq to dispatch
|
||||||
|
* the interrupt.
|
||||||
|
*
|
||||||
|
* Input parameters:
|
||||||
|
* regs - A pointer to the register save area on the stack.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
uint32_t *arm_decodeirq(uint32_t *regs);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_cpu_sgi
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform a Software Generated Interrupt (SGI). If CONFIG_SMP is
|
||||||
|
* selected, then the SGI is sent to all CPUs specified in the CPU set.
|
||||||
|
* That set may include the current CPU.
|
||||||
|
*
|
||||||
|
* If CONFIG_SMP is not selected, the cpuset is ignored and SGI is sent
|
||||||
|
* only to the current CPU.
|
||||||
|
*
|
||||||
|
* Input Paramters
|
||||||
|
* sgi - The SGI interrupt ID (0-15)
|
||||||
|
* cpuset - The set of CPUs to receive the SGI
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* OK is always retured at present.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int arm_cpu_sgi(int sgi, unsigned int cpuset);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_start_handler
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This is the handler for SGI1. This handler simply returns from the
|
||||||
|
* interrupt, restoring the state of the new task at the head of the ready
|
||||||
|
* to run list.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* Standard interrupt handling
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
int arm_start_handler(int irq, FAR void *context, FAR void *arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arm_pause_handler
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This is the handler for SGI2. It performs the following operations:
|
||||||
|
*
|
||||||
|
* 1. It saves the current task state at the head of the current assigned
|
||||||
|
* task list.
|
||||||
|
* 2. It waits on a spinlock, then
|
||||||
|
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||||
|
* head of the ready to run list.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* Standard interrupt handling
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
int arm_pause_handler(int irq, FAR void *context, FAR void *arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef EXTERN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
#endif /* CONFIG_ARMV7R_HAVE_GICv2 */
|
||||||
|
#endif /* __ARCH_ARM_SRC_ARMV7_R_GIC_H */
|
78
arch/arm/src/armv7-r/mpcore.h
Normal file
78
arch/arm/src/armv7-r/mpcore.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/arm/src/armv7-r/mpcore.h
|
||||||
|
* Generic Interrupt Controller Definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* Cortex™-A9 MPCore, Revision: r4p1, Technical Reference Manual, ARM DDI
|
||||||
|
* 0407I (ID091612).
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ARM_SRC_ARMV7_R_MPCORE_H
|
||||||
|
#define __ARCH_ARM_SRC_ARMV7_R_MPCORE_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "chip.h" /* For CHIP_MPCORE_VBASE */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* MPCore registers are memory mapped and accessed through a processor
|
||||||
|
* specific private address space via the SCU. The Cortex-A9 MCU chip.h
|
||||||
|
* header file must provide the definition CHIP_MPCORE_VBASE to access this
|
||||||
|
* the registers in this memory region.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Peripheral Base Offsets **************************************************/
|
||||||
|
|
||||||
|
#define MPCORE_SCU_OFFSET 0x0000 /* 0x0000-0x00fc SCU registers */
|
||||||
|
#define MPCORE_ICC_OFFSET 0x2000 /* 0x0000-0x00FC Interrupt conroller interface */
|
||||||
|
#define MPCORE_GTM_OFFSET 0x0200 /* 0x0200-0x02ff Global timer */
|
||||||
|
/* 0x0300-0x05ff Reserved */
|
||||||
|
#define MPCORE_PTM_OFFSET 0x0600 /* 0x0600-0x06ff Private timers and watchdogs */
|
||||||
|
/* 0x0700-0x07ff Reserved */
|
||||||
|
#define MPCORE_ICD_OFFSET 0x1000 /* 0x1000-0x1fff Interrupt Distributor */
|
||||||
|
|
||||||
|
/* Peripheral Base Addresses ************************************************/
|
||||||
|
|
||||||
|
#define MPCORE_SCU_VBASE (CHIP_MPCORE_VBASE+MPCORE_SCU_OFFSET)
|
||||||
|
#define MPCORE_ICC_VBASE (CHIP_MPCORE_VBASE+MPCORE_ICC_OFFSET)
|
||||||
|
#define MPCORE_GTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_GTM_OFFSET)
|
||||||
|
#define MPCORE_PTM_VBASE (CHIP_MPCORE_VBASE+MPCORE_PTM_OFFSET)
|
||||||
|
#define MPCORE_ICD_VBASE (CHIP_MPCORE_VBASE+MPCORE_ICD_OFFSET)
|
||||||
|
|
||||||
|
#endif /* __ARCH_ARM_SRC_ARMV7_R_MPCORE_H */
|
@ -66,9 +66,10 @@
|
|||||||
#define MPUIR_IREGION_SHIFT (16) /* Bits 16-23: Number MPU instruction regions */
|
#define MPUIR_IREGION_SHIFT (16) /* Bits 16-23: Number MPU instruction regions */
|
||||||
#define MPUIR_IREGION_MASK (0xff << MPUIR_IREGION_SHIFT)
|
#define MPUIR_IREGION_MASK (0xff << MPUIR_IREGION_SHIFT)
|
||||||
|
|
||||||
/* Region Base Address Register Definitions */
|
/* Region Base Address Register Definitions
|
||||||
|
* [31:5] Physical base address. Defines the base address of a region.
|
||||||
#define MPU_RBAR_ADDR_MASK 0xfffffffc
|
*/
|
||||||
|
#define MPU_RBAR_ADDR_MASK 0xffffffe0
|
||||||
|
|
||||||
/* Region Size and Enable Register */
|
/* Region Size and Enable Register */
|
||||||
|
|
||||||
@ -93,7 +94,7 @@
|
|||||||
#define MPU_RACR_B (1 << 0) /* Bit 0: Bufferable */
|
#define MPU_RACR_B (1 << 0) /* Bit 0: Bufferable */
|
||||||
#define MPU_RACR_C (1 << 1) /* Bit 1: Cacheable */
|
#define MPU_RACR_C (1 << 1) /* Bit 1: Cacheable */
|
||||||
#define MPU_RACR_S (1 << 2) /* Bit 2: Shareable */
|
#define MPU_RACR_S (1 << 2) /* Bit 2: Shareable */
|
||||||
#define MPU_RACR_TEX_SHIFT (8) /* Bits 0-2: Memory attributes (with C and B) */
|
#define MPU_RACR_TEX_SHIFT (3) /* Bits 3-5: Type extension */
|
||||||
#define MPU_RACR_TEX_MASK (7 << MPU_RACR_TEX_SHIFT)
|
#define MPU_RACR_TEX_MASK (7 << MPU_RACR_TEX_SHIFT)
|
||||||
# define MPU_RACR_TEX(n) ((uint32_t)(n) << MPU_RACR_TEX_SHIFT)
|
# define MPU_RACR_TEX(n) ((uint32_t)(n) << MPU_RACR_TEX_SHIFT)
|
||||||
#define MPU_RACR_AP_SHIFT (8) /* Bits 8-10: Access permission */
|
#define MPU_RACR_AP_SHIFT (8) /* Bits 8-10: Access permission */
|
||||||
@ -486,6 +487,52 @@ static inline void mpu_user_flash(uintptr_t base, size_t size)
|
|||||||
mpu_set_drsr(regval);
|
mpu_set_drsr(regval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_priv_noncache
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a non-cacheable region as privileged internal memory
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline void mpu_priv_noncache(uintptr_t base, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int region = mpu_allocregion();
|
||||||
|
uint32_t regval;
|
||||||
|
uint8_t l2size;
|
||||||
|
uint8_t subregions;
|
||||||
|
|
||||||
|
/* Select the region */
|
||||||
|
|
||||||
|
mpu_set_rgnr(region);
|
||||||
|
|
||||||
|
/* Select the region base address */
|
||||||
|
|
||||||
|
mpu_set_drbar(base & MPU_RBAR_ADDR_MASK);
|
||||||
|
|
||||||
|
/* Select the region size and the sub-region map */
|
||||||
|
|
||||||
|
l2size = mpu_log2regionceil(size);
|
||||||
|
subregions = mpu_subregion(base, size, l2size);
|
||||||
|
|
||||||
|
/* The configure the region
|
||||||
|
* inner/outer non-cache : TEX(4), C(0), B(0), S(1)
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = /* Not Cacheable */
|
||||||
|
/* Not Bufferable */
|
||||||
|
MPU_RACR_S | /* Shareable */
|
||||||
|
MPU_RACR_TEX(4) | /* TEX */
|
||||||
|
MPU_RACR_AP_RWRW | /* P:RO U:None */
|
||||||
|
MPU_RACR_XN; /* Instruction access disable */
|
||||||
|
mpu_set_dracr(regval);
|
||||||
|
|
||||||
|
regval = MPU_RASR_ENABLE | /* Enable region */
|
||||||
|
MPU_RASR_RSIZE_LOG2((uint32_t)l2size) | /* Region size */
|
||||||
|
((uint32_t)subregions << MPU_RASR_SRD_SHIFT); /* Sub-regions */
|
||||||
|
mpu_set_drsr(regval);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mpu_priv_flash
|
* Name: mpu_priv_flash
|
||||||
*
|
*
|
||||||
@ -734,6 +781,51 @@ static inline void mpu_peripheral(uintptr_t base, size_t size)
|
|||||||
mpu_set_drsr(regval);
|
mpu_set_drsr(regval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mpu_user_intsram_wb
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configure a region as user internal SRAM
|
||||||
|
* Unlike a mpu_user_intsram, this regions includes WB/WA cache policy
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline void mpu_user_intsram_wb(uintptr_t base, size_t size)
|
||||||
|
{
|
||||||
|
unsigned int region = mpu_allocregion();
|
||||||
|
uint32_t regval;
|
||||||
|
uint8_t l2size;
|
||||||
|
uint8_t subregions;
|
||||||
|
|
||||||
|
/* Select the region */
|
||||||
|
|
||||||
|
mpu_set_rgnr(region);
|
||||||
|
|
||||||
|
/* Select the region base address */
|
||||||
|
|
||||||
|
mpu_set_drbar(base & MPU_RBAR_ADDR_MASK);
|
||||||
|
|
||||||
|
/* Select the region size and the sub-region map */
|
||||||
|
|
||||||
|
l2size = mpu_log2regionceil(size);
|
||||||
|
subregions = mpu_subregion(base, size, l2size);
|
||||||
|
|
||||||
|
/* The configure the region
|
||||||
|
* WB/Write Allocate: TEX(5), C(0), B(1), S(1)
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = /* Not Cacheable */
|
||||||
|
MPU_RACR_B | /* Not Bufferable */
|
||||||
|
MPU_RACR_TEX(5) | /* TEX */
|
||||||
|
MPU_RACR_AP_RWRW; /* P:RW U:RW */
|
||||||
|
mpu_set_dracr(regval);
|
||||||
|
|
||||||
|
regval = MPU_RASR_ENABLE | /* Enable region */
|
||||||
|
MPU_RASR_RSIZE_LOG2((uint32_t)l2size) | /* Region size */
|
||||||
|
((uint32_t)subregions << MPU_RASR_SRD_SHIFT); /* Sub-regions */
|
||||||
|
mpu_set_drsr(regval);
|
||||||
|
}
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,8 @@
|
|||||||
#define SMART_WEAR_ZERO_MASK 0x0f
|
#define SMART_WEAR_ZERO_MASK 0x0f
|
||||||
#define SMART_WEAR_BLOCK_MASK 0x01
|
#define SMART_WEAR_BLOCK_MASK 0x01
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTD_SMART_WEAR_LEVEL
|
||||||
|
|
||||||
/* Bit mapping for wear level bits */
|
/* Bit mapping for wear level bits */
|
||||||
/* These are defined to allow updating the wear leveling with the minimum
|
/* These are defined to allow updating the wear leveling with the minimum
|
||||||
* number of sector relocations / maximum use of 1 --> 0 transitions when
|
* number of sector relocations / maximum use of 1 --> 0 transitions when
|
||||||
@ -184,6 +186,7 @@ static const uint8_t gWearBitToLevelMap4[] =
|
|||||||
7, 13, 10, 14, 6, 15, 5, 4,
|
7, 13, 10, 14, 6, 15, 5, 4,
|
||||||
3, 12, 9, 8, 2, 11, 1, 0
|
3, 12, 9, 8, 2, 11, 1, 0
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
|
Loading…
Reference in New Issue
Block a user