You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2022/11/21 05:44:17 UTC

[incubator-nuttx] branch master updated: arch/arm64: Add support for Generic Interrupt Controller Version 2

This is an automated email from the ASF dual-hosted git repository.

btashton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 6aba739f05 arch/arm64: Add support for Generic Interrupt Controller Version 2
6aba739f05 is described below

commit 6aba739f0542993635aabf7716a60972bf099076
Author: Lee Lup Yuen <lu...@appkaki.com>
AuthorDate: Wed Nov 16 15:29:43 2022 +0800

    arch/arm64: Add support for Generic Interrupt Controller Version 2
    
    Currently NuttX on Arm64 supports Generic Interrupt Controller (GIC) Versions 3 and 4: [`arm64_gicv3.c`](https://github.com/apache/incubator-nuttx/blob/master/arch/arm64/src/common/arm64_gicv3.c), [`arm64_gic.h`](https://github.com/apache/incubator-nuttx/blob/master/arch/arm64/src/common/arm64_gic.h). This PR adds support for GIC Version 2, which is needed by [Pine64 PinePhone](https://lupyuen.github.io/articles/interrupt) based on Allwinner A64 SoC.
    
    This 64-bit implementation of GIC v2 is mostly identical to the existing GIC v2 for 32-bit Armv7-A ([`armv7-a/arm_gicv2.c`](https://github.com/apache/incubator-nuttx/blob/master/arch/arm/src/armv7-a/arm_gicv2.c), [`armv7-a/gic.h`](https://github.com/apache/incubator-nuttx/blob/master/arch/arm/src/armv7-a/gic.h)), with minor modifications to support 64-bit Registers (Interrupt Context).
    
    -   `arch/arm64/Kconfig`: Under "ARM64 Options", we added an integer option `ARM_GIC_VERSION` ("GIC version") that selects the GIC Version. Valid values are 2, 3 and 4, default is 3.
    
    -   `arch/arm64/src/common/arm64_gicv2.c`: Implements 64-bit GIC v2 based on 32-bit [`armv7-a/arm_gicv2.c`](https://github.com/apache/incubator-nuttx/blob/master/arch/arm/src/armv7-a/arm_gicv2.c) and [`armv7-a/gic.h`](https://github.com/apache/incubator-nuttx/blob/master/arch/arm/src/armv7-a/gic.h), modified to support 64-bit Registers (Interrupt Context).
    
        Function and Macro Names have not been changed, for easier cross-referencing between the 32-bit and 64-bit implementations of GIC v2.
    
    -   `arch/arm64/src/common/arm64_gicv3.c`: Added Conditional Compilation for GIC v3. This file will not be compiled if `ARM_GIC_VERSION` is 2.
    
    -   `arch/arm64/src/common/arm64_gic.h`: Added the Version Identifier for GIC v2. At startup we read the GIC Version from hardware and verify that it matches `ARM_GIC_VERSION`.
    
    -   `arch/arm64/include/qemu/chip.h`: Added the QEMU Base Addresses for GIC v2.
    
    -   `arch/arm64/src/common/Make.defs`: Added the source file that implements GIC v2.
    
    -   `boards/arm64/qemu/qemu-armv8a/README.txt`: Added the documentation for testing GIC v2 with QEMU.
    
    -   `boards/arm64/qemu/qemu-armv8a/configs/nsh_gicv2/defconfig`: Added the Board Configuration `qemu-armv8a:nsh_gicv2` for testing GIC v2 with QEMU. Identical to `qemu-armv8a:nsh`, except that `ARM_GIC_VERSION` is 2.
---
 arch/arm64/Kconfig                                 |    8 +
 arch/arm64/include/qemu/chip.h                     |   13 +
 arch/arm64/src/common/Make.defs                    |    2 +-
 arch/arm64/src/common/arm64_gic.h                  |    1 +
 arch/arm64/src/common/arm64_gicv2.c                | 1389 ++++++++++++++++++++
 arch/arm64/src/common/arm64_gicv3.c                |    4 +
 boards/arm64/qemu/qemu-armv8a/README.txt           |   21 +-
 .../qemu/qemu-armv8a/configs/nsh_gicv2/defconfig   |   66 +
 8 files changed, 1500 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 483f3f6073..cb74385bf4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -95,6 +95,14 @@ config ARM_HAVE_NEON
 	---help---
 		Decide whether support NEON instruction
 
+config ARM_GIC_VERSION
+	int "GIC version"
+	default 3
+	range 2 4
+	---help---
+		Version of Generic Interrupt Controller (GIC) supported by the
+		architecture
+
 if ARCH_CHIP_QEMU
 source "arch/arm64/src/qemu/Kconfig"
 endif
diff --git a/arch/arm64/include/qemu/chip.h b/arch/arm64/include/qemu/chip.h
index 745876852b..6b6cae7521 100644
--- a/arch/arm64/include/qemu/chip.h
+++ b/arch/arm64/include/qemu/chip.h
@@ -35,9 +35,22 @@
 
 #if defined(CONFIG_ARCH_CHIP_QEMU)
 
+#if CONFIG_ARM_GIC_VERSION == 2
+
+#define CONFIG_GICD_BASE          0x8000000
+#define CONFIG_GICR_BASE          0x8010000
+
+#elif CONFIG_ARM_GIC_VERSION == 3 || CONFIG_ARM_GIC_VERSION == 4
+
 #define CONFIG_GICD_BASE          0x8000000
 #define CONFIG_GICR_BASE          0x80a0000
 
+#else
+
+#error CONFIG_ARM_GIC_VERSION should be 2, 3 or 4
+
+#endif /* CONFIG_ARM_GIC_VERSION */
+
 #define CONFIG_RAMBANK1_ADDR      0x40000000
 #define CONFIG_RAMBANK1_SIZE      MB(128)
 
diff --git a/arch/arm64/src/common/Make.defs b/arch/arm64/src/common/Make.defs
index 4e4b1a3a76..515b85f793 100644
--- a/arch/arm64/src/common/Make.defs
+++ b/arch/arm64/src/common/Make.defs
@@ -52,7 +52,7 @@ CMN_CSRCS += arm64_sigdeliver.c
 
 # Common C source files ( hardware BSP )
 CMN_CSRCS += arm64_mmu.c arm64_arch_timer.c arm64_cache.c
-CMN_CSRCS += arm64_doirq.c arm64_gicv3.c arm64_fatal.c
+CMN_CSRCS += arm64_doirq.c arm64_gicv2.c arm64_gicv3.c arm64_fatal.c
 CMN_CSRCS += arm64_syscall.c arm64_cpu_psci.c
 
 # Use common heap allocation for now (may need to be customized later)
diff --git a/arch/arm64/src/common/arm64_gic.h b/arch/arm64/src/common/arm64_gic.h
index 496fa944a6..73fa4b4b68 100644
--- a/arch/arm64/src/common/arm64_gic.h
+++ b/arch/arm64/src/common/arm64_gic.h
@@ -99,6 +99,7 @@
  * [3:0] - IMPLEMENTATION DEFINED.
  */
 #define GICD_PIDR2_ARCH_MASK        0xf0
+#define GICD_PIDR2_ARCH_GICV2       0x20
 #define GICD_PIDR2_ARCH_GICV3       0x30
 #define GICD_PIDR2_ARCH_GICV4       0x40
 
diff --git a/arch/arm64/src/common/arm64_gicv2.c b/arch/arm64/src/common/arm64_gicv2.c
new file mode 100644
index 0000000000..7e1ce03e14
--- /dev/null
+++ b/arch/arm64/src/common/arm64_gicv2.c
@@ -0,0 +1,1389 @@
+/****************************************************************************
+ * arch/arm64/src/common/arm64_gicv2.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* 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)
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <arch/irq.h>
+
+#include "arm64_internal.h"
+#include "arm64_gic.h"
+
+#if CONFIG_ARM_GIC_VERSION == 2
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* GIC Distributor / Redistributor Register Interface Base Addresses */
+
+#define MPCORE_ICD_VBASE CONFIG_GICD_BASE
+#define MPCORE_ICC_VBASE CONFIG_GICR_BASE
+
+/* 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)              (1 << GIC_SHIFT32(n))     /* 1-bit mask */
+
+/* GIC Register Offsets *****************************************************/
+
+/* CPU 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_ICCAIAR_OFFSET         0x0020    /* Aliased Interrupt Acknowledge Register */
+#define GIC_ICCAEOIR_OFFSET        0x0024    /* Aliased End of Interrupt Register */
+#define GIC_ICCAHPIR_OFFSET        0x0028    /* Aliased Highest Priority Pending Interrupt Register */
+                                             /* 0x002c-0x003c: Reserved */
+                                             /* 0x0040-0x00cf: Implementation defined */
+#define GIC_ICCAPR1_OFFSET         0x00d0    /* Active Priorities Register 1 */
+#define GIC_ICCAPR2_OFFSET         0x00d4    /* Active Priorities Register 2 */
+#define GIC_ICCAPR3_OFFSET         0x00d8    /* Active Priorities Register 3 */
+#define GIC_ICCAPR4_OFFSET         0x00dc    /* Active Priorities Register 4 */
+#define GIC_ICCNSAPR1_OFFSET       0x00e0    /* Non-secure Active Priorities Register 1 */
+#define GIC_ICCNSAPR2_OFFSET       0x00e4    /* Non-secure Active Priorities Register 2 */
+#define GIC_ICCNSAPR3_OFFSET       0x00e8    /* Non-secure Active Priorities Register 3 */
+#define GIC_ICCNSAPR4_OFFSET       0x00ec    /* Non-secure Active Priorities Register 4 */
+                                             /* 0x00ed-0x00f8: Reserved */
+#define GIC_ICCIDR_OFFSET          0x00fc    /* CPU Interface Implementer ID Register */
+#define GIC_ICCDIR_OFFSET          0x1000    /* Deactivate Interrupt 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-0x001c: Reserved */
+                                             /* 0x0020-0x003c: Implementation defined */
+                                             /* 0x0040-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))
+
+/* GICv2 Interrupt Set-Active Registers: 0x0300-0x31c */
+
+#define GIC_ICDSAR_OFFSET(n)       (0x0300 + GIC_OFFSET32(n))
+
+/* Interrupt Clear-Active Registers: 0x380-0x3fc */
+
+#define GIC_ICDCAR_OFFSET(n)       (0x0380 + GIC_OFFSET32(n))
+
+/* 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))
+
+/* 0x0d00-0x0dfc: Implementation defined */
+
+/* PPI Status Register: 0x0d00 */
+
+/* SPI Status Registers: 0x0d04-0x0d1c */
+
+#define GIC_ICDPPISR_OFFSET        0x0d00    /* PPI Status Register */
+#define GIC_ICDSPISR_OFFSET(n)     (0x0d00 + GIC_OFFSET32(n))
+
+/* 0x0d80-0x0dfc: Reserved */
+
+/* Non-secure Access Control Registers, optional: 00xe00-0x0efc */
+
+#define GIC_ICDNSACR_OFFSET(n)     (0x0e00 + GIC_OFFSET32(n))
+
+/* Software Generated Interrupt Register: 0x0f00 */
+
+#define GIC_ICDSGIR_OFFSET         0x0f00    /* Software Generated Interrupt Register */
+
+/* 0x0f0c-0x0f0c: Reserved */
+
+/* Peripheral Identification Registers: 0x0fd0-0xfe8 */
+
+#define GIC_ICDPIDR_OFFSET(n)      (0x0fd0 + ((n) << 2))
+
+/* SGI Clear-Pending Registers: 0x0f10-0x0f1c */
+
+#define GIC_ICDSCPR_OFFSET(n)      (0x0f10 + GIC_OFFSET8(n))
+
+/* SGI Set-Pending Registers: 0x0f20-0x0f2c */
+
+#define GIC_ICDSSPR_OFFSET(n)      (0x0f20 + GIC_OFFSET8(n))
+
+/* 0x0f30-0x0fcc: Reserved */
+
+/* 0x0fd0-0x0ffc: Implementation defined */
+
+/* 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).
+ */
+
+/* CPU 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_ICCAIAR                (MPCORE_ICC_VBASE+GIC_ICCAIAR_OFFSET)
+#define GIC_ICCAEOIR               (MPCORE_ICC_VBASE+GIC_ICCAEOIR_OFFSET)
+#define GIC_ICCAHPIR               (MPCORE_ICC_VBASE+GIC_ICCAHPIR_OFFSET)
+#define GIC_ICCAPR1                (MPCORE_ICC_VBASE+GIC_ICCAPR1_OFFSET)
+#define GIC_ICCAPR2                (MPCORE_ICC_VBASE+GIC_ICCAPR2_OFFSET)
+#define GIC_ICCAPR3                (MPCORE_ICC_VBASE+GIC_ICCAPR3_OFFSET)
+#define GIC_ICCAPR4                (MPCORE_ICC_VBASE+GIC_ICCAPR4_OFFSET)
+#define GIC_ICCNSAPR1              (MPCORE_ICC_VBASE+GIC_ICCNSAPR1_OFFSET)
+#define GIC_ICCNSAPR2              (MPCORE_ICC_VBASE+GIC_ICCNSAPR2_OFFSET)
+#define GIC_ICCNSAPR3              (MPCORE_ICC_VBASE+GIC_ICCNSAPR3_OFFSET)
+#define GIC_ICCNSAPR4              (MPCORE_ICC_VBASE+GIC_ICCNSAPR4_OFFSET)
+#define GIC_ICCIDR                 (MPCORE_ICC_VBASE+GIC_ICCIDR_OFFSET)
+#define GIC_ICCDIR                 (MPCORE_ICC_VBASE+GIC_ICCDIR_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_ICDSAR(n)              (MPCORE_ICD_VBASE+GIC_ICDSAR_OFFSET(n))
+#define GIC_ICDCAR(n)              (MPCORE_ICD_VBASE+GIC_ICDCAR_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_ICDNSACR(n)            (MPCORE_ICD_VBASE+GIC_ICDNSACR_OFFSET(n))
+#define GIC_ICDSGIR                (MPCORE_ICD_VBASE+GIC_ICDSGIR_OFFSET)
+#define GIC_ICDPIDR(n)             (MPCORE_ICD_VBASE+GIC_ICDPIDR_OFFSET(n))
+#define GIC_ICDSCPR(n)             (MPCORE_ICD_VBASE+GIC_ICDSCPR_OFFSET(n))
+#define GIC_ICDSSPR(n)             (MPCORE_ICD_VBASE+GIC_ICDSSPR_OFFSET(n))
+#define GIC_ICDCIDR(n)             (MPCORE_ICD_VBASE+GIC_ICDCIDR_OFFSET(n))
+
+/* GIC Register Bit Definitions *********************************************/
+
+/* CPU 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 */
+
+/* Aliased Interrupt Acknowledge Register */
+#define GIC_ICCAIAR_
+
+/* Aliased End of Interrupt Register */
+#define GIC_ICCAEOIR_
+
+/* Aliased Highest Priority Pending Interrupt Register */
+#define GIC_ICCAHPIR_
+
+/* Active Priorities Register 1 */
+#define GIC_ICCAPR1_
+
+/* Active Priorities Register 2 */
+#define GIC_ICCAPR2_
+
+/* Active Priorities Register 3 */
+#define GIC_ICCAPR3_
+
+/* Active Priorities Register 4 */
+#define GIC_ICCAPR4_
+
+/* Non-secure Active Priorities Register 1 */
+#define GIC_ICCNSAPR1_
+
+/* Non-secure Active Priorities Register 2 */
+#define GIC_ICCNSAPR2_
+
+/* Non-secure Active Priorities Register 3 */
+#define GIC_ICCNSAPR3_
+
+/* Non-secure Active Priorities Register 4 */
+#define GIC_ICCNSAPR4_
+
+/* 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)
+
+/* Deactivate Interrupt Register */
+#define GIC_ICCDIR_
+
+/* Distributor Registers */
+
+/* Distributor Control Register -- without security extensions */
+
+#define GIC_ICDDCR_ENABLE          (1 << 0)  /* Bit 0: Enable forwarding of interrupts */
+                                             /* Bits 1-31: Reserved */
+
+/* Distributor Control Register -- with security extensions */
+
+#define GIC_ICDDCR_ENABLEGRP0      (1 << 0)  /* Bit 0: Enable forwarding of Group 0 interrupts */
+#define GIC_ICDDCR_ENABLEGRP1      (1 << 1)  /* Bit 1: Enable forwarding of Group 1 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)
+
+/* GICv2 Interrupt Set-Active Registers */
+
+#define GIC_ICDSAR_INT(n)          GIC_MASK32(n)
+
+/* Interrupt Clear-Active Registers */
+
+#define GIC_ICDCAR_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)
+
+/* Non-secure Access Control Registers, optional */
+
+#define GIC_ICDNSACR_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 */
+
+/* SGI Clear-Pending Registers */
+#define GIC_ICDSCPR_
+
+/* SGI Set-Pending Registers */
+#define GIC_ICDSSPR_
+
+/* Peripheral ID2 Register */
+#define GIC_ICPIDR2 (6)
+
+/* 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.
+ */
+
+/* Shared Peripheral Interrupts (SPI) */
+
+#define GIC_IRQ_SPI              32  /* First SPI interrupt ID */
+
+/****************************************************************************
+ * Private 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;
+}
+
+/****************************************************************************
+ * 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 Parameters:
+ *   sgi    - The SGI interrupt ID (0-15)
+ *   cpuset - The set of CPUs to receive the SGI
+ *
+ * Returned Value:
+ *   OK is always returned at present.
+ *
+ ****************************************************************************/
+
+static inline void 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);
+}
+
+/****************************************************************************
+ * Name: gic_validate_dist_version
+ *
+ * Description:
+ *   Verify that GIC Version is 2.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) if GIC Version is 2; -ENODEV if GIC Version isn't 2.
+ *
+ ****************************************************************************/
+
+static int gic_validate_dist_version(void)
+{
+  uint32_t  reg;
+
+  /* Read the Peripheral ID2 Register (ICPIDR2) */
+
+  reg = getreg32(GIC_ICDPIDR(GIC_ICPIDR2)) & GICD_PIDR2_ARCH_MASK;
+
+  /* GIC Version should be 2 */
+
+  if (reg == GICD_PIDR2_ARCH_GICV2)
+    {
+      sinfo("GICv2 detected\n");
+    }
+  else
+    {
+      sinfo("GICv2 not detected\n");
+      return -ENODEV;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: arm_gic_irq_trigger
+ *
+ * Description:
+ *   Set the trigger type for the specified IRQ source and the current CPU.
+ *
+ *   Since this API is not supported on all architectures, it should be
+ *   avoided in common implementations where possible.
+ *
+ * Input Parameters:
+ *   irq - The interrupt request to modify.
+ *   edge - False: Active HIGH level sensitive, True: Rising edge sensitive
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int arm_gic_irq_trigger(int irq, bool edge)
+{
+  uintptr_t regaddr;
+  uint32_t regval;
+  uint32_t intcfg;
+
+  if (irq > GIC_IRQ_SGI15 && irq < NR_IRQS)
+    {
+      /* Get the address of the Interrupt Configuration Register for this
+       * irq.
+       */
+
+      regaddr = GIC_ICDICFR(irq);
+
+      /* Get the new Interrupt configuration bit setting */
+
+      intcfg = (edge ? (INT_ICDICFR_EDGE | INT_ICDICFR_1N) : INT_ICDICFR_1N);
+
+      /* Write the correct interrupt trigger to the Interrupt Configuration
+       * Register.
+       */
+
+      regval  = getreg32(regaddr);
+      regval &= ~GIC_ICDICFR_ID_MASK(irq);
+      regval |= GIC_ICDICFR_ID(irq, intcfg);
+      putreg32(regval, regaddr);
+
+      return OK;
+    }
+
+  return -EINVAL;
+}
+
+/****************************************************************************
+ * 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
+ *
+ ****************************************************************************/
+
+static 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).  All set to zero (group
+   *    0).
+   * 2. Trigger mode of the SPI (ICDICFR). All fields set to 0b01->Level
+   *    sensitive, 1-N model.
+   * 3. Interrupt Clear-Enable (ICDICER)
+   * 3. 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).
+   * 4. Target that receives the SPI interrupt (ICDIPTR).  Set all to
+   *    CPU0.
+   */
+
+  /* Registers with 1-bit per interrupt */
+
+  for (irq = GIC_IRQ_SPI; irq < nlines; irq += 32)
+    {
+      putreg32(0x00000000, GIC_ICDISR(irq));   /* SPIs group 0 */
+      putreg32(0xffffffff, GIC_ICDICER(irq));  /* SPIs disabled */
+    }
+
+  /* Registers with 2-bits per interrupt */
+
+  for (irq = GIC_IRQ_SPI; irq < nlines; irq += 16)
+    {
+      putreg32(0x55555555, GIC_ICDICFR(irq));  /* SPIs level sensitive */
+    }
+
+  /* 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. This attaches the handler to all CPUs. */
+
+  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
+ *
+ ****************************************************************************/
+
+static void arm_gic_initialize(void)
+{
+  uint32_t iccicr;
+  uint32_t icddcr;
+
+  /* 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)
+  /* 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; */
+
+#elif 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(CONFIG_ARCH_TRUSTZONE_SECURE)
+  /* 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: This is here only for superstituous reasons.  I don't think
+   * I need this setting in this configuration.
+   */
+
+  iccicr |= GIC_ICCICRS_ACKTCTL;
+
+#elif defined(CONFIG_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.
+   */
+
+  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.
+   */
+
+  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 Enable bit in the enable
+   * register (no security extensions).
+   */
+
+  iccicr |= GIC_ICCICR_ENABLE;
+  icddcr  = GIC_ICDDCR_ENABLE;
+
+#elif defined(CONFIG_ARCH_TRUSTZONE_SECURE)
+  /* Enable the Group 0 interrupts, FIQEn and disable Group 0/1
+   * bypass.
+   */
+
+#if 0 /* REVISIT -- I don't know why this needs to be like this */
+  iccicr |= (GIC_ICCICRS_ENABLEGRP0 | GIC_ICCICRS_FIQBYPDISGRP0 |
+             GIC_ICCICRS_IRQBYPDISGRP0 | GIC_ICCICRS_FIQBYPDISGRP1 |
+             GIC_ICCICRS_IRQBYPDISGRP1);
+#else
+  iccicr |= (GIC_ICCICRS_ENABLEGRP0 | GIC_ICCICRS_ENABLEGRP1 |
+             GIC_ICCICRS_FIQBYPDISGRP0 | GIC_ICCICRS_IRQBYPDISGRP0 |
+             GIC_ICCICRS_FIQBYPDISGRP1 | GIC_ICCICRS_IRQBYPDISGRP1);
+#endif
+  icddcr  = GIC_ICDDCR_ENABLEGRP0;
+
+#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);
+  icddcr  = (GIC_ICDDCR_ENABLEGRP0 | GIC_ICDDCR_ENABLEGRP1);
+
+#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);
+  icddcr  = GIC_ICDDCR_ENABLE;
+
+#endif
+
+  /* Write the final ICCICR value to enable the GIC. */
+
+  putreg32(iccicr, 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
+
+  /* Write the ICDDCR value to enable the forwarding of interrupt by the
+   * distributor.
+   */
+
+  putreg32(icddcr, GIC_ICDDCR);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: arm64_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.
+ *
+ ****************************************************************************/
+
+uint64_t * arm64_decodeirq(uint64_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 = arm64_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: up_affinity_irq
+ *
+ * Description:
+ *   Set an IRQ affinity by software.
+ *
+ ****************************************************************************/
+
+void up_affinity_irq(int irq, cpu_set_t cpuset)
+{
+  if (irq >= GIC_IRQ_SPI && irq < NR_IRQS)
+    {
+      uintptr_t regaddr;
+      uint32_t regval;
+
+      /* Write the new cpuset to the corresponding field in the in the
+       * distributor Interrupt Processor Target Register (GIC_ICDIPTR).
+       */
+
+      regaddr = GIC_ICDIPTR(irq);
+      regval  = getreg32(regaddr);
+      regval &= ~GIC_ICDIPTR_ID_MASK(irq);
+      regval |= GIC_ICDIPTR_ID(irq, cpuset);
+      putreg32(regval, regaddr);
+    }
+}
+
+/****************************************************************************
+ * Name: up_trigger_irq
+ *
+ * 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 Parameters
+ *   irq    - The SGI interrupt ID (0-15)
+ *   cpuset - The set of CPUs to receive the SGI
+ *
+ ****************************************************************************/
+
+void up_trigger_irq(int irq, cpu_set_t cpuset)
+{
+  if (irq >= 0 && irq <= GIC_IRQ_SGI15)
+    {
+      arm_cpu_sgi(irq, cpuset);
+    }
+  else if (irq >= 0 && irq < NR_IRQS)
+    {
+      uintptr_t regaddr;
+
+      /* Write '1' to the corresponding bit in the distributor Interrupt
+       * Set-Pending (ICDISPR)
+       */
+
+      regaddr = GIC_ICDISPR(irq);
+      putreg32(GIC_ICDISPR_INT(irq), regaddr);
+    }
+}
+
+/****************************************************************************
+ * Name: arm64_gic_irq_set_priority
+ *
+ * Description:
+ *   Set the interrupt priority and type.
+ *
+ *   If CONFIG_SMP is not selected, the cpuset is ignored and SGI is sent
+ *   only to the current CPU.
+ *
+ * Input Parameters
+ *   intid  - The SGI interrupt ID (0-15)
+ *   prio   - The interrupt priority
+ *   flags  - Bit IRQ_TYPE_EDGE is 1 if interrupt should be edge-triggered
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void arm64_gic_irq_set_priority(unsigned int intid, unsigned int prio,
+                                uint32_t flags)
+{
+  int ret;
+
+  /* Disable the interrupt */
+
+  up_disable_irq(intid);
+
+  /* Set the interrupt priority */
+
+  ret = up_prioritize_irq(intid, prio);
+  DEBUGASSERT(ret == OK);
+
+  /* Configure interrupt type */
+
+  if (!GIC_IS_SGI(intid))
+    {
+      if (flags & IRQ_TYPE_EDGE)
+        {
+          ret = arm_gic_irq_trigger(intid, true);
+          DEBUGASSERT(ret == OK);
+        }
+      else
+        {
+          ret = arm_gic_irq_trigger(intid, false);
+          DEBUGASSERT(ret == OK);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: arm64_gic_initialize
+ *
+ * Description:
+ *   Initialize GIC. Called by CPU0 only.
+ *
+ * Input Parameters
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+int arm64_gic_initialize(void)
+{
+  int err;
+
+  /* Verify that GIC Version is 2 */
+
+  err = gic_validate_dist_version();
+  if (err)
+    {
+      sinfo("no distributor detected, giving up ret=%d\n", err);
+      return err;
+    }
+
+  /* CPU0-specific initialization for GIC */
+
+  arm_gic0_initialize();
+
+  /* CPU-generic initialization for GIC */
+
+  arm_gic_initialize();
+
+  return 0;
+}
+
+#ifdef CONFIG_SMP
+
+/****************************************************************************
+ * Name: arm64_gic_secondary_init
+ *
+ * Description:
+ *   Initialize GIC. Called by all CPUs except CPU0.
+ *
+ * Input Parameters
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void arm64_gic_secondary_init(void)
+{
+  /* CPU-generic initialization for GIC */
+
+  arm_gic_initialize();
+}
+
+#endif /* CONFIG_SMP */
+
+#endif /* CONFIG_ARM_GIC_VERSION == 2 */
diff --git a/arch/arm64/src/common/arm64_gicv3.c b/arch/arm64/src/common/arm64_gicv3.c
index f4ab3fb205..5df8b9c9cc 100644
--- a/arch/arm64/src/common/arm64_gicv3.c
+++ b/arch/arm64/src/common/arm64_gicv3.c
@@ -36,6 +36,8 @@
 #include "arm64_gic.h"
 #include "arm64_fatal.h"
 
+#if CONFIG_ARM_GIC_VERSION == 3 || CONFIG_ARM_GIC_VERSION == 4
+
 /***************************************************************************
  * Pre-processor Definitions
  ***************************************************************************/
@@ -615,3 +617,5 @@ void arm64_gic_secondary_init(void)
 }
 
 #endif
+
+#endif /* CONFIG_ARM_GIC_VERSION == 3 || CONFIG_ARM_GIC_VERSION == 4 */
diff --git a/boards/arm64/qemu/qemu-armv8a/README.txt b/boards/arm64/qemu/qemu-armv8a/README.txt
index 51f436bd42..898a8f484d 100644
--- a/boards/arm64/qemu/qemu-armv8a/README.txt
+++ b/boards/arm64/qemu/qemu-armv8a/README.txt
@@ -4,7 +4,7 @@ README.txt
 This board configuration will use QEMU to emulate generic ARM64 v8-A series
 hardware platform and provides support for these devices:
 
- - GICv3 interrupt controller
+ - GICv2 and GICv3 interrupt controllers
  - ARM Generic Timer
  - PL011 UART controller
 
@@ -41,7 +41,7 @@ Getting Started
    $ qemu-system-aarch64 --help
 
 3. Configuring and running
-  3.1 Single Core
+  3.1 Single Core (GICv3)
    Configuring NuttX and compile:
    $ ./tools/configure.sh -l qemu-armv8a:nsh
    $ make
@@ -51,7 +51,7 @@ Getting Started
      -net none -chardev stdio,id=con,mux=on -serial chardev:con \
      -mon chardev=con,mode=readline -kernel ./nuttx
 
-  3.2 SMP
+  3.2 SMP (GICv3)
    Configuring NuttX and compile:
    $ ./tools/configure.sh -l qemu-armv8a:nsh_smp
    $ make
@@ -61,6 +61,16 @@ Getting Started
       -net none -chardev stdio,id=con,mux=on -serial chardev:con \
       -mon chardev=con,mode=readline -kernel ./nuttx
 
+  3.3 Single Core (GICv2)
+   Configuring NuttX and compile:
+   $ ./tools/configure.sh -l qemu-armv8a:nsh_gicv2
+   $ make
+   Running with qemu
+   $ qemu-system-aarch64 -cpu cortex-a53 -nographic \
+     -machine virt,virtualization=on,gic-version=2 \
+     -net none -chardev stdio,id=con,mux=on -serial chardev:con \
+     -mon chardev=con,mode=readline -kernel ./nuttx
+
    Note:
    1. Make sure the aarch64-none-elf toolchain install PATH has been added to environment variable
    2. To quit QEMU, type Ctrl + X
@@ -70,6 +80,11 @@ Getting Started
 Status
 ======
 
+2022-11-18:
+1. Added support for GICv2.
+
+2. Added board configuration for nsh_gicv2.
+
 2022-10-13:
 1. Renamed the board configuration name from qemu-a53 to qemu-v8a.
 
diff --git a/boards/arm64/qemu/qemu-armv8a/configs/nsh_gicv2/defconfig b/boards/arm64/qemu/qemu-armv8a/configs/nsh_gicv2/defconfig
new file mode 100644
index 0000000000..f6056bb21d
--- /dev/null
+++ b/boards/arm64/qemu/qemu-armv8a/configs/nsh_gicv2/defconfig
@@ -0,0 +1,66 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+CONFIG_ARCH="arm64"
+CONFIG_ARCH_ARM64=y
+CONFIG_ARCH_BOARD="qemu-armv8a"
+CONFIG_ARCH_BOARD_QEMU_ARMV8A=y
+CONFIG_ARCH_CHIP="qemu"
+CONFIG_ARCH_CHIP_QEMU=y
+CONFIG_ARCH_CHIP_QEMU_A53=y
+CONFIG_ARCH_INTERRUPTSTACK=4096
+CONFIG_ARM_GIC_VERSION=2
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_SCHED=y
+CONFIG_DEBUG_SCHED_ERROR=y
+CONFIG_DEBUG_SCHED_INFO=y
+CONFIG_DEBUG_SCHED_WARN=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_DEFAULT_TASK_STACKSIZE=8192
+CONFIG_DEV_ZERO=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_ROMFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=8192
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_ROMFSETC=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PTHREAD_STACK_MIN=8192
+CONFIG_QEMU_UART_PL011=y
+CONFIG_RAMLOG=y
+CONFIG_RAM_SIZE=134217728
+CONFIG_RAM_START=0x40000000
+CONFIG_RAW_BINARY=y
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_HPWORKPRIORITY=192
+CONFIG_SPINLOCK=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_MONTH=3
+CONFIG_START_YEAR=2022
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_SYSTEM=y
+CONFIG_TESTING_GETPRIME=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_UART1_SERIAL_CONSOLE=y
+CONFIG_USEC_PER_TICK=1000