1 /* 2 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2019-2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <string.h> 10 11 #include <arch_helpers.h> 12 #include <common/bl_common.h> 13 #include <common/debug.h> 14 #include <lib/mmio.h> 15 #include <lib/utils.h> 16 #include <lib/xlat_tables/xlat_tables_v2.h> 17 18 #include <mce.h> 19 #include <memctrl.h> 20 #include <memctrl_v2.h> 21 #include <smmu.h> 22 #include <tegra_def.h> 23 #include <tegra_platform.h> 24 #include <tegra_private.h> 25 26 /* Video Memory base and size (live values) */ 27 static uint64_t video_mem_base; 28 static uint64_t video_mem_size_mb; 29 30 /* 31 * Init Memory controller during boot. 32 */ 33 void tegra_memctrl_setup(void) 34 { 35 INFO("Tegra Memory Controller (v2)\n"); 36 37 /* Initialize the System memory management unit */ 38 tegra_smmu_init(); 39 40 /* allow platforms to program custom memory controller settings */ 41 plat_memctrl_setup(); 42 43 /* 44 * All requests at boot time, and certain requests during 45 * normal run time, are physically addressed and must bypass 46 * the SMMU. The client hub logic implements a hardware bypass 47 * path around the Translation Buffer Units (TBU). During 48 * boot-time, the SMMU_BYPASS_CTRL register (which defaults to 49 * TBU_BYPASS mode) will be used to steer all requests around 50 * the uninitialized TBUs. During normal operation, this register 51 * is locked into TBU_BYPASS_SID config, which routes requests 52 * with special StreamID 0x7f on the bypass path and all others 53 * through the selected TBU. This is done to disable SMMU Bypass 54 * mode, as it could be used to circumvent SMMU security checks. 55 */ 56 tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG, 57 MC_SMMU_BYPASS_CONFIG_SETTINGS); 58 } 59 60 /* 61 * Restore Memory Controller settings after "System Suspend" 62 */ 63 void tegra_memctrl_restore_settings(void) 64 { 65 /* restore platform's memory controller settings */ 66 plat_memctrl_restore(); 67 68 /* video memory carveout region */ 69 if (video_mem_base != 0ULL) { 70 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, 71 (uint32_t)video_mem_base); 72 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO) 73 == (uint32_t)video_mem_base); 74 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 75 (uint32_t)(video_mem_base >> 32)); 76 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI) 77 == (uint32_t)(video_mem_base >> 32)); 78 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, 79 (uint32_t)video_mem_size_mb); 80 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB) 81 == (uint32_t)video_mem_size_mb); 82 83 /* 84 * MCE propagates the VideoMem configuration values across the 85 * CCPLEX. 86 */ 87 mce_update_gsc_videomem(); 88 } 89 } 90 91 /* 92 * Secure the BL31 DRAM aperture. 93 * 94 * phys_base = physical base of TZDRAM aperture 95 * size_in_bytes = size of aperture in bytes 96 */ 97 void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) 98 { 99 /* 100 * Perform platform specific steps. 101 */ 102 plat_memctrl_tzdram_setup(phys_base, size_in_bytes); 103 } 104 105 /* 106 * Secure the BL31 TZRAM aperture. 107 * 108 * phys_base = physical base of TZRAM aperture 109 * size_in_bytes = size of aperture in bytes 110 */ 111 void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) 112 { 113 ; /* do nothing */ 114 } 115 116 /* 117 * Save MC settings before "System Suspend" to TZDRAM 118 */ 119 void tegra_mc_save_context(uint64_t mc_ctx_addr) 120 { 121 uint32_t i, num_entries = 0; 122 mc_regs_t *mc_ctx_regs; 123 const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 124 uint64_t tzdram_base = params_from_bl2->tzdram_base; 125 uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size; 126 127 assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end)); 128 129 /* get MC context table */ 130 mc_ctx_regs = plat_memctrl_get_sys_suspend_ctx(); 131 assert(mc_ctx_regs != NULL); 132 133 /* 134 * mc_ctx_regs[0].val contains the size of the context table minus 135 * the last entry. Sanity check the table size before we start with 136 * the context save operation. 137 */ 138 while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) { 139 num_entries++; 140 } 141 142 /* panic if the sizes do not match */ 143 if (num_entries != mc_ctx_regs[0].val) { 144 ERROR("MC context size mismatch!"); 145 panic(); 146 } 147 148 /* save MC register values */ 149 for (i = 1U; i < num_entries; i++) { 150 mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg); 151 } 152 153 /* increment by 1 to take care of the last entry */ 154 num_entries++; 155 156 /* Save MC config settings */ 157 (void)memcpy((void *)mc_ctx_addr, mc_ctx_regs, 158 sizeof(mc_regs_t) * num_entries); 159 160 /* save the MC table address */ 161 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO, 162 (uint32_t)mc_ctx_addr); 163 assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO) 164 == (uint32_t)mc_ctx_addr); 165 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI, 166 (uint32_t)(mc_ctx_addr >> 32)); 167 assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI) 168 == (uint32_t)(mc_ctx_addr >> 32)); 169 } 170 171 static void tegra_lock_videomem_nonoverlap(uint64_t phys_base, 172 uint64_t size_in_bytes) 173 { 174 uint32_t index; 175 uint64_t total_128kb_blocks = size_in_bytes >> 17; 176 uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12; 177 uint64_t val; 178 179 /* 180 * Reset the access configuration registers to restrict access to 181 * old Videomem aperture 182 */ 183 for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0; 184 index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE); 185 index += 4U) { 186 tegra_mc_write_32(index, 0); 187 } 188 189 /* 190 * Set the base. It must be 4k aligned, at least. 191 */ 192 assert((phys_base & (uint64_t)0xFFF) == 0U); 193 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base); 194 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 195 (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK); 196 197 /* 198 * Set the aperture size 199 * 200 * total size = (number of 128KB blocks) + (number of remaining 4KB 201 * blocks) 202 * 203 */ 204 val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) | 205 total_128kb_blocks); 206 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val); 207 208 /* 209 * Lock the configuration settings by enabling TZ-only lock and 210 * locking the configuration against any future changes from NS 211 * world. 212 */ 213 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG, 214 (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT); 215 216 /* 217 * MCE propagates the GSC configuration values across the 218 * CCPLEX. 219 */ 220 } 221 222 static void tegra_unlock_videomem_nonoverlap(void) 223 { 224 /* Clear the base */ 225 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0); 226 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0); 227 228 /* Clear the size */ 229 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0); 230 } 231 232 static void tegra_clear_videomem(uintptr_t non_overlap_area_start, 233 unsigned long long non_overlap_area_size) 234 { 235 int ret; 236 237 INFO("Cleaning previous Video Memory Carveout\n"); 238 239 /* 240 * Map the NS memory first, clean it and then unmap it. 241 */ 242 ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ 243 non_overlap_area_start, /* VA */ 244 non_overlap_area_size, /* size */ 245 MT_DEVICE | MT_RW | MT_NS); /* attrs */ 246 assert(ret == 0); 247 248 zeromem((void *)non_overlap_area_start, non_overlap_area_size); 249 flush_dcache_range(non_overlap_area_start, non_overlap_area_size); 250 251 ret = mmap_remove_dynamic_region(non_overlap_area_start, 252 non_overlap_area_size); 253 assert(ret == 0); 254 } 255 256 static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base, 257 unsigned long size_in_bytes) 258 { 259 uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20); 260 uintptr_t vmem_end_new = phys_base + size_in_bytes; 261 unsigned long long non_overlap_area_size; 262 263 /* 264 * Clear the old regions now being exposed. The following cases 265 * can occur - 266 * 267 * 1. clear whole old region (no overlap with new region) 268 * 2. clear old sub-region below new base 269 * 3. clear old sub-region above new end 270 */ 271 if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) { 272 tegra_clear_videomem(video_mem_base, 273 video_mem_size_mb << 20U); 274 } else { 275 if (video_mem_base < phys_base) { 276 non_overlap_area_size = phys_base - video_mem_base; 277 tegra_clear_videomem(video_mem_base, non_overlap_area_size); 278 } 279 if (vmem_end_old > vmem_end_new) { 280 non_overlap_area_size = vmem_end_old - vmem_end_new; 281 tegra_clear_videomem(vmem_end_new, non_overlap_area_size); 282 } 283 } 284 } 285 286 /* 287 * Program the Video Memory carveout region 288 * 289 * phys_base = physical base of aperture 290 * size_in_bytes = size of aperture in bytes 291 */ 292 void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) 293 { 294 /* 295 * Setup the Memory controller to restrict CPU accesses to the Video 296 * Memory region 297 */ 298 299 INFO("Configuring Video Memory Carveout\n"); 300 301 if (video_mem_base != 0U) { 302 /* 303 * Lock the non overlapping memory being cleared so that 304 * other masters do not accidently write to it. The memory 305 * would be unlocked once the non overlapping region is 306 * cleared and the new memory settings take effect. 307 */ 308 tegra_lock_videomem_nonoverlap(video_mem_base, 309 video_mem_size_mb << 20); 310 } 311 312 /* program the Videomem aperture */ 313 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); 314 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 315 (uint32_t)(phys_base >> 32)); 316 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); 317 318 /* Redundancy check for Video Protect setting */ 319 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO) 320 == (uint32_t)phys_base); 321 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI) 322 == (uint32_t)(phys_base >> 32)); 323 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB) 324 == (size_in_bytes >> 20)); 325 326 /* 327 * MCE propagates the VideoMem configuration values across the 328 * CCPLEX. 329 */ 330 (void)mce_update_gsc_videomem(); 331 332 /* Clear the non-overlapping memory */ 333 if (video_mem_base != 0U) { 334 tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes); 335 tegra_unlock_videomem_nonoverlap(); 336 } 337 338 /* store new values */ 339 video_mem_base = phys_base; 340 video_mem_size_mb = (uint64_t)size_in_bytes >> 20; 341 } 342 343 /* 344 * This feature exists only for v1 of the Tegra Memory Controller. 345 */ 346 void tegra_memctrl_disable_ahb_redirection(void) 347 { 348 ; /* do nothing */ 349 } 350 351 void tegra_memctrl_clear_pending_interrupts(void) 352 { 353 ; /* do nothing */ 354 } 355