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