tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / soc / nvidia / tegra132 / addressmap.c
blobc71c7b2e6ae1767f3916301b204b4174bfc799eb
1 /*
2 * This file is part of the coreboot project.
4 * Copyright 2014 Google Inc.
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.
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.
17 #include <arch/io.h>
18 #include <console/console.h>
19 #include <soc/addressmap.h>
20 #include <soc/id.h>
21 #include <soc/mc.h>
22 #include <soc/sdram.h>
23 #include <stdlib.h>
24 #include <symbols.h>
26 static uintptr_t tz_base_mib;
27 static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB;
29 /* returns total amount of DRAM (in MB) from memory controller registers */
30 int sdram_size_mb(void)
32 struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
33 static int total_size = 0;
35 if (total_size)
36 return total_size;
39 * This obtains memory size from the External Memory Aperture
40 * Configuration register. Nvidia confirmed that it is safe to assume
41 * this value represents the total physical DRAM size.
43 total_size = (read32(&mc->emem_cfg) >> MC_EMEM_CFG_SIZE_MB_SHIFT) &
44 MC_EMEM_CFG_SIZE_MB_MASK;
46 return total_size;
49 static void carveout_from_regs(uintptr_t *base_mib, size_t *size_mib,
50 uint32_t bom, uint32_t bom_hi, uint32_t size)
53 /* All size regs of carveouts are in MiB. */
54 if (size == 0)
55 return;
57 *size_mib = size;
58 bom >>= 20;
59 bom |= bom_hi << (32 - 20);
61 *base_mib = bom;
64 void carveout_range(int id, uintptr_t *base_mib, size_t *size_mib)
66 *base_mib = 0;
67 *size_mib = 0;
68 struct tegra_mc_regs * const mc = (struct tegra_mc_regs *)TEGRA_MC_BASE;
70 switch (id) {
71 case CARVEOUT_TZ:
72 *base_mib = tz_base_mib;
73 *size_mib = tz_size_mib;
74 break;
75 case CARVEOUT_SEC:
76 carveout_from_regs(base_mib, size_mib,
77 read32(&mc->sec_carveout_bom),
78 read32(&mc->sec_carveout_adr_hi),
79 read32(&mc->sec_carveout_size_mb));
80 break;
81 case CARVEOUT_MTS:
82 carveout_from_regs(base_mib, size_mib,
83 read32(&mc->mts_carveout_bom),
84 read32(&mc->mts_carveout_adr_hi),
85 read32(&mc->mts_carveout_size_mb));
86 break;
87 case CARVEOUT_VPR:
88 carveout_from_regs(base_mib, size_mib,
89 read32(&mc->video_protect_bom),
90 read32(&mc->video_protect_bom_adr_hi),
91 read32(&mc->video_protect_size_mb));
92 break;
93 default:
94 break;
98 static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib,
99 int ignore_tz)
101 uintptr_t base;
102 uintptr_t end;
103 int i;
105 base = (uintptr_t)_dram / MiB;
106 end = base + sdram_size_mb();
108 /* Requested limits out of range. */
109 if (*end_mib <= base || *base_mib >= end) {
110 *end_mib = *base_mib = 0;
111 return;
114 /* Clip region to passed in limits. */
115 if (*end_mib < end)
116 end = *end_mib;
117 if (*base_mib > base)
118 base = *base_mib;
120 for (i = 0; i < CARVEOUT_NUM; i++) {
121 uintptr_t carveout_base;
122 uintptr_t carveout_end;
123 size_t carveout_size;
125 if (i == CARVEOUT_TZ && ignore_tz)
126 continue;
128 carveout_range(i, &carveout_base, &carveout_size);
130 if (carveout_size == 0)
131 continue;
133 carveout_end = carveout_base + carveout_size;
135 /* Bypass carveouts out of requested range. */
136 if (carveout_base >= end || carveout_end <= base)
137 continue;
140 * This is crude, but the assumption is that carveouts live
141 * at the upper range of physical memory. Therefore, update
142 * the end address to be equal to the base of the carveout.
144 end = carveout_base;
147 *base_mib = base;
148 *end_mib = end;
151 void memory_in_range_below_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
153 *base_mib = 0;
154 *end_mib = 4096;
155 memory_in_range(base_mib, end_mib, 0);
158 void memory_in_range_above_4gb(uintptr_t *base_mib, uintptr_t *end_mib)
160 *base_mib = 4096;
161 *end_mib = ~0UL;
162 memory_in_range(base_mib, end_mib, 0);
165 void trustzone_region_init(void)
167 struct tegra_mc_regs * const mc = (void *)(uintptr_t)TEGRA_MC_BASE;
168 uintptr_t end = 4096;
170 /* Already has been initialized. */
171 if (tz_size_mib != 0 && tz_base_mib != 0)
172 return;
175 * Get memory layout below 4GiB ignoring the TZ carveout because
176 * that's the one to initialize.
178 memory_in_range(&tz_base_mib, &end, 1);
179 tz_base_mib = end - tz_size_mib;
181 /* AVP cannot set the TZ registers proper as it is always non-secure. */
182 if (context_avp())
183 return;
185 /* Set the carveout region. */
186 write32(&mc->security_cfg0, tz_base_mib << 20);
187 write32(&mc->security_cfg1, tz_size_mib);
189 /* Enable SMMU translations */
190 write32(&mc->smmu_config, MC_SMMU_CONFIG_ENABLE);