Apps: Zynq: Update to use libmetal I/O and device
authorWendy Liang <jliang@xilinx.com>
Tue, 16 Aug 2016 04:47:29 +0000 (21:47 -0700)
committerWendy Liang <jliang@xilinx.com>
Thu, 13 Oct 2016 05:01:48 +0000 (22:01 -0700)
Update Zynq generic system implementation to use libmetal I/O and
device APIs

Signed-off-by: Wendy Liang <jliang@xilinx.com>
apps/machine/zynq7/platform_info.c
apps/machine/zynq7/platform_info.h [new file with mode: 0644]
apps/system/generic/machine/zynq7/CMakeLists.txt
apps/system/generic/machine/zynq7/Xilinx.spec [new file with mode: 0644]
apps/system/generic/machine/zynq7/helper.c
apps/system/generic/machine/zynq7/linker_remote.ld
apps/system/generic/machine/zynq7/sys_init.c [new file with mode: 0644]

index 70b7fb6687c964bba5f39609d96887936fba3bc8..dbb22da1589e5a894d4f5a5042069a97f9831ced 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2014, Mentor Graphics Corporation
  * All rights reserved.
 /*
  * Copyright (c) 2014, Mentor Graphics Corporation
  * All rights reserved.
+ * Copyright (c) 2015 Xilinx, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  * DESCRIPTION
  *
  *       This file implements APIs to get platform specific
  * DESCRIPTION
  *
  *       This file implements APIs to get platform specific
- *       information for OpenAMP. 
+ *       information for OpenAMP.
  *
  **************************************************************************/
 
  *
  **************************************************************************/
 
-#include <string.h>
 #include "openamp/hil.h"
 #include "openamp/hil.h"
+#include "openamp/remoteproc_plat.h"
+#include "metal/atomic.h"
+#include "platform_info.h"
+
+#define REMOTE_CPU_ID                     0
 
 /* Reference implementation that show cases platform_get_cpu_info and 
  platform_get_for_firmware API implementation for Bare metal environment */
 
 extern struct hil_platform_ops zynq_a9_proc_ops;
 
 
 /* Reference implementation that show cases platform_get_cpu_info and 
  platform_get_for_firmware API implementation for Bare metal environment */
 
 extern struct hil_platform_ops zynq_a9_proc_ops;
 
-/* IPC Device parameters */
-#define SHM_ADDR                          (void *)0x08008000
-#define SHM_SIZE                          0x00200000
-#define VRING0_IPI_VECT                   15
-#define VRING1_IPI_VECT                   14
-#define MASTER_CPU_ID                     0
-#define REMOTE_CPU_ID                     1
 
 
-/**
- * This array provdes defnition of CPU nodes for master and remote
- * context. It contains two nodes beacuse the same file is intended
- * to use with both master and remote configurations. On zynq platform
- * only one node defintion is required for master/remote as there
- * are only two cores present in the platform.
- *
- * Only platform specific info is populated here. Rest of information
- * is obtained during resource table parsing.The platform specific
- * information includes;
- *
- * -CPU ID
- * -Shared Memory
- * -Interrupts
- * -Channel info.
- *
- * Although the channel info is not platform specific information
- * but it is conveneient to keep it in HIL so that user can easily
- * provide it without modifying the generic part.
- *
- * It is good idea to define hil_proc structure with platform
- * specific fields populated as this can be easily copied to hil_proc
- * structure passed as parameter in platform_get_processor_info. The
- * other option is to populate the required structures individually
- * and copy them one by one to hil_proc structure in platform_get_processor_info
- * function. The first option is adopted here.
- *
- *
- * 1) First node in the array is intended for the remote contexts and it
- *    defines Master CPU ID, shared memory, interrupts info, number of channels
- *    and there names. This node defines only one channel
- *   "rpmsg-openamp-demo-channel".
- *
- * 2)Second node is required by the master and it defines remote CPU ID,
- *   shared memory and interrupts info. In general no channel info is required by the
- *   Master node, however in baremetal master and linux remote case the linux
- *   rpmsg bus driver behaves as master so the rpmsg driver on linux side still needs
- *   channel info. This information is not required by the masters for baremetal
- *   remotes. 
- *
- */
-struct hil_proc proc_table[] = {
-
-       /* CPU node for remote context */
+struct rproc_info_plat_local proc_table = {
        {
        {
-        /* CPU ID of master */
-        MASTER_CPU_ID,
-
-        /* HIL platform ops table. */
-        &zynq_a9_proc_ops,
-
-        /* Shared memory info - Last field is not used currently */
-        {
-         SHM_ADDR, SHM_SIZE, 0x00},
-
-        /* VirtIO device info */
-        {
-         /* Leave these three fields empty as these are obtained from rsc
-          * table.
-          */
-         0, 0, 0,
-
-         /* Vring info */
-         {
+               /* CPU ID of master */
+               REMOTE_CPU_ID,
 
 
-          {
-           /* Provide only vring interrupts info here. Other fields are
-            * obtained from the resource table so leave them empty.
-            */
-           NULL, NULL, 0, 0,
-           {
-            VRING0_IPI_VECT, 0x1006, 1, NULL}
-           },
-          {
-           NULL, NULL, 0, 0,
-           {
-            VRING1_IPI_VECT, 0x1006, 1, NULL}
-           }
-          }
-         },
-
-        /* Number of RPMSG channels */
-        1,
-
-        /* RPMSG channel info - Only channel name is expected currently */
-        {
-         {"rpmsg-openamp-demo-channel"}
-         },
+               /* HIL platform ops table. */
+               &zynq_a9_proc_ops,
+       },
+       /* vring0 ipi device and vring descriptors memory device */
+       {
+               PLAT_RSC_VRING,
+               "generic",
+               "ipi0",
+               NULL,
+               "generic",
+               "vrings",
+       },
+       /* vring1 ipi device and vring descriptors memory device */
+       {
+               PLAT_RSC_VRING,
+               "generic",
+               "ipi1",
+               NULL,
+               "generic",
+               "vrings",
+       },
+       /* Shared memory device */
+       {
+               PLAT_RSC_SHM,
+               "shm",
+               0,  /* UNDEFINED */
+       },
+       /* Shared memory device */
+       {
+               PLAT_RSC_RPMSG_CHANNEL,
+               "rpmsg-openamp-demo-channel",
+       },
+       PLAT_RSC_LAST,
+};
 
 
-        /* Next three fields are for future use only */
-        0,
+const struct firmware_info fw_table[] =
+{
+       {"unknown",
         0,
         0,
-        NULL,
-        {NULL, NULL}
-       },
+        0}
 };
 
 };
 
