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 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 131 (uint32_t)(video_mem_base >> 32)); 132 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size_mb); 133 134 /* 135 * MCE propagates the VideoMem configuration values across the 136 * CCPLEX. 137 */ 138 mce_update_gsc_videomem(); 139 } 140 } 141 142 /* 143 * Secure the BL31 DRAM aperture. 144 * 145 * phys_base = physical base of TZDRAM aperture 146 * size_in_bytes = size of aperture in bytes 147 */ 148 void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) 149 { 150 /* 151 * Perform platform specific steps. 152 */ 153 plat_memctrl_tzdram_setup(phys_base, size_in_bytes); 154 } 155 156 /* 157 * Secure the BL31 TZRAM aperture. 158 * 159 * phys_base = physical base of TZRAM aperture 160 * size_in_bytes = size of aperture in bytes 161 */ 162 void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) 163 { 164 ; /* do nothing */ 165 } 166 167 /* 168 * Save MC settings before "System Suspend" to TZDRAM 169 */ 170 void tegra_mc_save_context(uint64_t mc_ctx_addr) 171 { 172 const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings(); 173 uint32_t i, num_entries = 0; 174 mc_regs_t *mc_ctx_regs; 175 const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 176 uint64_t tzdram_base = params_from_bl2->tzdram_base; 177 uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size; 178 179 assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end)); 180 181 /* get MC context table */ 182 mc_ctx_regs = plat_mc_settings->get_mc_system_suspend_ctx(); 183 assert(mc_ctx_regs != NULL); 184 185 /* 186 * mc_ctx_regs[0].val contains the size of the context table minus 187 * the last entry. Sanity check the table size before we start with 188 * the context save operation. 189 */ 190 while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) { 191 num_entries++; 192 } 193 194 /* panic if the sizes do not match */ 195 if (num_entries != mc_ctx_regs[0].val) { 196 ERROR("MC context size mismatch!"); 197 panic(); 198 } 199 200 /* save MC register values */ 201 for (i = 1U; i < num_entries; i++) { 202 mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg); 203 } 204 205 /* increment by 1 to take care of the last entry */ 206 num_entries++; 207 208 /* Save MC config settings */ 209 (void)memcpy((void *)mc_ctx_addr, mc_ctx_regs, 210 sizeof(mc_regs_t) * num_entries); 211 212 /* save the MC table address */ 213 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO, 214 (uint32_t)mc_ctx_addr); 215 assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO) 216 == (uint32_t)mc_ctx_addr); 217 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI, 218 (uint32_t)(mc_ctx_addr >> 32)); 219 assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI) 220 == (uint32_t)(mc_ctx_addr >> 32)); 221 } 222 223 static void tegra_lock_videomem_nonoverlap(uint64_t phys_base, 224 uint64_t size_in_bytes) 225 { 226 uint32_t index; 227 uint64_t total_128kb_blocks = size_in_bytes >> 17; 228 uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12; 229 uint64_t val; 230 231 /* 232 * Reset the access configuration registers to restrict access to 233 * old Videomem aperture 234 */ 235 for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0; 236 index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE); 237 index += 4U) { 238 tegra_mc_write_32(index, 0); 239 } 240 241 /* 242 * Set the base. It must be 4k aligned, at least. 243 */ 244 assert((phys_base & (uint64_t)0xFFF) == 0U); 245 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base); 246 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 247 (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK); 248 249 /* 250 * Set the aperture size 251 * 252 * total size = (number of 128KB blocks) + (number of remaining 4KB 253 * blocks) 254 * 255 */ 256 val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) | 257 total_128kb_blocks); 258 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val); 259 260 /* 261 * Lock the configuration settings by enabling TZ-only lock and 262 * locking the configuration against any future changes from NS 263 * world. 264 */ 265 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG, 266 (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT); 267 268 /* 269 * MCE propagates the GSC configuration values across the 270 * CCPLEX. 271 */ 272 } 273 274 static void tegra_unlock_videomem_nonoverlap(void) 275 { 276 /* Clear the base */ 277 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0); 278 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0); 279 280 /* Clear the size */ 281 tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0); 282 } 283 284 static void tegra_clear_videomem(uintptr_t non_overlap_area_start, 285 unsigned long long non_overlap_area_size) 286 { 287 int ret; 288 289 INFO("Cleaning previous Video Memory Carveout\n"); 290 291 /* 292 * Map the NS memory first, clean it and then unmap it. 293 */ 294 ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ 295 non_overlap_area_start, /* VA */ 296 non_overlap_area_size, /* size */ 297 MT_DEVICE | MT_RW | MT_NS); /* attrs */ 298 assert(ret == 0); 299 300 zeromem((void *)non_overlap_area_start, non_overlap_area_size); 301 flush_dcache_range(non_overlap_area_start, non_overlap_area_size); 302 303 ret = mmap_remove_dynamic_region(non_overlap_area_start, 304 non_overlap_area_size); 305 assert(ret == 0); 306 } 307 308 static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base, 309 unsigned long size_in_bytes) 310 { 311 uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20); 312 uintptr_t vmem_end_new = phys_base + size_in_bytes; 313 unsigned long long non_overlap_area_size; 314 315 /* 316 * Clear the old regions now being exposed. The following cases 317 * can occur - 318 * 319 * 1. clear whole old region (no overlap with new region) 320 * 2. clear old sub-region below new base 321 * 3. clear old sub-region above new end 322 */ 323 if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) { 324 tegra_clear_videomem(video_mem_base, 325 video_mem_size_mb << 20U); 326 } else { 327 if (video_mem_base < phys_base) { 328 non_overlap_area_size = phys_base - video_mem_base; 329 tegra_clear_videomem(video_mem_base, non_overlap_area_size); 330 } 331 if (vmem_end_old > vmem_end_new) { 332 non_overlap_area_size = vmem_end_old - vmem_end_new; 333 tegra_clear_videomem(vmem_end_new, non_overlap_area_size); 334 } 335 } 336 } 337 338 /* 339 * Program the Video Memory carveout region 340 * 341 * phys_base = physical base of aperture 342 * size_in_bytes = size of aperture in bytes 343 */ 344 void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) 345 { 346 /* 347 * Setup the Memory controller to restrict CPU accesses to the Video 348 * Memory region 349 */ 350 351 INFO("Configuring Video Memory Carveout\n"); 352 353 if (video_mem_base != 0U) { 354 /* 355 * Lock the non overlapping memory being cleared so that 356 * other masters do not accidently write to it. The memory 357 * would be unlocked once the non overlapping region is 358 * cleared and the new memory settings take effect. 359 */ 360 tegra_lock_videomem_nonoverlap(video_mem_base, 361 video_mem_size_mb << 20); 362 } 363 364 /* program the Videomem aperture */ 365 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); 366 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 367 (uint32_t)(phys_base >> 32)); 368 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); 369 370 /* 371 * MCE propagates the VideoMem configuration values across the 372 * CCPLEX. 373 */ 374 (void)mce_update_gsc_videomem(); 375 376 /* Clear the non-overlapping memory */ 377 if (video_mem_base != 0U) { 378 tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes); 379 tegra_unlock_videomem_nonoverlap(); 380 } 381 382 /* store new values */ 383 video_mem_base = phys_base; 384 video_mem_size_mb = (uint64_t)size_in_bytes >> 20; 385 } 386 387 /* 388 * This feature exists only for v1 of the Tegra Memory Controller. 389 */ 390 void tegra_memctrl_disable_ahb_redirection(void) 391 { 392 ; /* do nothing */ 393 } 394 395 void tegra_memctrl_clear_pending_interrupts(void) 396 { 397 ; /* do nothing */ 398 } 399