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