blob: 99239f95b961d36d30614bc4de95febacb38a6bd [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Dan Handleye83b0ca2014-01-14 18:17:09 +00002 * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <string.h>
32#include <assert.h>
33#include <arch_helpers.h>
34#include <platform.h>
35#include <bl_common.h>
36/* Included only for error codes */
37#include <psci.h>
James Morrissey40a6f642014-02-10 14:24:36 +000038#include "debug.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010039
40unsigned char platform_normal_stacks[PLATFORM_STACK_SIZE][PLATFORM_CORE_COUNT]
41__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE),
42 section("tzfw_normal_stacks")));
43
44/*******************************************************************************
45 * This array holds the characteristics of the differences between the three
46 * FVP platforms (Base, A53_A57 & Foundation). It will be populated during cold
47 * boot at each boot stage by the primary before enabling the MMU (to allow cci
48 * configuration) & used thereafter. Each BL will have its own copy to allow
49 * independent operation.
50 ******************************************************************************/
51static unsigned long platform_config[CONFIG_LIMIT];
52
53/*******************************************************************************
Achin Guptaa0cd9892014-02-09 13:30:38 +000054 * An internal global pointer of the level 1 translation tables which should not
55 * change once setup by the primary cpu during a cold boot.
Achin Gupta4f6ad662013-10-25 09:08:21 +010056 *******************************************************************************/
Achin Guptaa0cd9892014-02-09 13:30:38 +000057unsigned long l1_xlation_table __aligned(PLATFORM_CACHE_LINE_SIZE)
58__attribute__ ((section("tzfw_coherent_mem")));
Achin Gupta4f6ad662013-10-25 09:08:21 +010059
60/*******************************************************************************
61 * Enable the MMU assuming that the pagetables have already been created
62 *******************************************************************************/
63void enable_mmu()
64{
65 unsigned long mair, tcr, ttbr, sctlr;
66 unsigned long current_el = read_current_el();
Achin Guptaa0cd9892014-02-09 13:30:38 +000067#if DEBUG
68 unsigned int l1_table_desc_bits;
69 unsigned int l1_table_align;
70#endif
Achin Gupta4f6ad662013-10-25 09:08:21 +010071
72 /* Set the attributes in the right indices of the MAIR */
73 mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
74 mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
75 ATTR_IWBWA_OWBWA_NTR_INDEX);
76 write_mair(mair);
77
78 /*
79 * Set TCR bits as well. Inner & outer WBWA & shareable + T0SZ = 32
80 */
81 tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA |
82 TCR_RGN_INNER_WBA | TCR_T0SZ_4GB;
83 if (GET_EL(current_el) == MODE_EL3) {
84 tcr |= TCR_EL3_RES1;
Sandrine Bailleux295538b2013-11-15 14:46:44 +000085 /* Invalidate EL3 TLBs */
Achin Gupta4f6ad662013-10-25 09:08:21 +010086 tlbialle3();
87 } else {
88 /* Invalidate EL1 TLBs */
89 tlbivmalle1();
90 }
91
92 write_tcr(tcr);
93
Achin Guptaa0cd9892014-02-09 13:30:38 +000094 /* Set TTBR bits. Ensure the alignment for level 1 page table */
95#if DEBUG
96#define BITS_PER_4K_L3DESC 12
97#define BITS_PER_4K_L2DESC (9 + BITS_PER_4K_L3DESC)
98#define BITS_PER_4K_L1DESC (9 + BITS_PER_4K_L2DESC)
99 l1_table_desc_bits = (64 - TCR_T0SZ_4GB - BITS_PER_4K_L1DESC);
100 l1_table_align = l1_table_desc_bits + 3;
101 assert(((unsigned long) l1_xlation_table &
102 ((1 << l1_table_align) - 1)) == 0);
103#endif
Achin Gupta4f6ad662013-10-25 09:08:21 +0100104 ttbr = (unsigned long) l1_xlation_table;
105 write_ttbr0(ttbr);
106
107 sctlr = read_sctlr();
108 sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT | SCTLR_I_BIT;
109 sctlr |= SCTLR_A_BIT | SCTLR_C_BIT;
110 write_sctlr(sctlr);
111
112 return;
113}
114
115void disable_mmu(void)
116{
117 /* Zero out the MMU related registers */
118 write_mair(0);
119 write_tcr(0);
120 write_ttbr0(0);
121 write_sctlr(0);
122
Achin Gupta4f6ad662013-10-25 09:08:21 +0100123 /* Flush the caches */
124 dcsw_op_all(DCCISW);
125
126 return;
127}
128
129/*******************************************************************************
130 * Setup the pagetables as per the platform memory map & initialize the mmu
131 *******************************************************************************/
132void configure_mmu(meminfo *mem_layout,
133 unsigned long ro_start,
134 unsigned long ro_limit,
135 unsigned long coh_start,
136 unsigned long coh_limit)
137{
Sandrine Bailleux8d69a032013-11-27 09:38:52 +0000138 assert(IS_PAGE_ALIGNED(ro_start));
139 assert(IS_PAGE_ALIGNED(ro_limit));
140 assert(IS_PAGE_ALIGNED(coh_start));
141 assert(IS_PAGE_ALIGNED(coh_limit));
142
Achin Guptaa0cd9892014-02-09 13:30:38 +0000143 l1_xlation_table = fill_xlation_tables(mem_layout,
144 ro_start,
145 ro_limit,
146 coh_start,
147 coh_limit);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100148 enable_mmu();
149 return;
150}
151
152/* Simple routine which returns a configuration variable value */
153unsigned long platform_get_cfgvar(unsigned int var_id)
154{
155 assert(var_id < CONFIG_LIMIT);
156 return platform_config[var_id];
157}
158
159/*******************************************************************************
160 * A single boot loader stack is expected to work on both the Foundation FVP
161 * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
162 * SYS_ID register provides a mechanism for detecting the differences between
163 * these platforms. This information is stored in a per-BL array to allow the
164 * code to take the correct path.Per BL platform configuration.
165 ******************************************************************************/
166int platform_config_setup(void)
167{
168 unsigned int rev, hbi, bld, arch, sys_id, midr_pn;
169
170 sys_id = mmio_read_32(VE_SYSREGS_BASE + V2M_SYS_ID);
171 rev = (sys_id >> SYS_ID_REV_SHIFT) & SYS_ID_REV_MASK;
172 hbi = (sys_id >> SYS_ID_HBI_SHIFT) & SYS_ID_HBI_MASK;
173 bld = (sys_id >> SYS_ID_BLD_SHIFT) & SYS_ID_BLD_MASK;
174 arch = (sys_id >> SYS_ID_ARCH_SHIFT) & SYS_ID_ARCH_MASK;
175
James Morrissey40a6f642014-02-10 14:24:36 +0000176 if ((rev != REV_FVP) || (arch != ARCH_MODEL))
177 panic();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100178
179 /*
180 * The build field in the SYS_ID tells which variant of the GIC
181 * memory is implemented by the model.
182 */
183 switch (bld) {
184 case BLD_GIC_VE_MMAP:
185 platform_config[CONFIG_GICD_ADDR] = VE_GICD_BASE;
186 platform_config[CONFIG_GICC_ADDR] = VE_GICC_BASE;
187 platform_config[CONFIG_GICH_ADDR] = VE_GICH_BASE;
188 platform_config[CONFIG_GICV_ADDR] = VE_GICV_BASE;
189 break;
190 case BLD_GIC_A53A57_MMAP:
191 platform_config[CONFIG_GICD_ADDR] = BASE_GICD_BASE;
192 platform_config[CONFIG_GICC_ADDR] = BASE_GICC_BASE;
193 platform_config[CONFIG_GICH_ADDR] = BASE_GICH_BASE;
194 platform_config[CONFIG_GICV_ADDR] = BASE_GICV_BASE;
195 break;
196 default:
197 assert(0);
198 }
199
200 /*
201 * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010
202 * for the Foundation FVP.
203 */
204 switch (hbi) {
205 case HBI_FOUNDATION:
206 platform_config[CONFIG_MAX_AFF0] = 4;
207 platform_config[CONFIG_MAX_AFF1] = 1;
208 platform_config[CONFIG_CPU_SETUP] = 0;
209 platform_config[CONFIG_BASE_MMAP] = 0;
Harry Liebel30affd52013-10-30 17:41:48 +0000210 platform_config[CONFIG_HAS_CCI] = 0;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100211 break;
212 case HBI_FVP_BASE:
213 midr_pn = (read_midr() >> MIDR_PN_SHIFT) & MIDR_PN_MASK;
214 if ((midr_pn == MIDR_PN_A57) || (midr_pn == MIDR_PN_A53))
215 platform_config[CONFIG_CPU_SETUP] = 1;
216 else
217 platform_config[CONFIG_CPU_SETUP] = 0;
218
219 platform_config[CONFIG_MAX_AFF0] = 4;
220 platform_config[CONFIG_MAX_AFF1] = 2;
221 platform_config[CONFIG_BASE_MMAP] = 1;
Harry Liebel30affd52013-10-30 17:41:48 +0000222 platform_config[CONFIG_HAS_CCI] = 1;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100223 break;
224 default:
225 assert(0);
226 }
227
228 return 0;
229}
230
Ian Spray84687392014-01-02 16:57:12 +0000231unsigned long plat_get_ns_image_entrypoint(void)
232{
Achin Gupta4f6ad662013-10-25 09:08:21 +0100233 return NS_IMAGE_OFFSET;
234}