1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <string.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_helpers.h> 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <lib/mmio.h> 14*91f16700Schasinglulu #include <lib/utils.h> 15*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <memctrl.h> 18*91f16700Schasinglulu #include <memctrl_v1.h> 19*91f16700Schasinglulu #include <tegra_def.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu /* Video Memory base and size (live values) */ 22*91f16700Schasinglulu static uint64_t video_mem_base; 23*91f16700Schasinglulu static uint64_t video_mem_size; 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* 26*91f16700Schasinglulu * Init SMMU. 27*91f16700Schasinglulu */ 28*91f16700Schasinglulu void tegra_memctrl_setup(void) 29*91f16700Schasinglulu { 30*91f16700Schasinglulu /* 31*91f16700Schasinglulu * Setup the Memory controller to allow only secure accesses to 32*91f16700Schasinglulu * the TZDRAM carveout 33*91f16700Schasinglulu */ 34*91f16700Schasinglulu INFO("Tegra Memory Controller (v1)\n"); 35*91f16700Schasinglulu 36*91f16700Schasinglulu /* allow translations for all MC engines */ 37*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0, 38*91f16700Schasinglulu (unsigned int)MC_SMMU_TRANSLATION_ENABLE); 39*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0, 40*91f16700Schasinglulu (unsigned int)MC_SMMU_TRANSLATION_ENABLE); 41*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0, 42*91f16700Schasinglulu (unsigned int)MC_SMMU_TRANSLATION_ENABLE); 43*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0, 44*91f16700Schasinglulu (unsigned int)MC_SMMU_TRANSLATION_ENABLE); 45*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0, 46*91f16700Schasinglulu (unsigned int)MC_SMMU_TRANSLATION_ENABLE); 47*91f16700Schasinglulu 48*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY); 49*91f16700Schasinglulu 50*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL); 51*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL); 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* flush PTC and TLB */ 54*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL); 55*91f16700Schasinglulu (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */ 56*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL); 57*91f16700Schasinglulu 58*91f16700Schasinglulu /* enable SMMU */ 59*91f16700Schasinglulu tegra_mc_write_32(MC_SMMU_CONFIG_0, 60*91f16700Schasinglulu MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE); 61*91f16700Schasinglulu (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */ 62*91f16700Schasinglulu 63*91f16700Schasinglulu /* video memory carveout */ 64*91f16700Schasinglulu tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, 65*91f16700Schasinglulu (uint32_t)(video_mem_base >> 32)); 66*91f16700Schasinglulu tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)video_mem_base); 67*91f16700Schasinglulu tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size); 68*91f16700Schasinglulu } 69*91f16700Schasinglulu 70*91f16700Schasinglulu /* 71*91f16700Schasinglulu * Restore Memory Controller settings after "System Suspend" 72*91f16700Schasinglulu */ 73*91f16700Schasinglulu void tegra_memctrl_restore_settings(void) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu tegra_memctrl_setup(); 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* 79*91f16700Schasinglulu * Secure the BL31 DRAM aperture. 80*91f16700Schasinglulu * 81*91f16700Schasinglulu * phys_base = physical base of TZDRAM aperture 82*91f16700Schasinglulu * size_in_bytes = size of aperture in bytes 83*91f16700Schasinglulu */ 84*91f16700Schasinglulu void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) 85*91f16700Schasinglulu { 86*91f16700Schasinglulu /* 87*91f16700Schasinglulu * Setup the Memory controller to allow only secure accesses to 88*91f16700Schasinglulu * the TZDRAM carveout 89*91f16700Schasinglulu */ 90*91f16700Schasinglulu INFO("Configuring TrustZone DRAM Memory Carveout\n"); 91*91f16700Schasinglulu 92*91f16700Schasinglulu tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base); 93*91f16700Schasinglulu tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20); 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu static void tegra_clear_videomem(uintptr_t non_overlap_area_start, 97*91f16700Schasinglulu unsigned long long non_overlap_area_size) 98*91f16700Schasinglulu { 99*91f16700Schasinglulu int ret; 100*91f16700Schasinglulu 101*91f16700Schasinglulu /* 102*91f16700Schasinglulu * Map the NS memory first, clean it and then unmap it. 103*91f16700Schasinglulu */ 104*91f16700Schasinglulu ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ 105*91f16700Schasinglulu non_overlap_area_start, /* VA */ 106*91f16700Schasinglulu non_overlap_area_size, /* size */ 107*91f16700Schasinglulu MT_NS | MT_RW | MT_EXECUTE_NEVER | 108*91f16700Schasinglulu MT_NON_CACHEABLE); /* attrs */ 109*91f16700Schasinglulu assert(ret == 0); 110*91f16700Schasinglulu 111*91f16700Schasinglulu zeromem((void *)non_overlap_area_start, non_overlap_area_size); 112*91f16700Schasinglulu flush_dcache_range(non_overlap_area_start, non_overlap_area_size); 113*91f16700Schasinglulu 114*91f16700Schasinglulu mmap_remove_dynamic_region(non_overlap_area_start, 115*91f16700Schasinglulu non_overlap_area_size); 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * Program the Video Memory carveout region 120*91f16700Schasinglulu * 121*91f16700Schasinglulu * phys_base = physical base of aperture 122*91f16700Schasinglulu * size_in_bytes = size of aperture in bytes 123*91f16700Schasinglulu */ 124*91f16700Schasinglulu void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) 125*91f16700Schasinglulu { 126*91f16700Schasinglulu uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20); 127*91f16700Schasinglulu uintptr_t vmem_end_new = phys_base + size_in_bytes; 128*91f16700Schasinglulu unsigned long long non_overlap_area_size; 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* 131*91f16700Schasinglulu * Setup the Memory controller to restrict CPU accesses to the Video 132*91f16700Schasinglulu * Memory region 133*91f16700Schasinglulu */ 134*91f16700Schasinglulu INFO("Configuring Video Memory Carveout\n"); 135*91f16700Schasinglulu 136*91f16700Schasinglulu /* 137*91f16700Schasinglulu * Configure Memory Controller directly for the first time. 138*91f16700Schasinglulu */ 139*91f16700Schasinglulu if (video_mem_base == 0) 140*91f16700Schasinglulu goto done; 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* 143*91f16700Schasinglulu * Clear the old regions now being exposed. The following cases 144*91f16700Schasinglulu * can occur - 145*91f16700Schasinglulu * 146*91f16700Schasinglulu * 1. clear whole old region (no overlap with new region) 147*91f16700Schasinglulu * 2. clear old sub-region below new base 148*91f16700Schasinglulu * 3. clear old sub-region above new end 149*91f16700Schasinglulu */ 150*91f16700Schasinglulu INFO("Cleaning previous Video Memory Carveout\n"); 151*91f16700Schasinglulu 152*91f16700Schasinglulu if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) { 153*91f16700Schasinglulu tegra_clear_videomem(video_mem_base, video_mem_size << 20); 154*91f16700Schasinglulu } else { 155*91f16700Schasinglulu if (video_mem_base < phys_base) { 156*91f16700Schasinglulu non_overlap_area_size = phys_base - video_mem_base; 157*91f16700Schasinglulu tegra_clear_videomem(video_mem_base, non_overlap_area_size); 158*91f16700Schasinglulu } 159*91f16700Schasinglulu if (vmem_end_old > vmem_end_new) { 160*91f16700Schasinglulu non_overlap_area_size = vmem_end_old - vmem_end_new; 161*91f16700Schasinglulu tegra_clear_videomem(vmem_end_new, non_overlap_area_size); 162*91f16700Schasinglulu } 163*91f16700Schasinglulu } 164*91f16700Schasinglulu 165*91f16700Schasinglulu done: 166*91f16700Schasinglulu tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32)); 167*91f16700Schasinglulu tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); 168*91f16700Schasinglulu tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); 169*91f16700Schasinglulu 170*91f16700Schasinglulu /* store new values */ 171*91f16700Schasinglulu video_mem_base = phys_base; 172*91f16700Schasinglulu video_mem_size = size_in_bytes >> 20; 173*91f16700Schasinglulu } 174*91f16700Schasinglulu 175*91f16700Schasinglulu /* 176*91f16700Schasinglulu * During boot, USB3 and flash media (SDMMC/SATA) devices need access to 177*91f16700Schasinglulu * IRAM. Because these clients connect to the MC and do not have a direct 178*91f16700Schasinglulu * path to the IRAM, the MC implements AHB redirection during boot to allow 179*91f16700Schasinglulu * path to IRAM. In this mode, accesses to a programmed memory address aperture 180*91f16700Schasinglulu * are directed to the AHB bus, allowing access to the IRAM. The AHB aperture 181*91f16700Schasinglulu * is defined by the IRAM_BASE_LO and IRAM_BASE_HI registers, which are 182*91f16700Schasinglulu * initialized to disable this aperture. 183*91f16700Schasinglulu * 184*91f16700Schasinglulu * Once bootup is complete, we must program IRAM base to 0xffffffff and 185*91f16700Schasinglulu * IRAM top to 0x00000000, thus disabling access to IRAM. DRAM is then 186*91f16700Schasinglulu * potentially accessible in this address range. These aperture registers 187*91f16700Schasinglulu * also have an access_control/lock bit. After disabling the aperture, the 188*91f16700Schasinglulu * access_control register should be programmed to lock the registers. 189*91f16700Schasinglulu */ 190*91f16700Schasinglulu void tegra_memctrl_disable_ahb_redirection(void) 191*91f16700Schasinglulu { 192*91f16700Schasinglulu /* program the aperture registers */ 193*91f16700Schasinglulu tegra_mc_write_32(MC_IRAM_BASE_LO, 0xFFFFFFFF); 194*91f16700Schasinglulu tegra_mc_write_32(MC_IRAM_TOP_LO, 0); 195*91f16700Schasinglulu tegra_mc_write_32(MC_IRAM_BASE_TOP_HI, 0); 196*91f16700Schasinglulu 197*91f16700Schasinglulu /* lock the aperture registers */ 198*91f16700Schasinglulu tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES); 199*91f16700Schasinglulu } 200*91f16700Schasinglulu 201*91f16700Schasinglulu void tegra_memctrl_clear_pending_interrupts(void) 202*91f16700Schasinglulu { 203*91f16700Schasinglulu uint32_t mcerr; 204*91f16700Schasinglulu 205*91f16700Schasinglulu /* check if there are any pending interrupts */ 206*91f16700Schasinglulu mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS); 207*91f16700Schasinglulu 208*91f16700Schasinglulu if (mcerr != (uint32_t)0U) { /* should not see error here */ 209*91f16700Schasinglulu WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr); 210*91f16700Schasinglulu mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS), mcerr); 211*91f16700Schasinglulu } 212*91f16700Schasinglulu } 213