memctrl_v1.c 6.73 KB
Newer Older
1
/*
2
 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
6
7
 */

#include <assert.h>
8
9
10
11
12
13
14
15
#include <string.h>

#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>

16
#include <memctrl.h>
17
#include <memctrl_v1.h>
18
#include <tegra_def.h>
19
20

/* Video Memory base and size (live values) */
21
static uint64_t video_mem_base;
22
static uint64_t video_mem_size;
23
24
25
26
27
28
29
30
31
32

/*
 * Init SMMU.
 */
void tegra_memctrl_setup(void)
{
	/*
	 * Setup the Memory controller to allow only secure accesses to
	 * the TZDRAM carveout
	 */
33
	INFO("Tegra Memory Controller (v1)\n");
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

	/* allow translations for all MC engines */
	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0,
			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0,
			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0,
			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0,
			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);
	tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0,
			(unsigned int)MC_SMMU_TRANSLATION_ENABLE);

	tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY);

	tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL);
	tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL);

	/* flush PTC and TLB */
	tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL);
	(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
	tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL);

	/* enable SMMU */
	tegra_mc_write_32(MC_SMMU_CONFIG_0,
			  MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE);
	(void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
61
62

	/* video memory carveout */
63
64
65
	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
			  (uint32_t)(video_mem_base >> 32));
	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)video_mem_base);
66
	tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size);
67
68
}

69
70
71
72
73
74
75
76
/*
 * Restore Memory Controller settings after "System Suspend"
 */
void tegra_memctrl_restore_settings(void)
{
	tegra_memctrl_setup();
}

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
 * Secure the BL31 DRAM aperture.
 *
 * phys_base = physical base of TZDRAM aperture
 * size_in_bytes = size of aperture in bytes
 */
void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
{
	/*
	 * Setup the Memory controller to allow only secure accesses to
	 * the TZDRAM carveout
	 */
	INFO("Configuring TrustZone DRAM Memory Carveout\n");

	tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base);
	tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
}
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
 * Secure the BL31 TZRAM aperture.
 *
 * phys_base = physical base of TZRAM aperture
 * size_in_bytes = size of aperture in bytes
 */
void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes)
{
	/*
	 * The v1 hardware controller does not have any registers
	 * for setting up the on-chip TZRAM.
	 */
}

109
110
111
static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
				 unsigned long long non_overlap_area_size)
{
112
113
	int ret;

114
	/*
115
	 * Map the NS memory first, clean it and then unmap it.
116
	 */
117
	ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
118
119
120
				non_overlap_area_start, /* VA */
				non_overlap_area_size, /* size */
				MT_NS | MT_RW | MT_EXECUTE_NEVER); /* attrs */
121
	assert(ret == 0);
122

123
	zeromem((void *)non_overlap_area_start, non_overlap_area_size);
124
125
126
127
	flush_dcache_range(non_overlap_area_start, non_overlap_area_size);

	mmap_remove_dynamic_region(non_overlap_area_start,
		non_overlap_area_size);
128
129
}

130
131
132
133
134
135
136
137
138
139
/*
 * Program the Video Memory carveout region
 *
 * phys_base = physical base of aperture
 * size_in_bytes = size of aperture in bytes
 */
void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
{
	uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20);
	uintptr_t vmem_end_new = phys_base + size_in_bytes;
140
	unsigned long long non_overlap_area_size;
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

	/*
	 * Setup the Memory controller to restrict CPU accesses to the Video
	 * Memory region
	 */
	INFO("Configuring Video Memory Carveout\n");

	/*
	 * Configure Memory Controller directly for the first time.
	 */
	if (video_mem_base == 0)
		goto done;

	/*
	 * Clear the old regions now being exposed. The following cases
	 * can occur -
	 *
	 * 1. clear whole old region (no overlap with new region)
	 * 2. clear old sub-region below new base
	 * 3. clear old sub-region above new end
	 */
	INFO("Cleaning previous Video Memory Carveout\n");

164
	if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
165
		tegra_clear_videomem(video_mem_base, video_mem_size << 20);
166
167
	} else {
		if (video_mem_base < phys_base) {
168
169
			non_overlap_area_size = phys_base - video_mem_base;
			tegra_clear_videomem(video_mem_base, non_overlap_area_size);
170
171
		}
		if (vmem_end_old > vmem_end_new) {
172
173
			non_overlap_area_size = vmem_end_old - vmem_end_new;
			tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
174
175
		}
	}
176
177

done:
178
179
	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32));
	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
180
181
182
183
184
185
	tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);

	/* store new values */
	video_mem_base = phys_base;
	video_mem_size = size_in_bytes >> 20;
}
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

/*
 * During boot, USB3 and flash media (SDMMC/SATA) devices need access to
 * IRAM. Because these clients connect to the MC and do not have a direct
 * path to the IRAM, the MC implements AHB redirection during boot to allow
 * path to IRAM. In this mode, accesses to a programmed memory address aperture
 * are directed to the AHB bus, allowing access to the IRAM. The AHB aperture
 * is defined by the IRAM_BASE_LO and IRAM_BASE_HI registers, which are
 * initialized to disable this aperture.
 *
 * Once bootup is complete, we must program IRAM base to 0xffffffff and
 * IRAM top to 0x00000000, thus disabling access to IRAM. DRAM is then
 * potentially accessible in this address range. These aperture registers
 * also have an access_control/lock bit. After disabling the aperture, the
 * access_control register should be programmed to lock the registers.
 */
void tegra_memctrl_disable_ahb_redirection(void)
{
	/* program the aperture registers */
	tegra_mc_write_32(MC_IRAM_BASE_LO, 0xFFFFFFFF);
	tegra_mc_write_32(MC_IRAM_TOP_LO, 0);
	tegra_mc_write_32(MC_IRAM_BASE_TOP_HI, 0);

	/* lock the aperture registers */
	tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES);
}
212
213
214
215
216
217
218
219
220
221
222
223
224

void tegra_memctrl_clear_pending_interrupts(void)
{
	uint32_t mcerr;

	/* check if there are any pending interrupts */
	mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS);

	if (mcerr != (uint32_t)0U) { /* should not see error here */
		WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr);
		mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS),  mcerr);
	}
}