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 uint32_t val; 36 const uint32_t *mc_streamid_override_regs; 37 uint32_t num_streamid_override_regs; 38 const mc_streamid_security_cfg_t *mc_streamid_sec_cfgs; 39 uint32_t num_streamid_sec_cfgs; 40 const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings(); 41 uint32_t i; 42 43 INFO("Tegra Memory Controller (v2)\n"); 44 45 /* Program the SMMU pagesize */ 46 tegra_smmu_init(); 47 48 /* Get the settings from the platform */ 49 assert(plat_mc_settings != NULL); 50 mc_streamid_override_regs = plat_mc_settings->streamid_override_cfg; 51 num_streamid_override_regs = plat_mc_settings->num_streamid_override_cfgs; 52 mc_streamid_sec_cfgs = plat_mc_settings->streamid_security_cfg; 53 num_streamid_sec_cfgs = plat_mc_settings->num_streamid_security_cfgs; 54 55 /* Program all the Stream ID overrides */ 56 for (i = 0; i < num_streamid_override_regs; i++) 57 tegra_mc_streamid_write_32(mc_streamid_override_regs[i], 58 MC_STREAM_ID_MAX); 59 60 /* Program the security config settings for all Stream IDs */ 61 for (i = 0; i < num_streamid_sec_cfgs; i++) { 62 val = mc_streamid_sec_cfgs[i].override_enable << 16 | 63 mc_streamid_sec_cfgs[i].override_client_inputs << 8 | 64 mc_streamid_sec_cfgs[i].override_client_ns_flag << 0; 65 tegra_mc_streamid_write_32(mc_streamid_sec_cfgs[i].offset, val); 66 } 67 68 /* 69 * All requests at boot time, and certain requests during 70 * normal run time, are physically addressed and must bypass 71 * the SMMU. The client hub logic implements a hardware bypass 72 * path around the Translation Buffer Units (TBU). During 73 * boot-time, the SMMU_BYPASS_CTRL register (which defaults to 74 * TBU_BYPASS mode) will be used to steer all requests around 75 * the uninitialized TBUs. During normal operation, this register 76 * is locked into TBU_BYPASS_SID config, which routes requests 77 * with special StreamID 0x7f on the bypass path and all others 78 * through the selected TBU. This is done to disable SMMU Bypass 79 * mode, as it could be used to circumvent SMMU security checks. 80 */ 81 tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG, 82 MC_SMMU_BYPASS_CONFIG_SETTINGS); 83 assert(tegra_mc_read_32(MC_SMMU_BYPASS_CONFIG) 84 == MC_SMMU_BYPASS_CONFIG_SETTINGS); 85 86 /* 87 * Re-configure MSS to allow ROC to deal with ordering of the 88 * Memory Controller traffic. This is needed as the Memory Controller 89 * boots with MSS having all control, but ROC provides a performance 90 * boost as compared to MSS. 91 */ 92 if (plat_mc_settings->reconfig_mss_clients != NULL) { 93 plat_mc_settings->reconfig_mss_clients(); 94 } 95 96 /* Program overrides for MC transactions */ 97 if (plat_mc_settings->set_txn_overrides != NULL) { 98 plat_mc_settings->set_txn_overrides(); 99 } 100 } 101 102 /* 103 * Restore Memory Controller settings after "System Suspend" 104 */ 105 void tegra_memctrl_restore_settings(void) 106 { 107 const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings(); 108 109 assert(plat_mc_settings != NULL); 110 111 /* 112 * Re-configure MSS to allow ROC to deal with ordering of the 113 * Memory Controller traffic. This is needed as the Memory Controller 114 * resets during System Suspend with MSS having all control, but ROC 115 * provides a performance boost as compared to MSS. 116 */ 117 if (plat_mc_settings->reconfig_mss_clients != NULL) { 118 plat_mc_settings->reconfig_mss_clients(); 119 } 120 121 /* Program overrides for MC transactions */ 122 if (plat_mc_settings->set_txn_overrides != NULL) { 123 plat_mc_settings->set_txn_overrides(); 124 } 125 126 /* video memory carveout region */ 127 if (video_mem_base != 0ULL) { 128 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, 129 (uint32_t)video_mem_base); 130 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO) 131 == (uint32_t)video_mem_base); 132 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 133 (uint32_t)(video_mem_base >> 32)); 134 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI) 135 == (uint32_t)(video_mem_base >> 32)); 136 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, 137 (uint32_t)video_mem_size_mb); 138 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB) 139 == (uint32_t)video_mem_size_mb); 140 141 /* 142 * MCE propagates the VideoMem configuration values across the 143 * CCPLEX. 144 */ 145 mce_update_gsc_videomem(); 146 } 147 } 148 149 /* 150 * Secure the BL31 DRAM aperture. 151 * 152 * phys_base = physical base of TZDRAM aperture 153 * size_in_bytes = size of aperture in bytes 154 */ 155 void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) 156 { 157 /* 158 * Perform platform specific steps. 159 */ 160 plat_memctrl_tzdram_setup(phys_base, size_in_bytes); 161 } 162 163 /* 164 * Secure the BL31 TZRAM aperture. 165 * 166 * phys_base = physical base of TZRAM aperture 167 * size_in_bytes = size of aperture in bytes 168 */ 169 void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) 170 { 171 ; /* do nothing */ 172 } 173 174 /* 175 * Save MC settings before "System Suspend" to TZDRAM 176 */ 177 void tegra_mc_save_context(uint64_t mc_ctx_addr) 178 { 179 const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings(); 180 uint32_t i, num_entries = 0; 181 mc_regs_t *mc_ctx_regs; 182 const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 183 uint64_t tzdram_base = params_from_bl2->tzdram_base; 184 uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size; 185 186 assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end)); 187 188 /* get MC context table */ 189 mc_ctx_regs = plat_mc_settings->get_mc_system_suspend_ctx(); 190 assert(mc_ctx_regs != NULL); 191 192 /* 193 * mc_ctx_regs[0].val contains the size of the context table minus 194 * the last entry. Sanity check the table size before we start with 195 * the context save operation. 196 */ 197 while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) { 198 num_entries++; 199 } 200 201 /* panic if the sizes do not match */ 202 if (num_entries != mc_ctx_regs[0].val) { 203 ERROR("MC context size mismatch!"); 204 panic(); 205 } 206 207 /* save MC register values */ 208 for (i = 1U; i < num_entries; i++) { 209 mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg); 210 } 211 212 /* increment by 1 to take care of the last entry */ 213 num_entries++; 214 215 /* Save MC config settings */ 216 (void)memcpy((void *)mc_ctx_addr, mc_ctx_regs, 217 sizeof(mc_regs_t) * num_entries); 218 219 /* save the MC table address */ 220 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO, 221 (uint32_t)mc_ctx_addr); 222 assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO) 223 == (uint32_t)mc_ctx_addr); 224 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI, 225 (uint32_t)(mc_ctx_addr >> 32)); 226 assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI) 227 == (uint32_t)(mc_ctx_addr >> 32)); 228 } 229 230 static void tegra_lock_videomem_nonoverlap(uint64_t phys_base, 231 uint64_t size_in_bytes) 232 { 233 uint32_t index; 234 uint64_t total_128kb_blocks = size_in_bytes >> 17; 235 uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12; 236 uint64_t val; 237 238 /* 239 * Reset the access configuration registers to restrict access to 240 * old Videomem aperture 241 */ 242 for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0; 243 index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE); 244 index += 4U) { 245 tegra_mc_write_32(index, 0); 246 } 247 248 /* 249 * Set the base. It must be 4k aligned, at least. 250 */ 251 assert((phys_base & (uint64_t)0xFFF) == 0U); 252 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base); 253 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 254 (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK); 255 256 /* 257 * Set the aperture size 258 * 259 * total size = (number of 128KB blocks) + (number of remaining 4KB 260 * blocks) 261 * 262 */ 263 val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) | 264 total_128kb_blocks); 265 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val); 266 267 /* 268 * Lock the configuration settings by enabling TZ-only lock and 269 * locking the configuration against any future changes from NS 270 * world. 271 */ 272 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG, 273 (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT); 274 275 /* 276 * MCE propagates the GSC configuration values across the 277 * CCPLEX. 278 */ 279 } 280 281 static void tegra_unlock_videomem_nonoverlap(void) 282 { 283 /* Clear the base */ 284 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0); 285 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0); 286 287 /* Clear the size */ 288 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0); 289 } 290 291 static void tegra_clear_videomem(uintptr_t non_overlap_area_start, 292 unsigned long long non_overlap_area_size) 293 { 294 int ret; 295 296 INFO("Cleaning previous Video Memory Carveout\n"); 297 298 /* 299 * Map the NS memory first, clean it and then unmap it. 300 */ 301 ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ 302 non_overlap_area_start, /* VA */ 303 non_overlap_area_size, /* size */ 304 MT_DEVICE | MT_RW | MT_NS); /* attrs */ 305 assert(ret == 0); 306 307 zeromem((void *)non_overlap_area_start, non_overlap_area_size); 308 flush_dcache_range(non_overlap_area_start, non_overlap_area_size); 309 310 ret = mmap_remove_dynamic_region(non_overlap_area_start, 311 non_overlap_area_size); 312 assert(ret == 0); 313 } 314 315 static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base, 316 unsigned long size_in_bytes) 317 { 318 uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20); 319 uintptr_t vmem_end_new = phys_base + size_in_bytes; 320 unsigned long long non_overlap_area_size; 321 322 /* 323 * Clear the old regions now being exposed. The following cases 324 * can occur - 325 * 326 * 1. clear whole old region (no overlap with new region) 327 * 2. clear old sub-region below new base 328 * 3. clear old sub-region above new end 329 */ 330 if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) { 331 tegra_clear_videomem(video_mem_base, 332 video_mem_size_mb << 20U); 333 } else { 334 if (video_mem_base < phys_base) { 335 non_overlap_area_size = phys_base - video_mem_base; 336 tegra_clear_videomem(video_mem_base, non_overlap_area_size); 337 } 338 if (vmem_end_old > vmem_end_new) { 339 non_overlap_area_size = vmem_end_old - vmem_end_new; 340 tegra_clear_videomem(vmem_end_new, non_overlap_area_size); 341 } 342 } 343 } 344 345 /* 346 * Program the Video Memory carveout region 347 * 348 * phys_base = physical base of aperture 349 * size_in_bytes = size of aperture in bytes 350 */ 351 void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) 352 { 353 /* 354 * Setup the Memory controller to restrict CPU accesses to the Video 355 * Memory region 356 */ 357 358 INFO("Configuring Video Memory Carveout\n"); 359 360 if (video_mem_base != 0U) { 361 /* 362 * Lock the non overlapping memory being cleared so that 363 * other masters do not accidently write to it. The memory 364 * would be unlocked once the non overlapping region is 365 * cleared and the new memory settings take effect. 366 */ 367 tegra_lock_videomem_nonoverlap(video_mem_base, 368 video_mem_size_mb << 20); 369 } 370 371 /* program the Videomem aperture */ 372 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); 373 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 374 (uint32_t)(phys_base >> 32)); 375 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); 376 377 /* Redundancy check for Video Protect setting */ 378 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO) 379 == (uint32_t)phys_base); 380 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI) 381 == (uint32_t)(phys_base >> 32)); 382 assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB) 383 == (size_in_bytes >> 20)); 384 385 /* 386 * MCE propagates the VideoMem configuration values across the 387 * CCPLEX. 388 */ 389 (void)mce_update_gsc_videomem(); 390 391 /* Clear the non-overlapping memory */ 392 if (video_mem_base != 0U) { 393 tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes); 394 tegra_unlock_videomem_nonoverlap(); 395 } 396 397 /* store new values */ 398 video_mem_base = phys_base; 399 video_mem_size_mb = (uint64_t)size_in_bytes >> 20; 400 } 401 402 /* 403 * This feature exists only for v1 of the Tegra Memory Controller. 404 */ 405 void tegra_memctrl_disable_ahb_redirection(void) 406 { 407 ; /* do nothing */ 408 } 409 410 void tegra_memctrl_clear_pending_interrupts(void) 411 { 412 ; /* do nothing */ 413 } 414