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