+int fw_table_size = sizeof(fw_table)/sizeof(struct firmware_info);
diff --git a/apps/machine/zynq7/platform_info.h b/apps/machine/zynq7/platform_info.h
new file mode 100644 (file)
index 0000000..2903d2a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Xilinx, Inc. All rights reserved.
+ *
+ * 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 of Mentor Graphics Corporation 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 HOLDER 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.
+ */
+
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include "openamp/hil.h"
+#include "openamp/remoteproc_plat.h"
+
+/* remoteproc platform data structure */
+struct rproc_info_plat_local {
+       struct proc_info_hdr proc_hdr; /**< hil proc header */
+       struct plat_vring vring0; /**< vring0 data */
+       struct plat_vring vring1; /**< vring1 data */
+       struct plat_shm shm; /**< shared memory data */
+       struct plat_rpmsg_chnl rpmsg_chnl; /**< RPMSG channel data */
+       unsigned int last_type;
+};
index ad29ef78166538b225c2b51532a9c4c05a8b6e80..5445398e750a77333e4024c068ceeb0da069582d 100644 (file)
@@ -1,5 +1,5 @@
-collect (APP_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
 collect (APP_COMMON_SOURCES helper.c)
 collect (APP_COMMON_SOURCES helper.c)
+collect (APP_COMMON_SOURCES sys_init.c)
 
 if (WITH_REMOTEPROC_MASTER)
   set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_master.ld")
 
 if (WITH_REMOTEPROC_MASTER)
   set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_master.ld")
@@ -7,4 +7,12 @@ else (WITH_REMOTEPROC_MASTER)
   set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_remote.ld")
 endif (WITH_REMOTEPROC_MASTER)
 
   set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_remote.ld")
 endif (WITH_REMOTEPROC_MASTER)
 
-set_property (GLOBAL PROPERTY APP_LINKER_SCRIPT "${_linker_script}")
+set_property (GLOBAL PROPERTY APP_LINKER_OPT "-Wl,-build-id=none -specs=${CMAKE_CURRENT_SOURCE_DIR}/Xilinx.spec -T\"${_linker_script}\"")
+
+find_library(LIBXIL_LIB NAMES xil PATHS ${CMAKE_FIND_ROOT_PATH})
+get_filename_component(LIBXIL_LIB_DIR ${LIBXIL_LIB} DIRECTORY)
+collect(PROJECT_LIB_DIRS ${LIBXIL_LIB_DIR})
+
+collect(PROJECT_LIB_DEPS xil)
+collect(PROJECT_LIB_DEPS c)
+collect(PROJECT_LIB_DEPS m)
diff --git a/apps/system/generic/machine/zynq7/Xilinx.spec b/apps/system/generic/machine/zynq7/Xilinx.spec
new file mode 100644 (file)
index 0000000..8eea377
--- /dev/null
@@ -0,0 +1,2 @@
+*startfile:
+crti%O%s crtbegin%O%s
index 537446dea1c17d44fad495bb13dbeb87a76065cb..7a3e22a94a8fb558f27f492d31825a9021d81bb0 100755 (executable)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2014, Mentor Graphics Corporation
  * All rights reserved.
 /*
  * Copyright (c) 2014, Mentor Graphics Corporation
  * All rights reserved.
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <string.h>
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <string.h>
-#include "baremetal.h"
+#include "xparameters.h"
+#include "xil_exception.h"
+#include "xscugic.h"
+#include "xil_cache.h"
 #include "metal/sys.h"
 
 #include "metal/sys.h"
 
-#ifndef BAREMETAL_MASTER
-#define BAREMETAL_MASTER 0
-#endif
-
-/* Memory Regions for MMU Mapping */
-#if (BAREMETAL_MASTER == 1)
-
-#define ELF_START       0x10000000     /* Image entry point address */
-#define ELF_END         0x0FE00000     /* size of code,data,heap and stack sections */
-
-#define TLB_MEM_START   0x1FE00000     /* Address of TLB memory */
-
-#else
+#define INTC_DEVICE_ID         XPAR_SCUGIC_0_DEVICE_ID
+/** IPI IRQ ID */
+#define VRING0_IPI_VECT         15
+#define VRING1_IPI_VECT         14
 
 
-#define ELF_START       0x00000000     /* Image entry point address */
-#define ELF_END         0x08000000     /* size of code,data,heap and stack sections */
+XScuGic InterruptController;
 
 
-#define TLB_MEM_START   0x0FE00000     /* Address of TLB memory */
+extern void metal_irq_isr(unsigned int irq);
+extern int platform_register_metal_device(void);
 
 
-#endif
-
-/* The vector table address is the same as image entry point */
-#define RAM_VECTOR_TABLE_ADDR           ELF_START
-
-unsigned char ARM_AR_ISR_IRQ_Data[ARM_AR_ISR_STACK_SIZE];
-unsigned char ARM_AR_ISR_FIQ_Data[ARM_AR_ISR_STACK_SIZE];
-unsigned char ARM_AR_ISR_SUP_Stack[ARM_AR_ISR_STACK_SIZE];
-unsigned char ARM_AR_ISR_SYS_Stack[ARM_AR_ISR_STACK_SIZE];
-
-extern void bm_env_isr(int vector);
-
-/* IRQ handler */
-void __attribute__ ((interrupt("IRQ"))) __cs3_isr_irq()
+int zynq_a9_gic_initialize()
 {
 {
-       unsigned long raw_irq;
-       int irq_vector;
-
-       /* Read the Interrupt ACK register */
-       raw_irq = MEM_READ32(INT_GIC_CPU_BASE + INT_GIC_CPU_ACK);
-
-       /* mask interrupt to get vector */
-       irq_vector = raw_irq & INT_ACK_MASK;
-
-       bm_env_isr(irq_vector);
-
-       /* Clear the interrupt */
-       MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_ENDINT, raw_irq);
-}
-
-/* Only applicable for remote/slave node */
-void zynq7_gic_pr_int_initialize(void)
-{
-
-       /* Disable the GIC controller */
-       MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CTRL, 0x00000000);
-
-       /* Enable the interrupt distributor controller */
-       MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CTRL, INT_DIST_ENABLE);
-
-       /* Secondary cores  just need to disable their private interrupts */
-       MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_ENABLE_CLEAR + 0x00,
-                   0xffffffff);
-       /* 0  - 31 */
+       u32 Status;
 
 
-       MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CONFIG + 0x00, 0xAAAAAAAA);
-       /* 0  - 15 */
-       MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CONFIG + 0x04, 0xAAAAAAAA);
+       Xil_ExceptionDisable();
 
 
-       /* Disable the CPU Interface */
-       MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_CTRL, 0x00000000);
+       XScuGic_Config *IntcConfig;     /* The configuration parameters of the interrupt controller */
 
 
-       /* Allow interrupts with more priority (i.e. lower number) than FF */
-       MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_PRIORITY, 0x000000FF);
-
-       /* No binary point */
-       MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_POINT, 0x00000000);
-
-       /* Enable the CPU Interface */
-       MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_CTRL, INT_CPU_ENABLE);
-}
-
-int zynq7_gic_initialize()
-{
-
-       unsigned long reg_val;
-
-       /* Disable architecture interrupts (IRQ and FIQ)
-        * before initialization */
-       ARM_AR_CPSR_CXSF_READ(&reg_val);
-       reg_val |= (0x02 << 6);
-       ARM_AR_CPSR_CXSF_WRITE(reg_val);
-
-       zynq7_gic_pr_int_initialize();
-
-       /* Enable architecture Interrupts */
-       ARM_AR_CPSR_CXSF_READ(&reg_val);
-       reg_val &= ~(0x02 << 6);
-       ARM_AR_CPSR_CXSF_WRITE(reg_val);
-
-       return 0;
-}
-
-void arm_arch_install_isr_vector_table(unsigned long addr)
-{
-       unsigned long arch = 0;
-       void *dst_addr;
-
-       /* Assign destination address of vector table to RAM address */
-       dst_addr = (void *)addr;
-       /* Read Main ID Register (MIRD) */
-       ARM_AR_CP_READ(p15, 0, &arch, c0, c0, 0);
-
-       /* Check if Cortex-A series of ARMv7 architecture. */
-       if (((arch & MIDR_ARCH_MASK) >> 16) == MIDR_ARCH_ARMV7
-           && ((arch & MIDR_PART_NO_MASK) >> 4)
-           == MIDR_PART_NO_CORTEX_A) {
-               /* Set vector base address */
-               ARM_AR_CP_WRITE(p15, 0, dst_addr, c12, c0, 0);
-               ARM_AR_NOP_EXECUTE();
-               ARM_AR_NOP_EXECUTE();
-               ARM_AR_NOP_EXECUTE();
+       /*
+        * Initialize the interrupt controller driver
+        */
+       IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
+       if (NULL == IntcConfig) {
+               return XST_FAILURE;
        }
        }
-}
-
-void init_arm_stacks(void)
-{
-
-       /* Switch to IRQ mode (keeping interrupts disabled) */
-       ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_IRQ_MODE |
-                           ARM_AR_INTERRUPTS_DISABLE_BITS);
-
-       /* Set IRQ stack pointer */
-       ARM_AR_SP_WRITE(ARM_GE_STK_ALIGN
-                       (&ARM_AR_ISR_IRQ_Data[ARM_AR_ISR_STACK_SIZE - 1]));
-
-       /* Switch to FIQ mode (keeping interrupts disabled) */
-       ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_FIQ_MODE |
-                           ARM_AR_INTERRUPTS_DISABLE_BITS);
-
-       /* Set FIQ stack pointer */
-       ARM_AR_SP_WRITE(ARM_GE_STK_ALIGN
-                       (ARM_AR_ISR_FIQ_Data[ARM_AR_ISR_STACK_SIZE - 1]));
-
-       /* Switch to Supervisor mode (keeping interrupts disabled) */
-       ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_SUP_MODE |
-                           ARM_AR_INTERRUPTS_DISABLE_BITS);
-
-       /* Set Supervisor stack pointer */
-       ARM_AR_SP_WRITE(ARM_GE_STK_ALIGN
-                       (&ARM_AR_ISR_SUP_Stack[ARM_AR_ISR_STACK_SIZE - 1]));
-
-       /* Switch to System mode (keeping interrupts disabled) */
-       ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_SYS_DISABLED);
-}
-
-/***********************************************************************
- *
- *  arm_ar_mem_enable_mmu
- *
- *  Enables MMU and MAP the required memory regions.
- *
- ***********************************************************************/
-int arm_ar_mem_enable_mmu()
-{
-       unsigned int cp15_ctrl_val;
-       void *tlb_mem = (void *)TLB_MEM_START;
-
-       ARM_AR_MEM_CACHE_ALL_INVALIDATE();
-
-       /* Read current CP15 control register value */
-       ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
-
-       /* Clear the V bit(13) to set Normal exception vectors range. */
-       cp15_ctrl_val &= ~(ARM_AR_MEM_CP15_CTRL_V);
-
-       /* Clear the alignment bit(1) to enable unaligned memory accesses */
-       cp15_ctrl_val &= ~(ARM_AR_MEM_CP15_CTRL_A);
-
-       /* Write updated CP15 control register value */
-       ARM_AR_CP_WRITE(ARM_AR_CP15, 0, cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
 
 
-       ARM_AR_NOP_EXECUTE();
-       ARM_AR_NOP_EXECUTE();
-       ARM_AR_NOP_EXECUTE();
-
-       /* Check alignment of available memory pointer */
-       if (!(MEM_ALIGNED_CHECK(tlb_mem, ARM_AR_MEM_TTB_SIZE))) {
-               /* Align the pointer to the required boundary */
-               tlb_mem = MEM_PTR_ALIGN(tlb_mem, ARM_AR_MEM_TTB_SIZE);
+       Status = XScuGic_CfgInitialize(&InterruptController, IntcConfig,
+                                      IntcConfig->CpuBaseAddress);
+       if (Status != XST_SUCCESS) {
+               return XST_FAILURE;
        }
 
        }
 
-       /* Clear the entire translation table */
-       memset(tlb_mem, 0x00, ARM_AR_MEM_TTB_SIZE);
-
-       /* Set translation table base address */
-       ARM_AR_CP_WRITE(ARM_AR_CP15, 0, tlb_mem, ARM_AR_C2, ARM_AR_C0, 0);
-
-       ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C2, ARM_AR_C0, 0);
-
-       /* Map the given memory regions here */
-       arm_ar_map_mem_region(ELF_START, ELF_START, ELF_END, 0, WRITEBACK);
-       arm_ar_map_mem_region((unsigned int)tlb_mem, (unsigned int)tlb_mem,
-                             TLB_SIZE, 0, NOCACHE);
-       arm_ar_map_mem_region(PERIPH_BASE, PERIPH_BASE,
-                             PERIPH_SIZE, 1, NOCACHE);
-       arm_ar_map_mem_region(SLCR_BASE, SLCR_BASE, SLCR_SIZE, 1, NOCACHE);
-       arm_ar_map_mem_region(CPU_BASE, CPU_BASE, CPU_SIZE, 1, NOCACHE);
-
-       /* Set the domain access for domain D0 */
-       ARM_AR_CP_WRITE(ARM_AR_CP15, 0, ARM_AR_MEM_DOMAIN_D0_MANAGER_ACCESS,
-                       ARM_AR_C3, ARM_AR_C0, 0);
-
-       ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C3, ARM_AR_C0, 0);
-
-       /* Invalidate all TLB entries before enabling the MMU */
-       ARM_AR_CP_WRITE(ARM_AR_CP15, 0, 0, ARM_AR_C8, ARM_AR_C7, 0);
-
-       /* Read current CP15 control register value */
-       ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
-
-       /* Set instruction cache enable / data cache enable / MMU enable bits */
-       cp15_ctrl_val |= (ARM_AR_MEM_CP15_CTRL_I | ARM_AR_MEM_CP15_CTRL_C
-                         | ARM_AR_MEM_CP15_CTRL_M | ARM_AR_MEM_CP15_CTRL_Z);
-
-       /* Write updated CP15 control register value */
-       ARM_AR_CP_WRITE(ARM_AR_CP15, 0, cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
-
-       ARM_AR_NOP_EXECUTE();
-       ARM_AR_NOP_EXECUTE();
-       ARM_AR_NOP_EXECUTE();
-
+       /*
+        * Register the interrupt handler to the hardware interrupt handling
+        * logic in the ARM processor.
+        */
+       Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
+                       (Xil_ExceptionHandler)XScuGic_InterruptHandler,
+                       &InterruptController);
+
+       Xil_ExceptionEnable();
+       /* Connect IPI0 Interrupt ID with ISR */
+       XScuGic_Connect(&InterruptController, VRING0_IPI_VECT,
+                          (Xil_ExceptionHandler)metal_irq_isr,
+                          (void *)VRING0_IPI_VECT);
+
+       /* Connect IPI1 Interrupt ID with ISR */
+       XScuGic_Connect(&InterruptController, VRING1_IPI_VECT,
+                          (Xil_ExceptionHandler)metal_irq_isr,
+                          (void *)VRING1_IPI_VECT);
        return 0;
 }
 
 void init_system()
 {
        return 0;
 }
 
 void init_system()
 {
-       /* Place the vector table at the image entry point */
-       arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);
-
-       /* Enable MMU */
-       arm_ar_mem_enable_mmu();
-
-       /* Initialize ARM stacks */
-       init_arm_stacks();
+       struct metal_init_params metal_param = METAL_INIT_DEFAULTS;
 
 
-       /* Initialize GIC */
-       zynq7_gic_initialize();
+       metal_init(&metal_param);
+       zynq_a9_gic_initialize();
+       platform_register_metal_device();
 }
 
 void cleanup_system()
 {
        metal_finish();
 }
 
 void cleanup_system()
 {
        metal_finish();
-       Xil_DCacheInvalidate();
-       Xil_ICacheInvalidate();
        Xil_DCacheDisable();
        Xil_ICacheDisable();
        Xil_DCacheDisable();
        Xil_ICacheDisable();
+       Xil_DCacheInvalidate();
+       Xil_ICacheInvalidate();
 }
 }
