blob: 3df15b7841d264bac19618e4bb625a6594bf3b32 [file] [log] [blame]
Aaron Durbineeacf742014-07-10 15:05:13 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20
21#include <arch/io.h>
22#include <stdlib.h>
23#include <console/console.h>
24#include <soc/addressmap.h>
Aaron Durbin5f66b522014-07-14 15:00:41 -050025#include <soc/id.h>
Aaron Durbineeacf742014-07-10 15:05:13 -050026#include "mc.h"
27#include "sdram.h"
28
Aaron Durbin7ddb5f72014-07-21 14:24:42 -050029static uintptr_t tz_base_mib;
30static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB;
31
Aaron Durbineeacf742014-07-10 15:05:13 -050032/* returns total amount of DRAM (in MB) from memory controller registers */
33int sdram_size_mb(void)
34{
35 struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
36 static int total_size = 0;
37
38 if (total_size)
39 return total_size;
40
41 /*
42 * This obtains memory size from the External Memory Aperture
43 * Configuration register. Nvidia confirmed that it is safe to assume
44 * this value represents the total physical DRAM size.
45 */
46 total_size = (read32(&mc->emem_cfg) >> MC_EMEM_CFG_SIZE_MB_SHIFT) &
47 MC_EMEM_CFG_SIZE_MB_MASK;
48
Aaron Durbineeacf742014-07-10 15:05:13 -050049 return total_size;
50}
51
Aaron Durbinf13c5672014-07-11 15:56:31 -050052static void carveout_from_regs(uintptr_t *base_mib, size_t *size_mib,
53 uint32_t bom, uint32_t bom_hi, uint32_t size)
Aaron Durbineeacf742014-07-10 15:05:13 -050054{
Aaron Durbinf13c5672014-07-11 15:56:31 -050055
56 /* All size regs of carveouts are in MiB. */
57 if (size == 0)
58 return;
59
60 *size_mib = size;
61 bom >>= 20;
Aaron Durbin4185f9b2014-08-12 10:38:16 -050062 bom |= bom_hi << (32 - 20);
Aaron Durbinf13c5672014-07-11 15:56:31 -050063
64 *base_mib = bom;
65}
66
67void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib)
68{
69 *base_mib = 0;
70 *size_mib = 0;
71 struct tegra_mc_regs * const mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
72
73 switch (id) {
74 case CARVEOUT_TZ:
Aaron Durbin7ddb5f72014-07-21 14:24:42 -050075 *base_mib = tz_base_mib;
76 *size_mib = tz_size_mib;
Aaron Durbinf13c5672014-07-11 15:56:31 -050077 break;
78 case CARVEOUT_SEC:
79 carveout_from_regs(base_mib, size_mib,
80 read32(&mc->sec_carveout_bom),
81 read32(&mc->sec_carveout_adr_hi),
82 read32(&mc->sec_carveout_size_mb));
83 break;
84 case CARVEOUT_MTS:
85 carveout_from_regs(base_mib, size_mib,
86 read32(&mc->mts_carveout_bom),
87 read32(&mc->mts_carveout_adr_hi),
88 read32(&mc->mts_carveout_size_mb));
89 break;
90 case CARVEOUT_VPR:
91 carveout_from_regs(base_mib, size_mib,
92 read32(&mc->video_protect_bom),
93 read32(&mc->video_protect_bom_adr_hi),
94 read32(&mc->video_protect_size_mb));
95 break;
96 default:
97 break;
98 }
99}
100
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500101static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib,
102 int ignore_tz)
Aaron Durbinf13c5672014-07-11 15:56:31 -0500103{
104 uintptr_t base;
105 uintptr_t end;
106 int i;
107
108 base = CONFIG_SYS_SDRAM_BASE / MiB;
109 end = base + sdram_size_mb();
110
Aaron Durbinb397f012014-07-15 13:13:51 -0500111 /* Requested limits out of range. */
112 if (*end_mib <= base || *base_mib >= end) {
113 *end_mib = *base_mib = 0;
114 return;
115 }
116
117 /* Clip region to passed in limits. */
118 if (*end_mib < end)
119 end = *end_mib;
120 if (*base_mib > base)
121 base = *base_mib;
Aaron Durbinf13c5672014-07-11 15:56:31 -0500122
123 for (i = 0; i < CARVEOUT_NUM; i++) {
124 uintptr_t carveout_base;
Aaron Durbinb397f012014-07-15 13:13:51 -0500125 uintptr_t carveout_end;
Aaron Durbinf13c5672014-07-11 15:56:31 -0500126 size_t carveout_size;
127
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500128 if (i == CARVEOUT_TZ && ignore_tz)
129 continue;
130
Aaron Durbinf13c5672014-07-11 15:56:31 -0500131 carveout_range(i, &carveout_base, &carveout_size);
132
133 if (carveout_size == 0)
134 continue;
135
Aaron Durbinb397f012014-07-15 13:13:51 -0500136 carveout_end = carveout_base + carveout_size;
137
Aaron Durbinf13c5672014-07-11 15:56:31 -0500138 /* Bypass carveouts out of requested range. */
Aaron Durbinb397f012014-07-15 13:13:51 -0500139 if (carveout_base >= end || carveout_end <= base)
Aaron Durbinf13c5672014-07-11 15:56:31 -0500140 continue;
141
142 /*
143 * This is crude, but the assumption is that carveouts live
144 * at the upper range of physical memory. Therefore, update
145 * the end address to be equal to the base of the carveout.
146 */
147 end = carveout_base;
148 }
149
150 *base_mib = base;
151 *end_mib = end;
152}
153
Aaron Durbinb397f012014-07-15 13:13:51 -0500154void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
155{
156 *base_mib = 0;
157 *end_mib = 4096;
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500158 memory_in_range(base_mib, end_mib, 0);
Aaron Durbinb397f012014-07-15 13:13:51 -0500159}
160
161void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
162{
163 *base_mib = 4096;
164 *end_mib = ~0UL;
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500165 memory_in_range(base_mib, end_mib, 0);
Aaron Durbinb397f012014-07-15 13:13:51 -0500166}
167
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500168void trustzone_region_init(void)
169{
170 struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
171 uintptr_t end = 4096;
172
173 /* Already has been initialized. */
174 if (tz_size_mib != 0 && tz_base_mib != 0)
175 return;
176
177 /*
178 * Get memory layout below 4GiB ignoring the TZ carveout because
179 * that's the one to initialize.
180 */
181 memory_in_range(&tz_base_mib, &end, 1);
182 tz_base_mib = end - tz_size_mib;
183
184 /* AVP cannot set the TZ registers proper as it is always non-secure. */
185 if (context_avp())
186 return;
187
188 /* Set the carveout region. */
189 write32(tz_base_mib << 20, &mc->security_cfg0);
190 write32(tz_size_mib, &mc->security_cfg1);
191}