blob: 65371872fe29a80e305784f5ba190da0bf7d1956 [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 Durbinf13c5672014-07-11 15:56:31 -050025#include <soc/display.h>
Aaron Durbin5f66b522014-07-14 15:00:41 -050026#include <soc/id.h>
Aaron Durbineeacf742014-07-10 15:05:13 -050027#include "mc.h"
28#include "sdram.h"
29
Aaron Durbin7ddb5f72014-07-21 14:24:42 -050030static uintptr_t tz_base_mib;
31static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB;
32
Aaron Durbineeacf742014-07-10 15:05:13 -050033/* returns total amount of DRAM (in MB) from memory controller registers */
34int sdram_size_mb(void)
35{
36 struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
37 static int total_size = 0;
38
39 if (total_size)
40 return total_size;
41
42 /*
43 * This obtains memory size from the External Memory Aperture
44 * Configuration register. Nvidia confirmed that it is safe to assume
45 * this value represents the total physical DRAM size.
46 */
47 total_size = (read32(&mc->emem_cfg) >> MC_EMEM_CFG_SIZE_MB_SHIFT) &
48 MC_EMEM_CFG_SIZE_MB_MASK;
49
50 printk(BIOS_DEBUG, "%s: Total SDRAM (MB): %u\n", __func__, total_size);
51 return total_size;
52}
53
Aaron Durbinf13c5672014-07-11 15:56:31 -050054static void carveout_from_regs(uintptr_t *base_mib, size_t *size_mib,
55 uint32_t bom, uint32_t bom_hi, uint32_t size)
Aaron Durbineeacf742014-07-10 15:05:13 -050056{
Aaron Durbinf13c5672014-07-11 15:56:31 -050057
58 /* All size regs of carveouts are in MiB. */
59 if (size == 0)
60 return;
61
62 *size_mib = size;
63 bom >>= 20;
64 bom |= bom_hi >> (32 - 20);
65
66 *base_mib = bom;
67}
68
69void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib)
70{
71 *base_mib = 0;
72 *size_mib = 0;
73 struct tegra_mc_regs * const mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
74
75 switch (id) {
76 case CARVEOUT_TZ:
Aaron Durbin7ddb5f72014-07-21 14:24:42 -050077 *base_mib = tz_base_mib;
78 *size_mib = tz_size_mib;
Aaron Durbinf13c5672014-07-11 15:56:31 -050079 break;
80 case CARVEOUT_SEC:
81 carveout_from_regs(base_mib, size_mib,
82 read32(&mc->sec_carveout_bom),
83 read32(&mc->sec_carveout_adr_hi),
84 read32(&mc->sec_carveout_size_mb));
85 break;
86 case CARVEOUT_MTS:
87 carveout_from_regs(base_mib, size_mib,
88 read32(&mc->mts_carveout_bom),
89 read32(&mc->mts_carveout_adr_hi),
90 read32(&mc->mts_carveout_size_mb));
91 break;
92 case CARVEOUT_VPR:
93 carveout_from_regs(base_mib, size_mib,
94 read32(&mc->video_protect_bom),
95 read32(&mc->video_protect_bom_adr_hi),
96 read32(&mc->video_protect_size_mb));
97 break;
98 default:
99 break;
100 }
101}
102
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500103static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib,
104 int ignore_tz)
Aaron Durbinf13c5672014-07-11 15:56:31 -0500105{
106 uintptr_t base;
107 uintptr_t end;
108 int i;
109
110 base = CONFIG_SYS_SDRAM_BASE / MiB;
111 end = base + sdram_size_mb();
112
Aaron Durbinb397f012014-07-15 13:13:51 -0500113 /* Requested limits out of range. */
114 if (*end_mib <= base || *base_mib >= end) {
115 *end_mib = *base_mib = 0;
116 return;
117 }
118
119 /* Clip region to passed in limits. */
120 if (*end_mib < end)
121 end = *end_mib;
122 if (*base_mib > base)
123 base = *base_mib;
Aaron Durbinf13c5672014-07-11 15:56:31 -0500124
125 for (i = 0; i < CARVEOUT_NUM; i++) {
126 uintptr_t carveout_base;
Aaron Durbinb397f012014-07-15 13:13:51 -0500127 uintptr_t carveout_end;
Aaron Durbinf13c5672014-07-11 15:56:31 -0500128 size_t carveout_size;
129
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500130 if (i == CARVEOUT_TZ && ignore_tz)
131 continue;
132
Aaron Durbinf13c5672014-07-11 15:56:31 -0500133 carveout_range(i, &carveout_base, &carveout_size);
134
135 if (carveout_size == 0)
136 continue;
137
Aaron Durbinb397f012014-07-15 13:13:51 -0500138 carveout_end = carveout_base + carveout_size;
139
Aaron Durbinf13c5672014-07-11 15:56:31 -0500140 /* Bypass carveouts out of requested range. */
Aaron Durbinb397f012014-07-15 13:13:51 -0500141 if (carveout_base >= end || carveout_end <= base)
Aaron Durbinf13c5672014-07-11 15:56:31 -0500142 continue;
143
144 /*
145 * This is crude, but the assumption is that carveouts live
146 * at the upper range of physical memory. Therefore, update
147 * the end address to be equal to the base of the carveout.
148 */
149 end = carveout_base;
150 }
151
152 *base_mib = base;
153 *end_mib = end;
154}
155
Aaron Durbinb397f012014-07-15 13:13:51 -0500156void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
157{
158 *base_mib = 0;
159 *end_mib = 4096;
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500160 memory_in_range(base_mib, end_mib, 0);
Aaron Durbinb397f012014-07-15 13:13:51 -0500161}
162
163void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
164{
165 *base_mib = 4096;
166 *end_mib = ~0UL;
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500167 memory_in_range(base_mib, end_mib, 0);
Aaron Durbinb397f012014-07-15 13:13:51 -0500168}
169
Aaron Durbinf13c5672014-07-11 15:56:31 -0500170uintptr_t framebuffer_attributes(size_t *size_mib)
171{
172 uintptr_t begin;
173 uintptr_t end;
174
175 /* Place the framebuffer just below the 32-bit addressable limit. */
Aaron Durbinb397f012014-07-15 13:13:51 -0500176 memory_in_range_below_4gb(&begin, &end);
Aaron Durbinf13c5672014-07-11 15:56:31 -0500177
178 *size_mib = FB_SIZE_MB;
179 end -= *size_mib;
180
181 return end;
Aaron Durbineeacf742014-07-10 15:05:13 -0500182}
Aaron Durbin7ddb5f72014-07-21 14:24:42 -0500183
184void trustzone_region_init(void)
185{
186 struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
187 uintptr_t end = 4096;
188
189 /* Already has been initialized. */
190 if (tz_size_mib != 0 && tz_base_mib != 0)
191 return;
192
193 /*
194 * Get memory layout below 4GiB ignoring the TZ carveout because
195 * that's the one to initialize.
196 */
197 memory_in_range(&tz_base_mib, &end, 1);
198 tz_base_mib = end - tz_size_mib;
199
200 /* AVP cannot set the TZ registers proper as it is always non-secure. */
201 if (context_avp())
202 return;
203
204 /* Set the carveout region. */
205 write32(tz_base_mib << 20, &mc->security_cfg0);
206 write32(tz_size_mib, &mc->security_cfg1);
207}