xref: /arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <errno.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <arch.h>
11*91f16700Schasinglulu #include <arch_helpers.h>
12*91f16700Schasinglulu #include <common/debug.h>
13*91f16700Schasinglulu #include <denver.h>
14*91f16700Schasinglulu #include <lib/mmio.h>
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #include <mce_private.h>
17*91f16700Schasinglulu #include <platform_def.h>
18*91f16700Schasinglulu #include <t194_nvg.h>
19*91f16700Schasinglulu #include <tegra_private.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #define	ID_AFR0_EL1_CACHE_OPS_SHIFT	U(12)
22*91f16700Schasinglulu #define	ID_AFR0_EL1_CACHE_OPS_MASK	U(0xF)
23*91f16700Schasinglulu /*
24*91f16700Schasinglulu  * Reports the major and minor version of this interface.
25*91f16700Schasinglulu  *
26*91f16700Schasinglulu  * NVGDATA[0:31]: SW(R) Minor Version
27*91f16700Schasinglulu  * NVGDATA[32:63]: SW(R) Major Version
28*91f16700Schasinglulu  */
29*91f16700Schasinglulu uint64_t nvg_get_version(void)
30*91f16700Schasinglulu {
31*91f16700Schasinglulu 	nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_VERSION);
32*91f16700Schasinglulu 
33*91f16700Schasinglulu 	return (uint64_t)nvg_get_result();
34*91f16700Schasinglulu }
35*91f16700Schasinglulu 
36*91f16700Schasinglulu /*
37*91f16700Schasinglulu  * Set the expected wake time in TSC ticks for the next low-power state the
38*91f16700Schasinglulu  * core enters.
39*91f16700Schasinglulu  *
40*91f16700Schasinglulu  * NVGDATA[0:31]: SW(RW), WAKE_TIME
41*91f16700Schasinglulu  */
42*91f16700Schasinglulu void nvg_set_wake_time(uint32_t wake_time)
43*91f16700Schasinglulu {
44*91f16700Schasinglulu 	/* time (TSC ticks) until the core is expected to get a wake event */
45*91f16700Schasinglulu 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, (uint64_t)wake_time);
46*91f16700Schasinglulu }
47*91f16700Schasinglulu 
48*91f16700Schasinglulu /*
49*91f16700Schasinglulu  * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
50*91f16700Schasinglulu  * SYSTEM_CSTATE values.
51*91f16700Schasinglulu  *
52*91f16700Schasinglulu  * NVGDATA[0:2]: SW(RW), CLUSTER_CSTATE
53*91f16700Schasinglulu  * NVGDATA[7]: SW(W), update cluster flag
54*91f16700Schasinglulu  * NVGDATA[8:10]: SW(RW), CG_CSTATE
55*91f16700Schasinglulu  * NVGDATA[15]: SW(W), update ccplex flag
56*91f16700Schasinglulu  * NVGDATA[16:19]: SW(RW), SYSTEM_CSTATE
57*91f16700Schasinglulu  * NVGDATA[23]: SW(W), update system flag
58*91f16700Schasinglulu  * NVGDATA[31]: SW(W), update wake mask flag
59*91f16700Schasinglulu  * NVGDATA[32:63]: SW(RW), WAKE_MASK
60*91f16700Schasinglulu  */
61*91f16700Schasinglulu void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex,
62*91f16700Schasinglulu 		uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask)
63*91f16700Schasinglulu {
64*91f16700Schasinglulu 	uint64_t val = 0;
65*91f16700Schasinglulu 
66*91f16700Schasinglulu 	/* update CLUSTER_CSTATE? */
67*91f16700Schasinglulu 	if (cluster != 0U) {
68*91f16700Schasinglulu 		val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) |
69*91f16700Schasinglulu 				CLUSTER_CSTATE_UPDATE_BIT;
70*91f16700Schasinglulu 	}
71*91f16700Schasinglulu 
72*91f16700Schasinglulu 	/* update CCPLEX_CSTATE? */
73*91f16700Schasinglulu 	if (ccplex != 0U) {
74*91f16700Schasinglulu 		val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) |
75*91f16700Schasinglulu 				CCPLEX_CSTATE_UPDATE_BIT;
76*91f16700Schasinglulu 	}
77*91f16700Schasinglulu 
78*91f16700Schasinglulu 	/* update SYSTEM_CSTATE? */
79*91f16700Schasinglulu 	if (system != 0U) {
80*91f16700Schasinglulu 		val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
81*91f16700Schasinglulu 				SYSTEM_CSTATE_UPDATE_BIT;
82*91f16700Schasinglulu 	}
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 	/* update wake mask value? */
85*91f16700Schasinglulu 	if (update_wake_mask != 0U) {
86*91f16700Schasinglulu 		val |= CSTATE_WAKE_MASK_UPDATE_BIT;
87*91f16700Schasinglulu 	}
88*91f16700Schasinglulu 
89*91f16700Schasinglulu 	/* set the wake mask */
90*91f16700Schasinglulu 	val |= ((uint64_t)wake_mask & CSTATE_WAKE_MASK_CLEAR) << CSTATE_WAKE_MASK_SHIFT;
91*91f16700Schasinglulu 
92*91f16700Schasinglulu 	/* set the updated cstate info */
93*91f16700Schasinglulu 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
94*91f16700Schasinglulu }
95*91f16700Schasinglulu 
96*91f16700Schasinglulu /*
97*91f16700Schasinglulu  * Return a non-zero value if the CCPLEX is able to enter SC7
98*91f16700Schasinglulu  *
99*91f16700Schasinglulu  * NVGDATA[0]: SW(R), Is allowed result
100*91f16700Schasinglulu  */
101*91f16700Schasinglulu int32_t nvg_is_sc7_allowed(void)
102*91f16700Schasinglulu {
103*91f16700Schasinglulu 	/* issue command to check if SC7 is allowed */
104*91f16700Schasinglulu 	nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED);
105*91f16700Schasinglulu 
106*91f16700Schasinglulu 	/* 1 = SC7 allowed, 0 = SC7 not allowed */
107*91f16700Schasinglulu 	return (int32_t)nvg_get_result();
108*91f16700Schasinglulu }
109*91f16700Schasinglulu 
110*91f16700Schasinglulu /*
111*91f16700Schasinglulu  * Wake an offlined logical core. Note that a core is offlined by entering
112*91f16700Schasinglulu  * a C-state where the WAKE_MASK is all 0.
113*91f16700Schasinglulu  *
114*91f16700Schasinglulu  * NVGDATA[0:3]: SW(W) logical core to online
115*91f16700Schasinglulu  */
116*91f16700Schasinglulu int32_t nvg_online_core(uint32_t core)
117*91f16700Schasinglulu {
118*91f16700Schasinglulu 	int32_t ret = 0;
119*91f16700Schasinglulu 
120*91f16700Schasinglulu 	/* sanity check the core ID value */
121*91f16700Schasinglulu 	if (core > (uint32_t)PLATFORM_CORE_COUNT) {
122*91f16700Schasinglulu 		ERROR("%s: unknown core id (%d)\n", __func__, core);
123*91f16700Schasinglulu 		ret = -EINVAL;
124*91f16700Schasinglulu 	} else {
125*91f16700Schasinglulu 		/* get a core online */
126*91f16700Schasinglulu 		nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE,
127*91f16700Schasinglulu 					(uint64_t)core & MCE_CORE_ID_MASK);
128*91f16700Schasinglulu 	}
129*91f16700Schasinglulu 
130*91f16700Schasinglulu 	return ret;
131*91f16700Schasinglulu }
132*91f16700Schasinglulu 
133*91f16700Schasinglulu /*
134*91f16700Schasinglulu  * MC GSC (General Security Carveout) register values are expected to be
135*91f16700Schasinglulu  * changed by TrustZone ARM code after boot.
136*91f16700Schasinglulu  *
137*91f16700Schasinglulu  * NVGDATA[0:15] SW(R) GSC enun
138*91f16700Schasinglulu  */
139*91f16700Schasinglulu int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx)
140*91f16700Schasinglulu {
141*91f16700Schasinglulu 	int32_t ret = 0;
142*91f16700Schasinglulu 
143*91f16700Schasinglulu 	/* sanity check GSC ID */
144*91f16700Schasinglulu 	if (gsc_idx > (uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR) {
145*91f16700Schasinglulu 		ERROR("%s: unknown gsc_idx (%u)\n", __func__, gsc_idx);
146*91f16700Schasinglulu 		ret = -EINVAL;
147*91f16700Schasinglulu 	} else {
148*91f16700Schasinglulu 		nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC,
149*91f16700Schasinglulu 				     (uint64_t)gsc_idx);
150*91f16700Schasinglulu 	}
151*91f16700Schasinglulu 
152*91f16700Schasinglulu 	return ret;
153*91f16700Schasinglulu }
154*91f16700Schasinglulu 
155*91f16700Schasinglulu /*
156*91f16700Schasinglulu  * Cache clean and invalidate, clear TR-bit operation for all CCPLEX caches.
157*91f16700Schasinglulu  */
158*91f16700Schasinglulu int32_t nvg_roc_clean_cache_trbits(void)
159*91f16700Schasinglulu {
160*91f16700Schasinglulu 	int32_t ret = 0;
161*91f16700Schasinglulu 
162*91f16700Schasinglulu 	/* check if cache flush through mts is supported */
163*91f16700Schasinglulu 	if (((read_id_afr0_el1() >> ID_AFR0_EL1_CACHE_OPS_SHIFT) &
164*91f16700Schasinglulu 			ID_AFR0_EL1_CACHE_OPS_MASK) == 1U) {
165*91f16700Schasinglulu 		if (nvg_cache_inval_all() == 0U) {
166*91f16700Schasinglulu 			ERROR("%s: failed\n", __func__);
167*91f16700Schasinglulu 			ret = -ENODEV;
168*91f16700Schasinglulu 		}
169*91f16700Schasinglulu 	} else {
170*91f16700Schasinglulu 		ret = -ENOTSUP;
171*91f16700Schasinglulu 	}
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 	return ret;
174*91f16700Schasinglulu }
175*91f16700Schasinglulu 
176*91f16700Schasinglulu /*
177*91f16700Schasinglulu  * Set the power state for a core
178*91f16700Schasinglulu  */
179*91f16700Schasinglulu int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time)
180*91f16700Schasinglulu {
181*91f16700Schasinglulu 	int32_t ret = 0;
182*91f16700Schasinglulu 	uint64_t val = 0ULL;
183*91f16700Schasinglulu 
184*91f16700Schasinglulu 	/* check for allowed power state */
185*91f16700Schasinglulu 	if ((state != (uint32_t)TEGRA_NVG_CORE_C0) &&
186*91f16700Schasinglulu 		(state != (uint32_t)TEGRA_NVG_CORE_C1) &&
187*91f16700Schasinglulu 	    (state != (uint32_t)TEGRA_NVG_CORE_C6) &&
188*91f16700Schasinglulu 		(state != (uint32_t)TEGRA_NVG_CORE_C7))
189*91f16700Schasinglulu 	{
190*91f16700Schasinglulu 		ERROR("%s: unknown cstate (%u)\n", __func__, state);
191*91f16700Schasinglulu 		ret = -EINVAL;
192*91f16700Schasinglulu 	} else {
193*91f16700Schasinglulu 		/* time (TSC ticks) until the core is expected to get a wake event */
194*91f16700Schasinglulu 		nvg_set_wake_time(wake_time);
195*91f16700Schasinglulu 
196*91f16700Schasinglulu 		/* set the core cstate */
197*91f16700Schasinglulu 		val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
198*91f16700Schasinglulu 		write_actlr_el1(val | (uint64_t)state);
199*91f16700Schasinglulu 	}
200*91f16700Schasinglulu 
201*91f16700Schasinglulu 	return ret;
202*91f16700Schasinglulu }
203*91f16700Schasinglulu 
204*91f16700Schasinglulu #if ENABLE_STRICT_CHECKING_MODE
205*91f16700Schasinglulu /*
206*91f16700Schasinglulu  * Enable strict checking mode
207*91f16700Schasinglulu  *
208*91f16700Schasinglulu  * NVGDATA[3] strict_check ON + lock
209*91f16700Schasinglulu  */
210*91f16700Schasinglulu void nvg_enable_strict_checking_mode(void)
211*91f16700Schasinglulu {
212*91f16700Schasinglulu 	uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
213*91f16700Schasinglulu 				     STRICT_CHECKING_LOCKED_SET);
214*91f16700Schasinglulu 
215*91f16700Schasinglulu 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG, params);
216*91f16700Schasinglulu }
217*91f16700Schasinglulu 
218*91f16700Schasinglulu void nvg_verify_strict_checking_mode(void)
219*91f16700Schasinglulu {
220*91f16700Schasinglulu 	uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
221*91f16700Schasinglulu 				     STRICT_CHECKING_LOCKED_SET);
222*91f16700Schasinglulu 
223*91f16700Schasinglulu 	nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG);
224*91f16700Schasinglulu 	assert(params == (uint64_t)nvg_get_result());
225*91f16700Schasinglulu }
226*91f16700Schasinglulu #endif
227*91f16700Schasinglulu 
228*91f16700Schasinglulu /*
229*91f16700Schasinglulu  * Request a reboot
230*91f16700Schasinglulu  *
231*91f16700Schasinglulu  * NVGDATA[0]: reboot command
232*91f16700Schasinglulu  */
233*91f16700Schasinglulu void nvg_system_reboot(void)
234*91f16700Schasinglulu {
235*91f16700Schasinglulu 	/* issue command for reboot */
236*91f16700Schasinglulu 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
237*91f16700Schasinglulu 			     (uint64_t)TEGRA_NVG_REBOOT);
238*91f16700Schasinglulu }
239*91f16700Schasinglulu 
240*91f16700Schasinglulu /*
241*91f16700Schasinglulu  * Request a shutdown
242*91f16700Schasinglulu  *
243*91f16700Schasinglulu  * NVGDATA[0]: shutdown command
244*91f16700Schasinglulu  */
245*91f16700Schasinglulu void nvg_system_shutdown(void)
246*91f16700Schasinglulu {
247*91f16700Schasinglulu 	/* issue command for shutdown */
248*91f16700Schasinglulu 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
249*91f16700Schasinglulu 			     (uint64_t)TEGRA_NVG_SHUTDOWN);
250*91f16700Schasinglulu }
251*91f16700Schasinglulu 
252*91f16700Schasinglulu /*
253*91f16700Schasinglulu  * Request to clear CCPLEX->HSM correctable error signal.
254*91f16700Schasinglulu  * NVGDATA[1]: A write of 1 clears the CCPLEX->HSM correctable error signal,
255*91f16700Schasinglulu  *             A write of 0 has no effect.
256*91f16700Schasinglulu  */
257*91f16700Schasinglulu void nvg_clear_hsm_corr_status(void)
258*91f16700Schasinglulu {
259*91f16700Schasinglulu 	nvg_hsm_error_ctrl_channel_t status = { .bits = { .corr = 1U, }, };
260*91f16700Schasinglulu 
261*91f16700Schasinglulu 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL, status.flat);
262*91f16700Schasinglulu }
263