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 <errno.h> 8 9 #include <arch.h> 10 #include <arch_helpers.h> 11 #include <common/debug.h> 12 #include <denver.h> 13 #include <lib/mmio.h> 14 15 #include <mce_private.h> 16 #include <t18x_ari.h> 17 18 int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) 19 { 20 int32_t ret = 0; 21 22 (void)ari_base; 23 24 /* check for allowed power state */ 25 if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) && 26 (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) { 27 ERROR("%s: unknown cstate (%d)\n", __func__, state); 28 ret = EINVAL; 29 } else { 30 /* time (TSC ticks) until the core is expected to get a wake event */ 31 nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time); 32 33 /* set the core cstate */ 34 write_actlr_el1(state); 35 } 36 37 return ret; 38 } 39 40 /* 41 * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and 42 * SYSTEM_CSTATE values. 43 */ 44 int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, 45 uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, 46 uint8_t update_wake_mask) 47 { 48 uint64_t val = 0ULL; 49 50 (void)ari_base; 51 52 /* update CLUSTER_CSTATE? */ 53 if (cluster != 0U) { 54 val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) | 55 CLUSTER_CSTATE_UPDATE_BIT; 56 } 57 58 /* update CCPLEX_CSTATE? */ 59 if (ccplex != 0U) { 60 val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) | 61 CCPLEX_CSTATE_UPDATE_BIT; 62 } 63 64 /* update SYSTEM_CSTATE? */ 65 if (system != 0U) { 66 val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | 67 (((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | 68 SYSTEM_CSTATE_UPDATE_BIT); 69 } 70 71 /* update wake mask value? */ 72 if (update_wake_mask != 0U) { 73 val |= CSTATE_WAKE_MASK_UPDATE_BIT; 74 } 75 76 /* set the wake mask */ 77 val &= CSTATE_WAKE_MASK_CLEAR; 78 val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT); 79 80 /* set the updated cstate info */ 81 nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val); 82 83 return 0; 84 } 85 86 int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) 87 { 88 int32_t ret = 0; 89 90 (void)ari_base; 91 92 /* sanity check crossover type */ 93 if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) { 94 ret = EINVAL; 95 } else { 96 /* 97 * The crossover threshold limit types start from 98 * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7. 99 * The command indices for updating the threshold be generated 100 * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6 101 * command index. 102 */ 103 nvg_set_request_data((TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 + 104 (uint64_t)type), (uint64_t)time); 105 } 106 107 return ret; 108 } 109 110 uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state) 111 { 112 uint64_t ret; 113 114 (void)ari_base; 115 116 /* sanity check state */ 117 if (state == 0U) { 118 ret = EINVAL; 119 } else { 120 /* 121 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES 122 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for 123 * reading the threshold can be generated by adding the type to 124 * the NVG_CLEAR_CSTATE_STATS command index. 125 */ 126 nvg_set_request((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + 127 (uint64_t)state)); 128 ret = nvg_get_result(); 129 } 130 131 return ret; 132 } 133 134 int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) 135 { 136 uint64_t val; 137 138 (void)ari_base; 139 140 /* 141 * The only difference between a CSTATE_STATS_WRITE and 142 * CSTATE_STATS_READ is the usage of the 63:32 in the request. 143 * 63:32 are set to '0' for a read, while a write contains the 144 * actual stats value to be written. 145 */ 146 val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state; 147 148 /* 149 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES 150 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for 151 * reading the threshold can be generated by adding the type to 152 * the NVG_CLEAR_CSTATE_STATS command index. 153 */ 154 nvg_set_request_data((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + 155 (uint64_t)state), val); 156 157 return 0; 158 } 159 160 int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 161 { 162 (void)ari_base; 163 (void)state; 164 (void)wake_time; 165 166 /* This does not apply to the Denver cluster */ 167 return 0; 168 } 169 170 int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 171 { 172 uint64_t val; 173 int32_t ret; 174 175 (void)ari_base; 176 177 /* check for allowed power state */ 178 if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) && 179 (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) { 180 ERROR("%s: unknown cstate (%d)\n", __func__, state); 181 ret = EINVAL; 182 } else { 183 /* 184 * Request format - 185 * 63:32 = wake time 186 * 31:0 = C-state for this core 187 */ 188 val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) | 189 ((uint64_t)state & MCE_SC7_ALLOWED_MASK); 190 191 /* issue command to check if SC7 is allowed */ 192 nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val); 193 194 /* 1 = SC7 allowed, 0 = SC7 not allowed */ 195 ret = (nvg_get_result() != 0ULL) ? 1 : 0; 196 } 197 198 return ret; 199 } 200 201 int32_t nvg_online_core(uint32_t ari_base, uint32_t core) 202 { 203 uint64_t cpu = read_mpidr() & MPIDR_CPU_MASK; 204 uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 205 int32_t ret = 0; 206 207 (void)ari_base; 208 209 /* sanity check code id */ 210 if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { 211 ERROR("%s: unsupported core id (%d)\n", __func__, core); 212 ret = EINVAL; 213 } else { 214 /* 215 * The Denver cluster has 2 CPUs only - 0, 1. 216 */ 217 if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) { 218 ERROR("%s: unknown core id (%d)\n", __func__, core); 219 ret = EINVAL; 220 } else { 221 /* get a core online */ 222 nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, 223 ((uint64_t)core & MCE_CORE_ID_MASK)); 224 } 225 } 226 227 return ret; 228 } 229 230 int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) 231 { 232 uint32_t val; 233 234 (void)ari_base; 235 236 /* 237 * If the enable bit is cleared, Auto-CC3 will be disabled by setting 238 * the SW visible voltage/frequency request registers for all non 239 * floorswept cores valid independent of StandbyWFI and disabling 240 * the IDLE voltage/frequency request register. If set, Auto-CC3 241 * will be enabled by setting the ARM SW visible voltage/frequency 242 * request registers for all non floorswept cores to be enabled by 243 * StandbyWFI or the equivalent signal, and always keeping the IDLE 244 * voltage/frequency request register enabled. 245 */ 246 val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ 247 ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ 248 ((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U)); 249 250 nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, (uint64_t)val); 251 252 return 0; 253 } 254