index 103535e230557648e1f9b5e917ff444564c17057..4e311e9af37a55924943491242d79d5169639d11 100644 (file)
-/* Linker script for Xilinx Zynq-7000\r
- *\r
- * Version: Sourcery CodeBench Lite 2013.11-24\r
- * Support: https://sourcery.mentor.com/GNUToolchain/\r
- *\r
- * Copyright (c) 2007-2010 CodeSourcery, Inc.\r
- * Copyright (c) 2010-2013 Mentor Graphics, Inc.\r
- *\r
- * The authors hereby grant permission to use, copy, modify, distribute,\r
- * and license this software and its documentation for any purpose, provided\r
- * that existing copyright notices are retained in all copies and that this\r
- * notice is included verbatim in any distributions.  No written agreement,\r
- * license, or royalty fee is required for any of the authorized uses.\r
- * Modifications to this software may be copyrighted by their authors\r
- * and need not follow the licensing terms described here, provided that\r
- * the new terms are clearly indicated on the first page of each file where\r
- * they apply.\r
- */\r
-OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")\r
-ENTRY(__cs3_reset)\r
-SEARCH_DIR(.)\r
-GROUP(-lgcc -lc -lcs3 -lcs3unhosted -lcs3arm)\r
-\r
-MEMORY\r
-{\r
-  ram (rwx) : ORIGIN = 0x00000000, LENGTH = 256M\r
-  rom (rx) : ORIGIN = 0xe4000000, LENGTH = 64M\r
-}\r
-\r
-/* These force the linker to search for particular symbols from\r
- * the start of the link process and thus ensure the user's\r
- * overrides are picked up\r
- */\r
-EXTERN(__cs3_reset __cs3_reset_zynq7000_ram)\r
-EXTERN(__cs3_start_asm _start)\r
-/* Bring in the interrupt routines & vector */\r
-INCLUDE arm-names.inc\r
-EXTERN(__cs3_interrupt_vector_arm)\r
-EXTERN(__cs3_start_c main __cs3_stack __cs3_heap_end)\r
-\r
-/* Provide fall-back values */\r
-PROVIDE(__cs3_heap_start = _end);\r
-PROVIDE(__cs3_heap_end = __cs3_region_start_ram + __cs3_region_size_ram);\r
-PROVIDE(__cs3_region_num = (__cs3_regions_end - __cs3_regions) / 20);\r
-PROVIDE(__cs3_stack = __cs3_region_start_ram + __cs3_region_size_ram);\r
-\r
-SECTIONS\r
-{\r
-    _binary_firmware1_start = 0;\r
-    _binary_firmware1_end = 0;\r
-    _binary_firmware2_start = 0;\r
-    _binary_firmware2_end = 0;\r
-\r
-  .text :\r
-  {\r
-    CREATE_OBJECT_SYMBOLS\r
-    __cs3_region_start_ram = .;\r
-    _ftext = .;\r
-    *(.cs3.region-head.ram)\r
-    ASSERT (. == __cs3_region_start_ram, ".cs3.region-head.ram not permitted");\r
-    __cs3_interrupt_vector = __cs3_interrupt_vector_arm;\r
-    *(.cs3.interrupt_vector)\r
-    /* Make sure we pulled in an interrupt vector.  */\r
-    ASSERT (. != __cs3_interrupt_vector_arm, "No interrupt vector");\r
-\r
-    PROVIDE(__cs3_reset = __cs3_reset_zynq7000_ram);\r
-    *(.cs3.reset)\r
-    _start = DEFINED(__cs3_start_asm) ? __cs3_start_asm : _start;\r
-\r
-    *(.text.cs3.init)\r
-    *(.text .text.* .gnu.linkonce.t.*)\r
-    *(.plt)\r
-    *(.gnu.warning)\r
-    *(.glue_7t) *(.glue_7) *(.vfp11_veneer)\r
-\r
-    *(.ARM.extab* .gnu.linkonce.armextab.*)\r
-    *(.gcc_except_table)\r
-  } >ram\r
-  .eh_frame_hdr : ALIGN (4)\r
-  {\r
-    KEEP (*(.eh_frame_hdr))\r
-    *(.eh_frame_entry .eh_frame_entry.*)\r
-  } >ram\r
-  .eh_frame : ALIGN (4)\r
-  {\r
-    KEEP (*(.eh_frame)) *(.eh_frame.*)\r
-  } >ram\r
-  /* .ARM.exidx is sorted, so has to go in its own output section.  */\r
-  PROVIDE_HIDDEN (__exidx_start = .);\r
-  .ARM.exidx :\r
-  {\r
-    *(.ARM.exidx* .gnu.linkonce.armexidx.*)\r
-  } >ram\r
-  PROVIDE_HIDDEN (__exidx_end = .);\r
-  .rodata : ALIGN (4)\r
-  {\r
-    *(.rodata .rodata.* .gnu.linkonce.r.*)\r
-\r
-    . = ALIGN(4);\r
-    KEEP(*(.init))\r
-\r
-    . = ALIGN(4);\r
-    __preinit_array_start = .;\r
-    KEEP (*(.preinit_array))\r
-    __preinit_array_end = .;\r
-\r
-    . = ALIGN(4);\r
-    __init_array_start = .;\r
-    KEEP (*(SORT(.init_array.*)))\r
-    KEEP (*(.init_array))\r
-    __init_array_end = .;\r
-\r
-    . = ALIGN(4);\r
-    KEEP(*(.fini))\r
-\r
-    . = ALIGN(4);\r
-    __fini_array_start = .;\r
-    KEEP (*(.fini_array))\r
-    KEEP (*(SORT(.fini_array.*)))\r
-    __fini_array_end = .;\r
-\r
-    . = ALIGN(0x4);\r
-    KEEP (*crtbegin.o(.ctors))\r
-    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))\r
-    KEEP (*(SORT(.ctors.*)))\r
-    KEEP (*crtend.o(.ctors))\r
-\r
-    . = ALIGN(0x4);\r
-    KEEP (*crtbegin.o(.dtors))\r
-    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))\r
-    KEEP (*(SORT(.dtors.*)))\r
-    KEEP (*crtend.o(.dtors))\r
-\r
-    . = ALIGN(4);\r
-    __cs3_regions = .;\r
-    LONG (0)\r
-    LONG (__cs3_region_init_ram)\r
-    LONG (__cs3_region_start_ram)\r
-    LONG (__cs3_region_init_size_ram)\r
-    LONG (__cs3_region_zero_size_ram)\r
-    __cs3_regions_end = .;\r
-    . = ALIGN (8);\r
-    _etext = .;\r
-  } >ram\r
-\r
-  ASSERT (!(__cs3_region_init_ram & 7), "__cs3_region_init_ram not aligned")\r
-  ASSERT (!(__cs3_region_start_ram & 7), "__cs3_region_start_ram not aligned")\r
-  ASSERT (!(__cs3_region_init_size_ram & 7), "__cs3_region_init_size_ram not aligned")\r
-  ASSERT (!(__cs3_region_zero_size_ram & 7), "__cs3_region_zero_size_ram not aligned")\r
-  .cs3.rom : ALIGN (8)\r
-  {\r
-    __cs3_region_start_rom = .;\r
-    *(.cs3.region-head.rom)\r
-    *(.rom)\r
-    . = ALIGN (8);\r
-  } >rom\r
-  .cs3.rom.bss :\r
-  {\r
-    *(.rom.b .bss.rom)\r
-    . = ALIGN (8);\r
-  } >rom\r
-  /* __cs3_region_end_rom is deprecated */\r
-  __cs3_region_end_rom = __cs3_region_start_rom + LENGTH(rom);\r
-  __cs3_region_size_rom = LENGTH(rom);\r
-  __cs3_region_init_rom = LOADADDR (.cs3.rom);\r
-  __cs3_region_init_size_rom = LOADADDR (.cs3.rom.bss) - LOADADDR (.cs3.rom);\r
-  __cs3_region_zero_size_rom = SIZEOF(.cs3.rom.bss);\r
-\r
-  .data : ALIGN (8)\r
-  {\r
-    KEEP(*(.jcr))\r
-    *(.got.plt) *(.got)\r
-    *(.shdata)\r
-    *(.data .data.* .gnu.linkonce.d.*)\r
-    . = ALIGN (8);\r
-    *(.ram)\r
-    . = ALIGN (8);\r
-    _edata = .;\r
-  } >ram\r
-  .bss : ALIGN (8)\r
-  {\r
-    *(.shbss)\r
-    *(.bss .bss.* .gnu.linkonce.b.*)\r
-    *(COMMON)\r
-    . = ALIGN (8);\r
-    *(.ram.b .bss.ram)\r
-    . = ALIGN (8);\r
-    _end = .;\r
-    __end = .;\r
-  } >ram\r
-  /* __cs3_region_end_ram is deprecated */\r
-  __cs3_region_end_ram = __cs3_region_start_ram + LENGTH(ram);\r
-  __cs3_region_size_ram = LENGTH(ram);\r
-  __cs3_region_init_ram = LOADADDR (.text);\r
-  __cs3_region_init_size_ram = _edata - ADDR (.text);\r
-  __cs3_region_zero_size_ram = _end - _edata;\r
-\r
-  .stab 0 (NOLOAD) : { *(.stab) }\r
-  .stabstr 0 (NOLOAD) : { *(.stabstr) }\r
-  /* DWARF debug sections.\r
-   * Symbols in the DWARF debugging sections are relative to\r
-   * the beginning of the section so we begin them at 0.\r
-   */\r
-  /* DWARF 1 */\r
-  .debug          0 : { *(.debug) }\r
-  .line           0 : { *(.line) }\r
-  /* GNU DWARF 1 extensions */\r
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }\r
-  .debug_sfnames  0 : { *(.debug_sfnames) }\r
-  /* DWARF 1.1 and DWARF 2 */\r
-  .debug_aranges  0 : { *(.debug_aranges) }\r
-  .debug_pubnames 0 : { *(.debug_pubnames) }\r
-  /* DWARF 2 */\r
-  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }\r
-  .debug_abbrev   0 : { *(.debug_abbrev) }\r
-  .debug_line     0 : { *(.debug_line) }\r
-  .debug_frame    0 : { *(.debug_frame) }\r
-  .debug_str      0 : { *(.debug_str) }\r
-  .debug_loc      0 : { *(.debug_loc) }\r
-  .debug_macinfo  0 : { *(.debug_macinfo) }\r
-  /* DWARF 2.1 */\r
-  .debug_ranges   0 : { *(.debug_ranges) }\r
-  /* SGI/MIPS DWARF 2 extensions */\r
-  .debug_weaknames 0 : { *(.debug_weaknames) }\r
-  .debug_funcnames 0 : { *(.debug_funcnames) }\r
-  .debug_typenames 0 : { *(.debug_typenames) }\r
-  .debug_varnames  0 : { *(.debug_varnames) }\r
-\r
-  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }\r
-  .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }\r
-  /DISCARD/ : { *(.note.GNU-stack) }\r
-}\r
-/* checksum: b15b0bf76673e544380111 */\r
+/*******************************************************************/
+/*                                                                 */
+/* This file is automatically generated by linker script generator.*/
+/*                                                                 */
+/* Version:                                 */
+/*                                                                 */
+/* Copyright (c) 2010 Xilinx, Inc.  All rights reserved.           */
+/*                                                                 */
+/* Description : Cortex-A9 Linker Script                          */
+/*                                                                 */
+/*******************************************************************/
+
+_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
+_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x4000;
+
+_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
+_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
+_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 4096;
+_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
+_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
+
+/* Define Memories in the system */
+
+MEMORY
+{
+   ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x00100000, LENGTH = 0x08000000
+   ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x00030000
+   ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00
+}
+
+/* Specify the default entry point to the program */
+
+ENTRY(_vector_table)
+
+/* Define the sections, and where they are mapped in memory */
+
+SECTIONS
+{
+.text : {
+
+_binary_firmware1_start = 0;
+_binary_firmware1_end = 0;
+_binary_firmware2_start = 0;
+_binary_firmware2_end = 0;
+
+   *(.vectors)
+   *(.boot)
+   *(.text)
+   *(.text.*)
+   *(.gnu.linkonce.t.*)
+   *(.plt)
+   *(.gnu_warning)
+   *(.gcc_execpt_table)
+   *(.glue_7)
+   *(.glue_7t)
+   *(.vfp11_veneer)
+   *(.ARM.extab)
+   *(.gnu.linkonce.armextab.*)
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.init : {
+   KEEP (*(.init))
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.fini : {
+   KEEP (*(.fini))
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.rodata : {
+   __rodata_start = .;
+   *(.rodata)
+   *(.rodata.*)
+   *(.gnu.linkonce.r.*)
+   __rodata_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.rodata1 : {
+   __rodata1_start = .;
+   *(.rodata1)
+   *(.rodata1.*)
+   __rodata1_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.sdata2 : {
+   __sdata2_start = .;
+   *(.sdata2)
+   *(.sdata2.*)
+   *(.gnu.linkonce.s2.*)
+   __sdata2_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.sbss2 : {
+   __sbss2_start = .;
+   *(.sbss2)
+   *(.sbss2.*)
+   *(.gnu.linkonce.sb2.*)
+   __sbss2_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.data : {
+   __data_start = .;
+   *(.data)
+   *(.data.*)
+   *(.gnu.linkonce.d.*)
+   *(.jcr)
+   *(.got)
+   *(.got.plt)
+   __data_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.data1 : {
+   __data1_start = .;
+   *(.data1)
+   *(.data1.*)
+   __data1_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.got : {
+   *(.got)
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.ctors : {
+   __CTOR_LIST__ = .;
+   ___CTORS_LIST___ = .;
+   KEEP (*crtbegin.o(.ctors))
+   KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
+   KEEP (*(SORT(.ctors.*)))
+   KEEP (*(.ctors))
+   __CTOR_END__ = .;
+   ___CTORS_END___ = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.dtors : {
+   __DTOR_LIST__ = .;
+   ___DTORS_LIST___ = .;
+   KEEP (*crtbegin.o(.dtors))
+   KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
+   KEEP (*(SORT(.dtors.*)))
+   KEEP (*(.dtors))
+   __DTOR_END__ = .;
+   ___DTORS_END___ = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.fixup : {
+   __fixup_start = .;
+   *(.fixup)
+   __fixup_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.eh_frame : {
+   *(.eh_frame)
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.eh_framehdr : {
+   __eh_framehdr_start = .;
+   *(.eh_framehdr)
+   __eh_framehdr_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.gcc_except_table : {
+   *(.gcc_except_table)
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.mmu_tbl (ALIGN(16384)) : {
+   __mmu_tbl_start = .;
+   *(.mmu_tbl)
+   __mmu_tbl_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.ARM.exidx : {
+   __exidx_start = .;
+   *(.ARM.exidx*)
+   *(.gnu.linkonce.armexidix.*.*)
+   __exidx_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.preinit_array : {
+   __preinit_array_start = .;
+   KEEP (*(SORT(.preinit_array.*)))
+   KEEP (*(.preinit_array))
+   __preinit_array_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.init_array : {
+   __init_array_start = .;
+   KEEP (*(SORT(.init_array.*)))
+   KEEP (*(.init_array))
+   __init_array_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.fini_array : {
+   __fini_array_start = .;
+   KEEP (*(SORT(.fini_array.*)))
+   KEEP (*(.fini_array))
+   __fini_array_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.ARM.attributes : {
+   __ARM.attributes_start = .;
+   *(.ARM.attributes)
+   __ARM.attributes_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.sdata : {
+   __sdata_start = .;
+   *(.sdata)
+   *(.sdata.*)
+   *(.gnu.linkonce.s.*)
+   __sdata_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.sbss (NOLOAD) : {
+   __sbss_start = .;
+   *(.sbss)
+   *(.sbss.*)
+   *(.gnu.linkonce.sb.*)
+   __sbss_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.tdata : {
+   __tdata_start = .;
+   *(.tdata)
+   *(.tdata.*)
+   *(.gnu.linkonce.td.*)
+   __tdata_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.tbss : {
+   __tbss_start = .;
+   *(.tbss)
+   *(.tbss.*)
+   *(.gnu.linkonce.tb.*)
+   __tbss_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.bss (NOLOAD) : {
+   __bss_start = .;
+   *(.bss)
+   *(.bss.*)
+   *(.gnu.linkonce.b.*)
+   *(COMMON)
+   __bss_end = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
+
+_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
+
+/* Generate Stack and Heap definitions */
+
+.heap (NOLOAD) : {
+   . = ALIGN(16);
+   _heap = .;
+   HeapBase = .;
+   _heap_start = .;
+   . += _HEAP_SIZE;
+   _heap_end = .;
+   HeapLimit = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+.stack (NOLOAD) : {
+   . = ALIGN(16);
+   _stack_end = .;
+   . += _STACK_SIZE;
+   _stack = .;
+   __stack = _stack;
+   . = ALIGN(16);
+   _irq_stack_end = .;
+   . += _IRQ_STACK_SIZE;
+   __irq_stack = .;
+   _supervisor_stack_end = .;
+   . += _SUPERVISOR_STACK_SIZE;
+   . = ALIGN(16);
+   __supervisor_stack = .;
+   _abort_stack_end = .;
+   . += _ABORT_STACK_SIZE;
+   . = ALIGN(16);
+   __abort_stack = .;
+   _fiq_stack_end = .;
+   . += _FIQ_STACK_SIZE;
+   . = ALIGN(16);
+   __fiq_stack = .;
+   _undef_stack_end = .;
+   . += _UNDEF_STACK_SIZE;
+   . = ALIGN(16);
+   __undef_stack = .;
+} > ps7_ddr_0_S_AXI_BASEADDR
+
+_end = .;
+}
diff --git a/apps/system/generic/machine/zynq7/sys_init.c b/apps/system/generic/machine/zynq7/sys_init.c
new file mode 100644 (file)
index 0000000..3459a7c
--- /dev/null
@@ -0,0 +1,166 @@
+
+/*
+ * Copyright (c) 2014, Mentor Graphics Corporation
+ * All rights reserved.
+ *
+ * Copyright (c) 2015 Xilinx, Inc. All rights reserved.
+ *
+ * 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 of the <ORGANIZATION> 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 HOLDER 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.
+ */
+#include <string.h>
+#include "xparameters.h"
+#include "xil_exception.h"
+#include "xscugic.h"
+#include "metal/sys.h"
+#include "metal/device.h"
+#include "metal/io.h"
+#include "metal/shmem.h"
+
+/** Device base address */
+#define SCUGIC_PERIPH_BASE      0xF8F00000
+#define SCUGIC_DIST_BASE        (SCUGIC_PERIPH_BASE + 0x00001000)
+#define UNDEFINE_BASE_ADDR      0x0
+
+#define UNDEFINE_MEM_SIZE       0xFFFFFFFF
+
+/** IPI IRQ ID */
+#define IPI0_IRQ_VECT_ID         15
+#define IPI1_IRQ_VECT_ID         14
+
+#define IPI0_DEV_NAME           "ipi0"
+#define IPI1_DEV_NAME           "ipi1"
+#define VRING_DEV_NAME          "vrings"
+#define SHM_NAME                "shm"
+
+const metal_phys_addr_t undefine_mem_addr = UNDEFINE_BASE_ADDR;
+const metal_phys_addr_t ipi_base_addr = SCUGIC_DIST_BASE;
+
+struct metal_device metal_dev_table[] = {
+       {
+               /* IPI0 device */
+               IPI0_DEV_NAME,
+               NULL,
+               1,
+               {
+                       {
+                               (void *)SCUGIC_DIST_BASE,
+                               &ipi_base_addr,
+                               0x1000,
+                               (sizeof(metal_phys_addr_t) << 3),
+                               (unsigned long)(-1),
+                               METAL_UNCACHED,
+                               {NULL},
+                       }
+               },
+               {NULL},
+               1,
+               (void *)IPI0_IRQ_VECT_ID,
+
+       },
+       {
+               /* IPI device */
+               IPI1_DEV_NAME,
+               NULL,
+               1,
+               {
+                       {
+                               (void *)SCUGIC_DIST_BASE,
+                               &ipi_base_addr,
+                               0x1000,
+                               (sizeof(metal_phys_addr_t) << 3),
+                               (unsigned long)(-1),
+                               METAL_UNCACHED,
+                               {NULL},
+                       }
+               },
+               {NULL},
+               1,
+               (void *)IPI1_IRQ_VECT_ID,
+
+       },
+       {
+               /* Shared memory management device */
+               VRING_DEV_NAME,
+               NULL,
+               1,
+               {
+                       {
+                               (void *)UNDEFINE_BASE_ADDR,
+                               &undefine_mem_addr,
+                               UNDEFINE_MEM_SIZE,
+                               (sizeof(metal_phys_addr_t) << 3),
+                               (unsigned long)(-1),
+                               METAL_UNCACHED | METAL_SHARED_MEM,
+                               {NULL},
+                       }
+               },
+               {NULL},
+               0,
+               NULL,
+
+       },
+};
+
+struct metal_generic_shmem shm = {
+       SHM_NAME,
+       {
+               (void *)UNDEFINE_BASE_ADDR,
+               &undefine_mem_addr,
+               UNDEFINE_MEM_SIZE,
+               (sizeof(metal_phys_addr_t) << 3),
+               (unsigned long)(-1),
+               0,
+               {NULL},
+       },
+       {NULL, NULL},
+};
+
+/**
+ * This funciton is to install baremeta/RTOS libmetal devices.
+ */
+extern char RPROC_DEBUG[];
+int platform_register_metal_device(void)
+{
+       int i;
+       int ret;
+       struct metal_device *dev;
+
+       /* Register device */
+       metal_bus_register(&metal_generic_bus);
+       for (i = 0;
+            i < (int)(sizeof(metal_dev_table)/sizeof(struct metal_device));
+            i++) {
+               dev = &metal_dev_table[i];
+               ret = metal_register_generic_device(dev);
+               if (ret)
+                       return ret;
+       }
+
+       /* Register shared memory */
+       metal_shmem_register_generic(&shm);
+
+       return 0;
+}
+