537446dea1c17d44fad495bb13dbeb87a76065cb
[processor-sdk/open-amp.git] / apps / system / generic / machine / zynq7 / helper.c
1 /*
2  * Copyright (c) 2014, Mentor Graphics Corporation
3  * All rights reserved.
4  *
5  * Copyright (c) 2015 Xilinx, Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include <string.h>
32 #include "baremetal.h"
33 #include "metal/sys.h"
35 #ifndef BAREMETAL_MASTER
36 #define BAREMETAL_MASTER 0
37 #endif
39 /* Memory Regions for MMU Mapping */
40 #if (BAREMETAL_MASTER == 1)
42 #define ELF_START       0x10000000      /* Image entry point address */
43 #define ELF_END         0x0FE00000      /* size of code,data,heap and stack sections */
45 #define TLB_MEM_START   0x1FE00000      /* Address of TLB memory */
47 #else
49 #define ELF_START       0x00000000      /* Image entry point address */
50 #define ELF_END         0x08000000      /* size of code,data,heap and stack sections */
52 #define TLB_MEM_START   0x0FE00000      /* Address of TLB memory */
54 #endif
56 /* The vector table address is the same as image entry point */
57 #define RAM_VECTOR_TABLE_ADDR           ELF_START
59 unsigned char ARM_AR_ISR_IRQ_Data[ARM_AR_ISR_STACK_SIZE];
60 unsigned char ARM_AR_ISR_FIQ_Data[ARM_AR_ISR_STACK_SIZE];
61 unsigned char ARM_AR_ISR_SUP_Stack[ARM_AR_ISR_STACK_SIZE];
62 unsigned char ARM_AR_ISR_SYS_Stack[ARM_AR_ISR_STACK_SIZE];
64 extern void bm_env_isr(int vector);
66 /* IRQ handler */
67 void __attribute__ ((interrupt("IRQ"))) __cs3_isr_irq()
68 {
69         unsigned long raw_irq;
70         int irq_vector;
72         /* Read the Interrupt ACK register */
73         raw_irq = MEM_READ32(INT_GIC_CPU_BASE + INT_GIC_CPU_ACK);
75         /* mask interrupt to get vector */
76         irq_vector = raw_irq & INT_ACK_MASK;
78         bm_env_isr(irq_vector);
80         /* Clear the interrupt */
81         MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_ENDINT, raw_irq);
82 }
84 /* Only applicable for remote/slave node */
85 void zynq7_gic_pr_int_initialize(void)
86 {
88         /* Disable the GIC controller */
89         MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CTRL, 0x00000000);
91         /* Enable the interrupt distributor controller */
92         MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CTRL, INT_DIST_ENABLE);
94         /* Secondary cores  just need to disable their private interrupts */
95         MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_ENABLE_CLEAR + 0x00,
96                     0xffffffff);
97         /* 0  - 31 */
99         MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CONFIG + 0x00, 0xAAAAAAAA);
100         /* 0  - 15 */
101         MEM_WRITE32(INT_GIC_DIST_BASE + INT_GIC_DIST_CONFIG + 0x04, 0xAAAAAAAA);
103         /* Disable the CPU Interface */
104         MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_CTRL, 0x00000000);
106         /* Allow interrupts with more priority (i.e. lower number) than FF */
107         MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_PRIORITY, 0x000000FF);
109         /* No binary point */
110         MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_POINT, 0x00000000);
112         /* Enable the CPU Interface */
113         MEM_WRITE32(INT_GIC_CPU_BASE + INT_GIC_CPU_CTRL, INT_CPU_ENABLE);
116 int zynq7_gic_initialize()
119         unsigned long reg_val;
121         /* Disable architecture interrupts (IRQ and FIQ)
122          * before initialization */
123         ARM_AR_CPSR_CXSF_READ(&reg_val);
124         reg_val |= (0x02 << 6);
125         ARM_AR_CPSR_CXSF_WRITE(reg_val);
127         zynq7_gic_pr_int_initialize();
129         /* Enable architecture Interrupts */
130         ARM_AR_CPSR_CXSF_READ(&reg_val);
131         reg_val &= ~(0x02 << 6);
132         ARM_AR_CPSR_CXSF_WRITE(reg_val);
134         return 0;
137 void arm_arch_install_isr_vector_table(unsigned long addr)
139         unsigned long arch = 0;
140         void *dst_addr;
142         /* Assign destination address of vector table to RAM address */
143         dst_addr = (void *)addr;
144         /* Read Main ID Register (MIRD) */
145         ARM_AR_CP_READ(p15, 0, &arch, c0, c0, 0);
147         /* Check if Cortex-A series of ARMv7 architecture. */
148         if (((arch & MIDR_ARCH_MASK) >> 16) == MIDR_ARCH_ARMV7
149             && ((arch & MIDR_PART_NO_MASK) >> 4)
150             == MIDR_PART_NO_CORTEX_A) {
151                 /* Set vector base address */
152                 ARM_AR_CP_WRITE(p15, 0, dst_addr, c12, c0, 0);
153                 ARM_AR_NOP_EXECUTE();
154                 ARM_AR_NOP_EXECUTE();
155                 ARM_AR_NOP_EXECUTE();
156         }
159 void init_arm_stacks(void)
162         /* Switch to IRQ mode (keeping interrupts disabled) */
163         ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_IRQ_MODE |
164                             ARM_AR_INTERRUPTS_DISABLE_BITS);
166         /* Set IRQ stack pointer */
167         ARM_AR_SP_WRITE(ARM_GE_STK_ALIGN
168                         (&ARM_AR_ISR_IRQ_Data[ARM_AR_ISR_STACK_SIZE - 1]));
170         /* Switch to FIQ mode (keeping interrupts disabled) */
171         ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_FIQ_MODE |
172                             ARM_AR_INTERRUPTS_DISABLE_BITS);
174         /* Set FIQ stack pointer */
175         ARM_AR_SP_WRITE(ARM_GE_STK_ALIGN
176                         (ARM_AR_ISR_FIQ_Data[ARM_AR_ISR_STACK_SIZE - 1]));
178         /* Switch to Supervisor mode (keeping interrupts disabled) */
179         ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_SUP_MODE |
180                             ARM_AR_INTERRUPTS_DISABLE_BITS);
182         /* Set Supervisor stack pointer */
183         ARM_AR_SP_WRITE(ARM_GE_STK_ALIGN
184                         (&ARM_AR_ISR_SUP_Stack[ARM_AR_ISR_STACK_SIZE - 1]));
186         /* Switch to System mode (keeping interrupts disabled) */
187         ARM_AR_CPSR_C_WRITE(ARM_AR_INT_CPSR_SYS_DISABLED);
190 /***********************************************************************
191  *
192  *  arm_ar_mem_enable_mmu
193  *
194  *  Enables MMU and MAP the required memory regions.
195  *
196  ***********************************************************************/
197 int arm_ar_mem_enable_mmu()
199         unsigned int cp15_ctrl_val;
200         void *tlb_mem = (void *)TLB_MEM_START;
202         ARM_AR_MEM_CACHE_ALL_INVALIDATE();
204         /* Read current CP15 control register value */
205         ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
207         /* Clear the V bit(13) to set Normal exception vectors range. */
208         cp15_ctrl_val &= ~(ARM_AR_MEM_CP15_CTRL_V);
210         /* Clear the alignment bit(1) to enable unaligned memory accesses */
211         cp15_ctrl_val &= ~(ARM_AR_MEM_CP15_CTRL_A);
213         /* Write updated CP15 control register value */
214         ARM_AR_CP_WRITE(ARM_AR_CP15, 0, cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
216         ARM_AR_NOP_EXECUTE();
217         ARM_AR_NOP_EXECUTE();
218         ARM_AR_NOP_EXECUTE();
220         /* Check alignment of available memory pointer */
221         if (!(MEM_ALIGNED_CHECK(tlb_mem, ARM_AR_MEM_TTB_SIZE))) {
222                 /* Align the pointer to the required boundary */
223                 tlb_mem = MEM_PTR_ALIGN(tlb_mem, ARM_AR_MEM_TTB_SIZE);
224         }
226         /* Clear the entire translation table */
227         memset(tlb_mem, 0x00, ARM_AR_MEM_TTB_SIZE);
229         /* Set translation table base address */
230         ARM_AR_CP_WRITE(ARM_AR_CP15, 0, tlb_mem, ARM_AR_C2, ARM_AR_C0, 0);
232         ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C2, ARM_AR_C0, 0);
234         /* Map the given memory regions here */
235         arm_ar_map_mem_region(ELF_START, ELF_START, ELF_END, 0, WRITEBACK);
236         arm_ar_map_mem_region((unsigned int)tlb_mem, (unsigned int)tlb_mem,
237                               TLB_SIZE, 0, NOCACHE);
238         arm_ar_map_mem_region(PERIPH_BASE, PERIPH_BASE,
239                               PERIPH_SIZE, 1, NOCACHE);
240         arm_ar_map_mem_region(SLCR_BASE, SLCR_BASE, SLCR_SIZE, 1, NOCACHE);
241         arm_ar_map_mem_region(CPU_BASE, CPU_BASE, CPU_SIZE, 1, NOCACHE);
243         /* Set the domain access for domain D0 */
244         ARM_AR_CP_WRITE(ARM_AR_CP15, 0, ARM_AR_MEM_DOMAIN_D0_MANAGER_ACCESS,
245                         ARM_AR_C3, ARM_AR_C0, 0);
247         ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C3, ARM_AR_C0, 0);
249         /* Invalidate all TLB entries before enabling the MMU */
250         ARM_AR_CP_WRITE(ARM_AR_CP15, 0, 0, ARM_AR_C8, ARM_AR_C7, 0);
252         /* Read current CP15 control register value */
253         ARM_AR_CP_READ(ARM_AR_CP15, 0, &cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
255         /* Set instruction cache enable / data cache enable / MMU enable bits */
256         cp15_ctrl_val |= (ARM_AR_MEM_CP15_CTRL_I | ARM_AR_MEM_CP15_CTRL_C
257                           | ARM_AR_MEM_CP15_CTRL_M | ARM_AR_MEM_CP15_CTRL_Z);
259         /* Write updated CP15 control register value */
260         ARM_AR_CP_WRITE(ARM_AR_CP15, 0, cp15_ctrl_val, ARM_AR_C1, ARM_AR_C0, 0);
262         ARM_AR_NOP_EXECUTE();
263         ARM_AR_NOP_EXECUTE();
264         ARM_AR_NOP_EXECUTE();
266         return 0;
269 void init_system()
271         /* Place the vector table at the image entry point */
272         arm_arch_install_isr_vector_table(RAM_VECTOR_TABLE_ADDR);
274         /* Enable MMU */
275         arm_ar_mem_enable_mmu();
277         /* Initialize ARM stacks */
278         init_arm_stacks();
280         /* Initialize GIC */
281         zynq7_gic_initialize();
284 void cleanup_system()
286         metal_finish();
287         Xil_DCacheInvalidate();
288         Xil_ICacheInvalidate();
289         Xil_DCacheDisable();
290         Xil_ICacheDisable();