From d33b0640fe6c3ee88b8de77695d3e3f7eddfd436 Mon Sep 17 00:00:00 2001 From: EunBong Song Date: Wed, 29 Aug 2018 01:50:41 +0000 Subject: [PATCH] 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 * 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 * 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 * 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 * 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 Approved-by: GregoryN --- arch/arm/src/armv7-r/Kconfig | 7 + arch/arm/src/armv7-r/arm_gicv2.c | 529 ++++++++++++++++ arch/arm/src/armv7-r/arm_head.S | 1 + arch/arm/src/armv7-r/arm_initialstate.c | 8 +- arch/arm/src/armv7-r/arm_schedulesigaction.c | 12 +- arch/arm/src/armv7-r/cp15.h | 1 + arch/arm/src/armv7-r/gic.h | 634 +++++++++++++++++++ arch/arm/src/armv7-r/mpcore.h | 78 +++ arch/arm/src/armv7-r/mpu.h | 100 ++- drivers/mtd/smart.c | 3 + 10 files changed, 1366 insertions(+), 7 deletions(-) create mode 100644 arch/arm/src/armv7-r/arm_gicv2.c create mode 100644 arch/arm/src/armv7-r/gic.h create mode 100644 arch/arm/src/armv7-r/mpcore.h diff --git a/arch/arm/src/armv7-r/Kconfig b/arch/arm/src/armv7-r/Kconfig index f5ce353584a..da6cddaed1a 100644 --- a/arch/arm/src/armv7-r/Kconfig +++ b/arch/arm/src/armv7-r/Kconfig @@ -5,6 +5,13 @@ 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 bool default y if BOOT_SDRAM_DATA diff --git a/arch/arm/src/armv7-r/arm_gicv2.c b/arch/arm/src/armv7-r/arm_gicv2.c new file mode 100644 index 00000000000..f147481ad35 --- /dev/null +++ b/arch/arm/src/armv7-r/arm_gicv2.c @@ -0,0 +1,529 @@ +/**************************************************************************** + * arch/arm/src/armv7-r/arm_gicv2.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include + +#include +#include +#include +#include +#include + +#include + +#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 */ diff --git a/arch/arm/src/armv7-r/arm_head.S b/arch/arm/src/armv7-r/arm_head.S index 9042d25a439..391416e9926 100644 --- a/arch/arm/src/armv7-r/arm_head.S +++ b/arch/arm/src/armv7-r/arm_head.S @@ -190,6 +190,7 @@ __start: mov r0, #0 mcr CP15_BPIALL(r0) /* Invalidate entire branch prediction array */ mcr CP15_ICIALLU(r0) /* Invalidate I-cache */ + mcr CP15_DCIALLU(r0) /* Invalidate D-cache */ /* Configure the system control register (see sctrl.h) */ diff --git a/arch/arm/src/armv7-r/arm_initialstate.c b/arch/arm/src/armv7-r/arm_initialstate.c index 74b61fa71c8..708072a85e0 100644 --- a/arch/arm/src/armv7-r/arm_initialstate.c +++ b/arch/arm/src/armv7-r/arm_initialstate.c @@ -131,9 +131,15 @@ void up_initial_state(struct tcb_s *tcb) #ifndef CONFIG_ARMV7R_DECODEFIQ - cpsr |= (PSR_F_BIT | PSR_A_BIT | PSR_E_BIT); + cpsr |= PSR_F_BIT; #endif /* !CONFIG_ARMV7R_DECODEFIQ */ + +#ifdef CONFIG_ENDIAN_BIG + + cpsr |= PSR_E_BIT; + +#endif /* CONFIG_ENDIAN_BIG */ #endif /* CONFIG_SUPPRESS_INTERRUPTS */ xcp->regs[REG_CPSR] = cpsr; diff --git a/arch/arm/src/armv7-r/arm_schedulesigaction.c b/arch/arm/src/armv7-r/arm_schedulesigaction.c index 6491961647a..3752cc0e7d1 100644 --- a/arch/arm/src/armv7-r/arm_schedulesigaction.c +++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c @@ -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_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 * 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_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 } } diff --git a/arch/arm/src/armv7-r/cp15.h b/arch/arm/src/armv7-r/cp15.h index 99a841ffc54..883ac099ad5 100644 --- a/arch/arm/src/armv7-r/cp15.h +++ b/arch/arm/src/armv7-r/cp15.h @@ -165,5 +165,6 @@ #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_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 */ diff --git a/arch/arm/src/armv7-r/gic.h b/arch/arm/src/armv7-r/gic.h new file mode 100644 index 00000000000..2e6042bd481 --- /dev/null +++ b/arch/arm/src/armv7-r/gic.h @@ -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 + * + * 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 +#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) < + * + * 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 */ diff --git a/arch/arm/src/armv7-r/mpu.h b/arch/arm/src/armv7-r/mpu.h index 7c1a201567d..646e4875f6e 100644 --- a/arch/arm/src/armv7-r/mpu.h +++ b/arch/arm/src/armv7-r/mpu.h @@ -66,9 +66,10 @@ #define MPUIR_IREGION_SHIFT (16) /* Bits 16-23: Number MPU instruction regions */ #define MPUIR_IREGION_MASK (0xff << MPUIR_IREGION_SHIFT) -/* Region Base Address Register Definitions */ - -#define MPU_RBAR_ADDR_MASK 0xfffffffc +/* Region Base Address Register Definitions + * [31:5] Physical base address. Defines the base address of a region. + */ +#define MPU_RBAR_ADDR_MASK 0xffffffe0 /* Region Size and Enable Register */ @@ -93,7 +94,7 @@ #define MPU_RACR_B (1 << 0) /* Bit 0: Bufferable */ #define MPU_RACR_C (1 << 1) /* Bit 1: Cacheable */ #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(n) ((uint32_t)(n) << MPU_RACR_TEX_SHIFT) #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); } +/**************************************************************************** + * 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 * @@ -734,6 +781,51 @@ static inline void mpu_peripheral(uintptr_t base, size_t size) 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 #if defined(__cplusplus) } diff --git a/drivers/mtd/smart.c b/drivers/mtd/smart.c index fd89fb67c2b..a08842f2f1c 100644 --- a/drivers/mtd/smart.c +++ b/drivers/mtd/smart.c @@ -152,6 +152,8 @@ #define SMART_WEAR_ZERO_MASK 0x0f #define SMART_WEAR_BLOCK_MASK 0x01 +#ifdef CONFIG_MTD_SMART_WEAR_LEVEL + /* Bit mapping for wear level bits */ /* These are defined to allow updating the wear leveling with the minimum * 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, 3, 12, 9, 8, 2, 11, 1, 0 }; +#endif /**************************************************************************** * Private Types