blob: 4f7c71e4afc5bdbc21a23a475cca25910be5239a [file] [log] [blame]
Varun Wadekarb316e242015-05-19 16:48:04 +05301/*
Douglas Raillard21362a92016-12-02 13:51:54 +00002 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
Varun Wadekarb316e242015-05-19 16:48:04 +05303 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
Varun Wadekar7a269e22015-06-10 14:04:32 +053031#include <arch_helpers.h>
Varun Wadekarb316e242015-05-19 16:48:04 +053032#include <assert.h>
33#include <debug.h>
34#include <mmio.h>
35#include <memctrl.h>
Varun Wadekar7a269e22015-06-10 14:04:32 +053036#include <string.h>
Varun Wadekarb316e242015-05-19 16:48:04 +053037#include <tegra_def.h>
Douglas Raillarda8954fc2017-01-26 15:54:44 +000038#include <utils.h>
Varun Wadekar7a269e22015-06-10 14:04:32 +053039#include <xlat_tables.h>
40
Varun Wadekar7a269e22015-06-10 14:04:32 +053041#define TEGRA_GPU_RESET_REG_OFFSET 0x28c
42#define GPU_RESET_BIT (1 << 24)
43
44/* Video Memory base and size (live values) */
45static uintptr_t video_mem_base;
46static uint64_t video_mem_size;
Varun Wadekarb316e242015-05-19 16:48:04 +053047
48/*
49 * Init SMMU.
50 */
51void tegra_memctrl_setup(void)
52{
53 /*
54 * Setup the Memory controller to allow only secure accesses to
55 * the TZDRAM carveout
56 */
57 INFO("Configuring SMMU\n");
58
59 /* allow translations for all MC engines */
60 tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0,
61 (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
62 tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0,
63 (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
64 tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0,
65 (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
66 tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0,
67 (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
68 tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0,
69 (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
70
71 tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY);
72
73 tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL);
74 tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL);
75
76 /* flush PTC and TLB */
77 tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL);
78 (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
79 tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL);
80
81 /* enable SMMU */
82 tegra_mc_write_32(MC_SMMU_CONFIG_0,
83 MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE);
84 (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
Varun Wadekar7a269e22015-06-10 14:04:32 +053085
86 /* video memory carveout */
87 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE, video_mem_base);
88 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size);
Varun Wadekarb316e242015-05-19 16:48:04 +053089}
90
91/*
92 * Secure the BL31 DRAM aperture.
93 *
94 * phys_base = physical base of TZDRAM aperture
95 * size_in_bytes = size of aperture in bytes
96 */
97void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
98{
99 /*
100 * Setup the Memory controller to allow only secure accesses to
101 * the TZDRAM carveout
102 */
103 INFO("Configuring TrustZone DRAM Memory Carveout\n");
104
105 tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base);
106 tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
107}
Varun Wadekar7a269e22015-06-10 14:04:32 +0530108
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100109static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
110 unsigned long long non_overlap_area_size)
111{
112 /*
113 * Perform cache maintenance to ensure that the non-overlapping area is
114 * zeroed out. The first invalidation of this range ensures that
115 * possible evictions of dirty cache lines do not interfere with the
Douglas Raillard21362a92016-12-02 13:51:54 +0000116 * 'zeromem' operation. Other CPUs could speculatively prefetch the
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100117 * main memory contents of this area between the first invalidation and
Douglas Raillard21362a92016-12-02 13:51:54 +0000118 * the 'zeromem' operation. The second invalidation ensures that any
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100119 * such cache lines are removed as well.
120 */
121 inv_dcache_range(non_overlap_area_start, non_overlap_area_size);
Douglas Raillard21362a92016-12-02 13:51:54 +0000122 zeromem((void *)non_overlap_area_start, non_overlap_area_size);
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100123 inv_dcache_range(non_overlap_area_start, non_overlap_area_size);
124}
125
Varun Wadekar7a269e22015-06-10 14:04:32 +0530126/*
127 * Program the Video Memory carveout region
128 *
129 * phys_base = physical base of aperture
130 * size_in_bytes = size of aperture in bytes
131 */
132void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
133{
134 uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20);
135 uintptr_t vmem_end_new = phys_base + size_in_bytes;
136 uint32_t regval;
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100137 unsigned long long non_overlap_area_size;
Varun Wadekar7a269e22015-06-10 14:04:32 +0530138
139 /*
140 * The GPU is the user of the Video Memory region. In order to
141 * transition to the new memory region smoothly, we program the
142 * new base/size ONLY if the GPU is in reset mode.
143 */
144 regval = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET);
145 if ((regval & GPU_RESET_BIT) == 0) {
146 ERROR("GPU not in reset! Video Memory setup failed\n");
147 return;
148 }
149
150 /*
151 * Setup the Memory controller to restrict CPU accesses to the Video
152 * Memory region
153 */
154 INFO("Configuring Video Memory Carveout\n");
155
156 /*
157 * Configure Memory Controller directly for the first time.
158 */
159 if (video_mem_base == 0)
160 goto done;
161
162 /*
163 * Clear the old regions now being exposed. The following cases
164 * can occur -
165 *
166 * 1. clear whole old region (no overlap with new region)
167 * 2. clear old sub-region below new base
168 * 3. clear old sub-region above new end
169 */
170 INFO("Cleaning previous Video Memory Carveout\n");
171
172 disable_mmu_el3();
Varun Wadekar1be2f972015-08-26 15:06:14 +0530173 if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100174 tegra_clear_videomem(video_mem_base, video_mem_size << 20);
Varun Wadekar1be2f972015-08-26 15:06:14 +0530175 } else {
176 if (video_mem_base < phys_base) {
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100177 non_overlap_area_size = phys_base - video_mem_base;
178 tegra_clear_videomem(video_mem_base, non_overlap_area_size);
Varun Wadekar1be2f972015-08-26 15:06:14 +0530179 }
180 if (vmem_end_old > vmem_end_new) {
Vikram Kanigiri4489ad12015-09-10 14:12:36 +0100181 non_overlap_area_size = vmem_end_old - vmem_end_new;
182 tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
Varun Wadekar1be2f972015-08-26 15:06:14 +0530183 }
184 }
Varun Wadekar7a269e22015-06-10 14:04:32 +0530185 enable_mmu_el3(0);
186
187done:
188 tegra_mc_write_32(MC_VIDEO_PROTECT_BASE, phys_base);
189 tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
190
191 /* store new values */
192 video_mem_base = phys_base;
193 video_mem_size = size_in_bytes >> 20;
194}