xref: /rk3399_ARM-atf/plat/nvidia/tegra/soc/t186/plat_setup.c (revision 7b3b41d6766e61c5b61259dc4ba100befffd2769)
1 /*
2  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <arch_helpers.h>
10 #include <bl31/bl31.h>
11 #include <bl31/interrupt_mgmt.h>
12 #include <common/bl_common.h>
13 #include <common/debug.h>
14 #include <common/interrupt_props.h>
15 #include <context.h>
16 #include <cortex_a57.h>
17 #include <denver.h>
18 #include <drivers/arm/gic_common.h>
19 #include <drivers/arm/gicv2.h>
20 #include <drivers/console.h>
21 #include <lib/el3_runtime/context_mgmt.h>
22 #include <lib/xlat_tables/xlat_tables_v2.h>
23 #include <plat/common/platform.h>
24 
25 #include <mce.h>
26 #include <tegra_def.h>
27 #include <tegra_platform.h>
28 #include <tegra_private.h>
29 
30 DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A57_L2CTLR_EL1)
31 extern uint64_t tegra_enable_l2_ecc_parity_prot;
32 
33 /*******************************************************************************
34  * Tegra186 CPU numbers in cluster #0
35  *******************************************************************************
36  */
37 #define TEGRA186_CLUSTER0_CORE2		2
38 #define TEGRA186_CLUSTER0_CORE3		3
39 
40 /*******************************************************************************
41  * The Tegra power domain tree has a single system level power domain i.e. a
42  * single root node. The first entry in the power domain descriptor specifies
43  * the number of power domains at the highest power level.
44  *******************************************************************************
45  */
46 const unsigned char tegra_power_domain_tree_desc[] = {
47 	/* No of root nodes */
48 	1,
49 	/* No of clusters */
50 	PLATFORM_CLUSTER_COUNT,
51 	/* No of CPU cores - cluster0 */
52 	PLATFORM_MAX_CPUS_PER_CLUSTER,
53 	/* No of CPU cores - cluster1 */
54 	PLATFORM_MAX_CPUS_PER_CLUSTER
55 };
56 
57 /*******************************************************************************
58  * This function returns the Tegra default topology tree information.
59  ******************************************************************************/
60 const unsigned char *plat_get_power_domain_tree_desc(void)
61 {
62 	return tegra_power_domain_tree_desc;
63 }
64 
65 /*
66  * Table of regions to map using the MMU.
67  */
68 static const mmap_region_t tegra_mmap[] = {
69 	MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x10000, /* 64KB */
70 			MT_DEVICE | MT_RW | MT_SECURE),
71 	MAP_REGION_FLAT(TEGRA_TSA_BASE, 0x20000, /* 128KB */
72 			MT_DEVICE | MT_RW | MT_SECURE),
73 	MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x10000, /* 64KB */
74 			MT_DEVICE | MT_RW | MT_SECURE),
75 	MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000, /* 64KB */
76 			MT_DEVICE | MT_RW | MT_SECURE),
77 	MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000, /* 128KB - UART A, B*/
78 			MT_DEVICE | MT_RW | MT_SECURE),
79 	MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000, /* 128KB - UART C, G */
80 			MT_DEVICE | MT_RW | MT_SECURE),
81 	MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000, /* 192KB - UART D, E, F */
82 			MT_DEVICE | MT_RW | MT_SECURE),
83 	MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000, /* 64KB */
84 			MT_DEVICE | MT_RW | MT_SECURE),
85 	MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */
86 			MT_DEVICE | MT_RW | MT_SECURE),
87 	MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000, /* 64KB */
88 			MT_DEVICE | MT_RW | MT_SECURE),
89 	MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000, /* 64KB */
90 			MT_DEVICE | MT_RW | MT_SECURE),
91 	MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000, /* 64KB */
92 			MT_DEVICE | MT_RW | MT_SECURE),
93 	MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000, /* 64KB */
94 			MT_DEVICE | MT_RW | MT_SECURE),
95 	MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000, /* 256KB */
96 			MT_DEVICE | MT_RW | MT_SECURE),
97 	MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000, /* 64KB */
98 			MT_DEVICE | MT_RW | MT_SECURE),
99 	MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */
100 			MT_DEVICE | MT_RW | MT_SECURE),
101 	MAP_REGION_FLAT(TEGRA_ARM_ACTMON_CTR_BASE, 0x20000, /* 128KB - ARM/Denver */
102 			MT_DEVICE | MT_RW | MT_SECURE),
103 	MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000, /* 64KB */
104 			MT_DEVICE | MT_RW | MT_SECURE),
105 	{0}
106 };
107 
108 /*******************************************************************************
109  * Set up the pagetables as per the platform memory map & initialize the MMU
110  ******************************************************************************/
111 const mmap_region_t *plat_get_mmio_map(void)
112 {
113 	/* MMIO space */
114 	return tegra_mmap;
115 }
116 
117 /*******************************************************************************
118  * Handler to get the System Counter Frequency
119  ******************************************************************************/
120 unsigned int plat_get_syscnt_freq2(void)
121 {
122 	return 31250000;
123 }
124 
125 /*******************************************************************************
126  * Maximum supported UART controllers
127  ******************************************************************************/
128 #define TEGRA186_MAX_UART_PORTS		7
129 
130 /*******************************************************************************
131  * This variable holds the UART port base addresses
132  ******************************************************************************/
133 static uint32_t tegra186_uart_addresses[TEGRA186_MAX_UART_PORTS + 1] = {
134 	0,	/* undefined - treated as an error case */
135 	TEGRA_UARTA_BASE,
136 	TEGRA_UARTB_BASE,
137 	TEGRA_UARTC_BASE,
138 	TEGRA_UARTD_BASE,
139 	TEGRA_UARTE_BASE,
140 	TEGRA_UARTF_BASE,
141 	TEGRA_UARTG_BASE,
142 };
143 
144 /*******************************************************************************
145  * Retrieve the UART controller base to be used as the console
146  ******************************************************************************/
147 uint32_t plat_get_console_from_id(int id)
148 {
149 	if (id > TEGRA186_MAX_UART_PORTS)
150 		return 0;
151 
152 	return tegra186_uart_addresses[id];
153 }
154 
155 /* represent chip-version as concatenation of major (15:12), minor (11:8) and subrev (7:0) */
156 #define TEGRA186_VER_A02P	0x1201
157 
158 /*******************************************************************************
159  * Handler for early platform setup
160  ******************************************************************************/
161 void plat_early_platform_setup(void)
162 {
163 	int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
164 	uint32_t chip_subrev, val;
165 
166 	/* sanity check MCE firmware compatibility */
167 	mce_verify_firmware_version();
168 
169 	/*
170 	 * Enable ECC and Parity Protection for Cortex-A57 CPUs
171 	 * for Tegra A02p SKUs
172 	 */
173 	if (impl != DENVER_IMPL) {
174 
175 		/* get the major, minor and sub-version values */
176 		chip_subrev = mmio_read_32(TEGRA_FUSE_BASE + OPT_SUBREVISION) &
177 			      SUBREVISION_MASK;
178 
179 		/* prepare chip version number */
180 		val = (tegra_get_chipid_major() << 12) |
181 		      (tegra_get_chipid_minor() << 8) |
182 		       chip_subrev;
183 
184 		/* enable L2 ECC for Tegra186 A02P and beyond */
185 		if (val >= TEGRA186_VER_A02P) {
186 
187 			val = read_l2ctlr_el1();
188 			val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
189 			write_l2ctlr_el1(val);
190 
191 			/*
192 			 * Set the flag to enable ECC/Parity Protection
193 			 * when we exit System Suspend or Cluster Powerdn
194 			 */
195 			tegra_enable_l2_ecc_parity_prot = 1;
196 		}
197 	}
198 }
199 
200 /* Secure IRQs for Tegra186 */
201 static const interrupt_prop_t tegra186_interrupt_props[] = {
202 	INTR_PROP_DESC(TEGRA186_TOP_WDT_IRQ, GIC_HIGHEST_SEC_PRIORITY,
203 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
204 	INTR_PROP_DESC(TEGRA186_AON_WDT_IRQ, GIC_HIGHEST_SEC_PRIORITY,
205 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE)
206 };
207 
208 /*******************************************************************************
209  * Initialize the GIC and SGIs
210  ******************************************************************************/
211 void plat_gic_setup(void)
212 {
213 	tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props));
214 
215 	/*
216 	 * Initialize the FIQ handler only if the platform supports any
217 	 * FIQ interrupt sources.
218 	 */
219 	if (sizeof(tegra186_interrupt_props) > 0)
220 		tegra_fiq_handler_setup();
221 }
222 
223 /*******************************************************************************
224  * Return pointer to the BL31 params from previous bootloader
225  ******************************************************************************/
226 struct tegra_bl31_params *plat_get_bl31_params(void)
227 {
228 	uint32_t val;
229 
230 	val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_LO);
231 
232 	return (struct tegra_bl31_params *)(uintptr_t)val;
233 }
234 
235 /*******************************************************************************
236  * Return pointer to the BL31 platform params from previous bootloader
237  ******************************************************************************/
238 plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
239 {
240 	uint32_t val;
241 
242 	val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_HI);
243 
244 	return (plat_params_from_bl2_t *)(uintptr_t)val;
245 }
246 
247 /*******************************************************************************
248  * This function implements a part of the critical interface between the psci
249  * generic layer and the platform that allows the former to query the platform
250  * to convert an MPIDR to a unique linear index. An error code (-1) is returned
251  * in case the MPIDR is invalid.
252  ******************************************************************************/
253 int plat_core_pos_by_mpidr(u_register_t mpidr)
254 {
255 	unsigned int cluster_id, cpu_id, pos;
256 
257 	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
258 	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
259 
260 	/*
261 	 * Validate cluster_id by checking whether it represents
262 	 * one of the two clusters present on the platform.
263 	 */
264 	if (cluster_id >= PLATFORM_CLUSTER_COUNT)
265 		return PSCI_E_NOT_PRESENT;
266 
267 	/*
268 	 * Validate cpu_id by checking whether it represents a CPU in
269 	 * one of the two clusters present on the platform.
270 	 */
271 	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
272 		return PSCI_E_NOT_PRESENT;
273 
274 	/* calculate the core position */
275 	pos = cpu_id + (cluster_id << 2);
276 
277 	/* check for non-existent CPUs */
278 	if (pos == TEGRA186_CLUSTER0_CORE2 || pos == TEGRA186_CLUSTER0_CORE3)
279 		return PSCI_E_NOT_PRESENT;
280 
281 	return pos;
282 }
283