1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch.h> 32 #include <arch_helpers.h> 33 #include <debug.h> 34 #include <denver.h> 35 #include <mmio.h> 36 #include <mce.h> 37 #include <sys/errno.h> 38 #include <t18x_ari.h> 39 40 extern void nvg_set_request_data(uint64_t req, uint64_t data); 41 extern void nvg_set_request(uint64_t req); 42 extern uint64_t nvg_get_result(void); 43 44 int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) 45 { 46 /* check for allowed power state */ 47 if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && 48 state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { 49 ERROR("%s: unknown cstate (%d)\n", __func__, state); 50 return EINVAL; 51 } 52 53 /* time (TSC ticks) until the core is expected to get a wake event */ 54 nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time); 55 56 /* set the core cstate */ 57 write_actlr_el1(state); 58 59 return 0; 60 } 61 62 /* 63 * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and 64 * SYSTEM_CSTATE values. 65 */ 66 int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, 67 uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, 68 uint8_t update_wake_mask) 69 { 70 uint64_t val = 0; 71 72 /* update CLUSTER_CSTATE? */ 73 if (cluster) 74 val |= (cluster & CLUSTER_CSTATE_MASK) | 75 CLUSTER_CSTATE_UPDATE_BIT; 76 77 /* update CCPLEX_CSTATE? */ 78 if (ccplex) 79 val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | 80 CCPLEX_CSTATE_UPDATE_BIT; 81 82 /* update SYSTEM_CSTATE? */ 83 if (system) 84 val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | 85 ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | 86 SYSTEM_CSTATE_UPDATE_BIT); 87 88 /* update wake mask value? */ 89 if (update_wake_mask) 90 val |= CSTATE_WAKE_MASK_UPDATE_BIT; 91 92 /* set the wake mask */ 93 val &= CSTATE_WAKE_MASK_CLEAR; 94 val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT); 95 96 /* set the updated cstate info */ 97 nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val); 98 99 return 0; 100 } 101 102 int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) 103 { 104 /* sanity check crossover type */ 105 if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) 106 return EINVAL; 107 108 /* 109 * The crossover threshold limit types start from 110 * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7. The 111 * command indices for updating the threshold can be generated 112 * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6 113 * command index. 114 */ 115 nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 + type, 116 (uint64_t)time); 117 118 return 0; 119 } 120 121 uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state) 122 { 123 /* sanity check state */ 124 if (state == 0) 125 return EINVAL; 126 127 /* 128 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES 129 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for 130 * reading the threshold can be generated by adding the type to 131 * the NVG_CLEAR_CSTATE_STATS command index. 132 */ 133 nvg_set_request(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state); 134 135 return (int64_t)nvg_get_result(); 136 } 137 138 int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) 139 { 140 uint64_t val; 141 142 /* 143 * The only difference between a CSTATE_STATS_WRITE and 144 * CSTATE_STATS_READ is the usage of the 63:32 in the request. 145 * 63:32 are set to '0' for a read, while a write contains the 146 * actual stats value to be written. 147 */ 148 val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state; 149 150 /* 151 * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES 152 * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for 153 * reading the threshold can be generated by adding the type to 154 * the NVG_CLEAR_CSTATE_STATS command index. 155 */ 156 nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state, val); 157 158 return 0; 159 } 160 161 int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 162 { 163 /* This does not apply to the Denver cluster */ 164 return 0; 165 } 166 167 int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 168 { 169 uint64_t val; 170 171 /* check for allowed power state */ 172 if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && 173 state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { 174 ERROR("%s: unknown cstate (%d)\n", __func__, state); 175 return EINVAL; 176 } 177 178 /* 179 * Request format - 180 * 63:32 = wake time 181 * 31:0 = C-state for this core 182 */ 183 val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) | 184 (state & MCE_SC7_ALLOWED_MASK); 185 186 /* issue command to check if SC7 is allowed */ 187 nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val); 188 189 /* 1 = SC7 allowed, 0 = SC7 not allowed */ 190 return !!nvg_get_result(); 191 } 192 193 int nvg_online_core(uint32_t ari_base, uint32_t core) 194 { 195 int cpu = read_mpidr() & MPIDR_CPU_MASK; 196 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 197 198 /* sanity check code id */ 199 if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { 200 ERROR("%s: unsupported core id (%d)\n", __func__, core); 201 return EINVAL; 202 } 203 204 /* 205 * The Denver cluster has 2 CPUs only - 0, 1. 206 */ 207 if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { 208 ERROR("%s: unknown core id (%d)\n", __func__, core); 209 return EINVAL; 210 } 211 212 /* get a core online */ 213 nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, core & MCE_CORE_ID_MASK); 214 215 return 0; 216 } 217 218 int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) 219 { 220 int val; 221 222 /* 223 * If the enable bit is cleared, Auto-CC3 will be disabled by setting 224 * the SW visible voltage/frequency request registers for all non 225 * floorswept cores valid independent of StandbyWFI and disabling 226 * the IDLE voltage/frequency request register. If set, Auto-CC3 227 * will be enabled by setting the ARM SW visible voltage/frequency 228 * request registers for all non floorswept cores to be enabled by 229 * StandbyWFI or the equivalent signal, and always keeping the IDLE 230 * voltage/frequency request register enabled. 231 */ 232 val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ 233 ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ 234 (enable ? MCE_AUTO_CC3_ENABLE_BIT : 0)); 235 236 nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, val); 237 238 return 0; 239 } 240