1 /* 2 * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <arch_helpers.h> 9 #include <common/debug.h> 10 #include <denver.h> 11 #include <errno.h> 12 #include <lib/mmio.h> 13 #include <mce_private.h> 14 #include <platform_def.h> 15 #include <t194_nvg.h> 16 #include <tegra_private.h> 17 18 extern void nvg_set_request_data(uint64_t req, uint64_t data); 19 extern void nvg_set_request(uint64_t req); 20 extern uint64_t nvg_get_result(void); 21 22 /* 23 * Reports the major and minor version of this interface. 24 * 25 * NVGDATA[0:31]: SW(R) Minor Version 26 * NVGDATA[32:63]: SW(R) Major Version 27 */ 28 uint64_t nvg_get_version(void) 29 { 30 nvg_set_request(TEGRA_NVG_CHANNEL_VERSION); 31 32 return (uint64_t)nvg_get_result(); 33 } 34 35 /* 36 * Enable the perf per watt mode. 37 * 38 * NVGDATA[0]: SW(RW), 1 = enable perf per watt mode 39 */ 40 int32_t nvg_enable_power_perf_mode(void) 41 { 42 nvg_set_request_data(TEGRA_NVG_CHANNEL_POWER_PERF, 1U); 43 44 return 0; 45 } 46 47 /* 48 * Disable the perf per watt mode. 49 * 50 * NVGDATA[0]: SW(RW), 0 = disable perf per watt mode 51 */ 52 int32_t nvg_disable_power_perf_mode(void) 53 { 54 nvg_set_request_data(TEGRA_NVG_CHANNEL_POWER_PERF, 0U); 55 56 return 0; 57 } 58 59 /* 60 * Enable the battery saver mode. 61 * 62 * NVGDATA[2]: SW(RW), 1 = enable battery saver mode 63 */ 64 int32_t nvg_enable_power_saver_modes(void) 65 { 66 nvg_set_request_data(TEGRA_NVG_CHANNEL_POWER_MODES, 1U); 67 68 return 0; 69 } 70 71 /* 72 * Disable the battery saver mode. 73 * 74 * NVGDATA[2]: SW(RW), 0 = disable battery saver mode 75 */ 76 int32_t nvg_disable_power_saver_modes(void) 77 { 78 nvg_set_request_data(TEGRA_NVG_CHANNEL_POWER_MODES, 0U); 79 80 return 0; 81 } 82 83 /* 84 * Set the expected wake time in TSC ticks for the next low-power state the 85 * core enters. 86 * 87 * NVGDATA[0:31]: SW(RW), WAKE_TIME 88 */ 89 void nvg_set_wake_time(uint32_t wake_time) 90 { 91 /* time (TSC ticks) until the core is expected to get a wake event */ 92 nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, (uint64_t)wake_time); 93 } 94 95 /* 96 * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and 97 * SYSTEM_CSTATE values. 98 * 99 * NVGDATA[0:2]: SW(RW), CLUSTER_CSTATE 100 * NVGDATA[7]: SW(W), update cluster flag 101 * NVGDATA[8:9]: SW(RW), CG_CSTATE 102 * NVGDATA[15]: SW(W), update ccplex flag 103 * NVGDATA[16:19]: SW(RW), SYSTEM_CSTATE 104 * NVGDATA[23]: SW(W), update system flag 105 * NVGDATA[31]: SW(W), update wake mask flag 106 * NVGDATA[32:63]: SW(RW), WAKE_MASK 107 */ 108 void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex, 109 uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask) 110 { 111 uint64_t val = 0; 112 113 /* update CLUSTER_CSTATE? */ 114 if (cluster != 0U) { 115 val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) | 116 CLUSTER_CSTATE_UPDATE_BIT; 117 } 118 119 /* update CCPLEX_CSTATE? */ 120 if (ccplex != 0U) { 121 val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) | 122 CCPLEX_CSTATE_UPDATE_BIT; 123 } 124 125 /* update SYSTEM_CSTATE? */ 126 if (system != 0U) { 127 val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | 128 SYSTEM_CSTATE_UPDATE_BIT; 129 } 130 131 /* update wake mask value? */ 132 if (update_wake_mask != 0U) { 133 val |= CSTATE_WAKE_MASK_UPDATE_BIT; 134 } 135 136 /* set the wake mask */ 137 val |= ((uint64_t)wake_mask & CSTATE_WAKE_MASK_CLEAR) << CSTATE_WAKE_MASK_SHIFT; 138 139 /* set the updated cstate info */ 140 nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val); 141 } 142 143 /* 144 * Indices gives MTS the crossover point in TSC ticks for when it becomes 145 * no longer viable to enter the named state 146 * 147 * Type 0 : NVGDATA[0:31]: C6 Lower bound 148 * Type 1 : NVGDATA[0:31]: CC6 Lower bound 149 * Type 2 : NVGDATA[0:31]: CG7 Lower bound 150 */ 151 int32_t nvg_update_crossover_time(uint32_t type, uint32_t time) 152 { 153 int32_t ret = 0; 154 155 switch (type) { 156 case TEGRA_NVG_CROSSOVER_C6: 157 nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_C6_LOWER_BOUND, 158 (uint64_t)time); 159 break; 160 161 case TEGRA_NVG_CROSSOVER_CC6: 162 nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_CC6_LOWER_BOUND, 163 (uint64_t)time); 164 break; 165 166 case TEGRA_NVG_CROSSOVER_CG7: 167 nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_CG7_LOWER_BOUND, 168 (uint64_t)time); 169 break; 170 171 default: 172 ERROR("%s: unknown crossover type (%d)\n", __func__, type); 173 ret = EINVAL; 174 break; 175 } 176 177 return ret; 178 } 179 180 /* 181 * These NVG calls allow ARM SW to access CSTATE statistical information 182 * 183 * NVGDATA[0:3]: SW(RW) Core/cluster/cg id 184 * NVGDATA[16:31]: SW(RW) Stat id 185 */ 186 int32_t nvg_set_cstate_stat_query_value(uint64_t data) 187 { 188 int32_t ret = 0; 189 190 /* sanity check stat id */ 191 if (data > (uint64_t)NVG_STAT_QUERY_C7_RESIDENCY_SUM) { 192 ERROR("%s: unknown stat id (%d)\n", __func__, (uint32_t)data); 193 ret = EINVAL; 194 } else { 195 nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_REQUEST, data); 196 } 197 198 return ret; 199 } 200 201 /* 202 * The read-only value associated with the CSTATE_STAT_QUERY_REQUEST 203 * 204 * NVGDATA[0:63]: SW(R) Stat count 205 */ 206 uint64_t nvg_get_cstate_stat_query_value(void) 207 { 208 nvg_set_request(TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_VALUE); 209 210 return (uint64_t)nvg_get_result(); 211 } 212 213 /* 214 * Return a non-zero value if the CCPLEX is able to enter SC7 215 * 216 * NVGDATA[0]: SW(R), Is allowed result 217 */ 218 int32_t nvg_is_sc7_allowed(void) 219 { 220 /* issue command to check if SC7 is allowed */ 221 nvg_set_request(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED); 222 223 /* 1 = SC7 allowed, 0 = SC7 not allowed */ 224 return (int32_t)nvg_get_result(); 225 } 226 227 /* 228 * Wake an offlined logical core. Note that a core is offlined by entering 229 * a C-state where the WAKE_MASK is all 0. 230 * 231 * NVGDATA[0:3]: SW(W) logical core to online 232 */ 233 int32_t nvg_online_core(uint32_t core) 234 { 235 int32_t ret = 0; 236 237 /* sanity check the core ID value */ 238 if (core > (uint32_t)PLATFORM_CORE_COUNT) { 239 ERROR("%s: unknown core id (%d)\n", __func__, core); 240 ret = EINVAL; 241 } else { 242 /* get a core online */ 243 nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, 244 (uint64_t)core & MCE_CORE_ID_MASK); 245 } 246 247 return ret; 248 } 249 250 /* 251 * Enables and controls the voltage/frequency hint for CC3. CC3 is disabled 252 * by default. 253 * 254 * NVGDATA[7:0] SW(RW) frequency request 255 * NVGDATA[31:31] SW(RW) enable bit 256 */ 257 int32_t nvg_cc3_ctrl(uint32_t freq, uint8_t enable) 258 { 259 uint64_t val = 0; 260 261 /* 262 * If the enable bit is cleared, Auto-CC3 will be disabled by setting 263 * the SW visible frequency request registers for all non 264 * floorswept cores valid independent of StandbyWFI and disabling 265 * the IDLE frequency request register. If set, Auto-CC3 266 * will be enabled by setting the ARM SW visible frequency 267 * request registers for all non floorswept cores to be enabled by 268 * StandbyWFI or the equivalent signal, and always keeping the IDLE 269 * frequency request register enabled. 270 */ 271 if (enable != 0U) { 272 val = ((uint64_t)freq & MCE_AUTO_CC3_FREQ_MASK) | MCE_AUTO_CC3_ENABLE_BIT; 273 } 274 nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, val); 275 276 return 0; 277 } 278 279 /* 280 * MC GSC (General Security Carveout) register values are expected to be 281 * changed by TrustZone ARM code after boot. 282 * 283 * NVGDATA[0:15] SW(R) GSC enun 284 */ 285 int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx) 286 { 287 int32_t ret = 0; 288 289 /* sanity check GSC ID */ 290 if (gsc_idx > (uint32_t)TEGRA_NVG_GSC_VPR_IDX) { 291 ERROR("%s: unknown gsc_idx (%d)\n", __func__, gsc_idx); 292 ret = EINVAL; 293 } else { 294 nvg_set_request_data(TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC, 295 (uint64_t)gsc_idx); 296 } 297 298 return ret; 299 } 300 301 /* 302 * Cache clean operation for all CCPLEX caches. 303 * 304 * NVGDATA[0] cache_clean 305 */ 306 int32_t nvg_roc_clean_cache(void) 307 { 308 nvg_set_request_data(TEGRA_NVG_CHANNEL_CCPLEX_CACHE_INVAL, 309 (uint64_t)CACHE_CLEAN_SET); 310 311 return 0; 312 } 313 314 /* 315 * Cache clean and invalidate operation for all CCPLEX caches. 316 * 317 * NVGDATA[1] cache_clean_inval 318 */ 319 int32_t nvg_roc_flush_cache(void) 320 { 321 nvg_set_request_data(TEGRA_NVG_CHANNEL_CCPLEX_CACHE_INVAL, 322 (uint64_t)CACHE_CLEAN_INVAL_SET); 323 324 return 0; 325 } 326 327 /* 328 * Cache clean and invalidate, clear TR-bit operation for all CCPLEX caches. 329 * 330 * NVGDATA[2] cache_clean_inval_tr 331 */ 332 int32_t nvg_roc_clean_cache_trbits(void) 333 { 334 nvg_set_request_data(TEGRA_NVG_CHANNEL_CCPLEX_CACHE_INVAL, 335 (uint64_t)CACHE_CLEAN_INVAL_TR_SET); 336 337 return 0; 338 } 339 340 /* 341 * Set the power state for a core 342 */ 343 int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time) 344 { 345 int32_t ret = 0; 346 uint64_t val = 0ULL; 347 348 /* check for allowed power state */ 349 if ((state != (uint32_t)TEGRA_NVG_CORE_C0) && 350 (state != (uint32_t)TEGRA_NVG_CORE_C1) && 351 (state != (uint32_t)TEGRA_NVG_CORE_C6) && 352 (state != (uint32_t)TEGRA_NVG_CORE_C7)) 353 { 354 ERROR("%s: unknown cstate (%d)\n", __func__, state); 355 ret = EINVAL; 356 } else { 357 /* time (TSC ticks) until the core is expected to get a wake event */ 358 nvg_set_wake_time(wake_time); 359 360 /* set the core cstate */ 361 val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK; 362 write_actlr_el1(val | (uint64_t)state); 363 } 364 365 return ret; 366 } 367