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