1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(GD_GPL)
9 */
10
11#include <config.h>
12#include <machine/assembler.h>
13#include <arch/machine/hardware.h>
14#include <arch/machine/registerset.h>
15#include <util.h>
16
17#ifndef ALLOW_UNALIGNED_ACCESS
18#define ALLOW_UNALIGNED_ACCESS 1
19#endif
20
21#if ALLOW_UNALIGNED_ACCESS
22#define CR_ALIGN_SET     BIT(CONTROL_U)
23#define CR_ALIGN_CLEAR   BIT(CONTROL_A)
24#else
25#define CR_ALIGN_SET     BIT(CONTROL_A)
26#define CR_ALIGN_CLEAR   BIT(CONTROL_U)
27#endif
28
29#ifndef CONFIG_DEBUG_DISABLE_L1_ICACHE
30    #define CR_L1_ICACHE_SET   BIT(CONTROL_I)
31    #define CR_L1_ICACHE_CLEAR 0
32#else
33    #define CR_L1_ICACHE_SET   0
34    #define CR_L1_ICACHE_CLEAR BIT(CONTROL_I)
35#endif
36
37#ifndef CONFIG_DEBUG_DISABLE_L1_DCACHE
38    #define CR_L1_DCACHE_SET   BIT(CONTROL_C)
39    #define CR_L1_DCACHE_CLEAR 0
40#else
41    #define CR_L1_DCACHE_SET   0
42    #define CR_L1_DCACHE_CLEAR BIT(CONTROL_C)
43#endif
44
45#ifndef CONFIG_DEBUG_DISABLE_BRANCH_PREDICTION
46    #define CR_BRANCH_PREDICTION_SET   BIT(CONTROL_Z)
47    #define CR_BRANCH_PREDICTION_CLEAR 0
48#else
49    #define CR_BRANCH_PREDICTION_SET   0
50    #define CR_BRANCH_PREDICTION_CLEAR BIT(CONTROL_Z)
51#endif
52
53#define CR_BITS_SET    (CR_ALIGN_SET | \
54                        CR_L1_ICACHE_SET | \
55                        CR_L1_DCACHE_SET | \
56                        BIT(CONTROL_M) | \
57                        CR_BRANCH_PREDICTION_SET | \
58                        BIT(CONTROL_V) | \
59                        BIT(CONTROL_XP))
60
61#define CR_BITS_CLEAR  (CR_ALIGN_CLEAR | \
62                        CR_L1_ICACHE_CLEAR | \
63                        CR_L1_DCACHE_CLEAR | \
64                        CR_BRANCH_PREDICTION_CLEAR | \
65                        BIT(CONTROL_B) | \
66                        BIT(CONTROL_S) | \
67                        BIT(CONTROL_R) | \
68                        BIT(CONTROL_VE) | \
69                        BIT(CONTROL_RR) | \
70                        BIT(CONTROL_EE) | \
71                        BIT(CONTROL_TRE) | \
72                        BIT(CONTROL_AP))
73
74/*
75 * Entry point of the kernel ELF image.
76 * R0-R3 contain parameters that are passed to init_kernel().
77 */
78
79.code 32
80.section .boot.text, "ax"
81BEGIN_FUNC(_start)
82
83    /* Supervisor/hypervisor mode, interrupts disabled */
84    ldr r5, =CPSR_KERNEL
85    msr cpsr_fc, r5
86
87    /* Initialise CP15 control register */
88#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
89    mrc p15, 4, r4, c1, c0, 0
90#else
91    mrc p15, 0, r4, c1, c0, 0
92#endif
93    ldr r5, =CR_BITS_SET
94    ldr r6, =CR_BITS_CLEAR
95    orr r4, r4, r5
96    bic r4, r4, r6
97#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
98    mcr p15, 4, r4, c1, c0, 0
99
100    /* Initialise vector base */
101    ldr r4, =PPTR_VECTOR_TABLE
102    mcr p15, 4, r4, c12, c0, 0
103#else
104    mcr p15, 0, r4, c1, c0, 0
105#endif
106
107#if defined(CONFIG_ARM_CORTEX_A9) && defined(CONFIG_ENABLE_A9_PREFETCHER)
108    /* Set bit 2 in the ACTLR, which on the cortex-a9 is the l1 prefetch enable
109     * bit. See section 4.3.10 of the Cortex-A9 Technical Reference Manual */
110    mrc p15, 0, r4, c1, c0, 1
111    ldr r5, =BIT(2)
112    orr r4, r4, r5
113    mcr p15, 0, r4, c1, c0, 1
114#endif
115
116#if defined(CONFIG_PLAT_HIKEY)
117    /* Prefetcher configuration */
118   mrrc p15, 0, r4, r5, c15
119   ldr r6, =PREFETCHER_MASK
120   bic r4, r4, r6
121   ldr r6, =PREFETCHER
122   orr r4, r4, r6
123   mcrr p15, 0, r4, r5, c15
124#endif
125
126     /* Load kernel stack pointer
127      * On ARM SMP, kernel_stack_alloc is indexed by CPU ID
128      * to get different stacks for each core
129      */
130    ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS)
131
132#ifdef ENABLE_SMP_SUPPORT
133    /*
134     * Read MPIDR in r4
135     * See ARM Referce Manual (ARMv7-A and ARMv7-R edition), Section B4.1.106
136     * for more details about MPIDR register.
137     */
138    mrc p15, 0, r4, c0, c0, 5
139    and r4, r4, #0xff
140    /* Set the sp for each core assuming linear indices */
141    ldr     r5, =BIT(CONFIG_KERNEL_STACK_BITS)
142    mul     r5, r4
143    add     sp, sp, r5
144#endif /* ENABLE_SMP_SUPPORT */
145
146    /* Attempt to workaround any known ARM errata. */
147    push {r0-r3}
148    blx arm_errata
149    pop {r0-r3}
150
151    /* Hyp kernel always run in Hyp mode. */
152#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT
153    /* Initialise ABORT stack pointer */
154    cps #PMODE_ABORT
155    ldr sp, =_breakpoint_stack_top
156    cps #PMODE_SUPERVISOR
157#endif
158
159    /* Call bootstrapping implemented in C */
160    blx init_kernel
161
162    /* Restore the initial thread */
163    b restore_user_context
164
165END_FUNC(_start)
166