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 /******************************************************************************* 41 * Register offsets for ARI request/results 42 ******************************************************************************/ 43 #define ARI_REQUEST 0x0 44 #define ARI_REQUEST_EVENT_MASK 0x4 45 #define ARI_STATUS 0x8 46 #define ARI_REQUEST_DATA_LO 0xC 47 #define ARI_REQUEST_DATA_HI 0x10 48 #define ARI_RESPONSE_DATA_LO 0x14 49 #define ARI_RESPONSE_DATA_HI 0x18 50 51 /* Status values for the current request */ 52 #define ARI_REQ_PENDING 1 53 #define ARI_REQ_ONGOING 3 54 #define ARI_REQUEST_VALID_BIT (1 << 8) 55 #define ARI_EVT_MASK_STANDBYWFI_BIT (1 << 7) 56 57 /******************************************************************************* 58 * ARI helper functions 59 ******************************************************************************/ 60 static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg) 61 { 62 return mmio_read_32(ari_base + reg); 63 } 64 65 static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg) 66 { 67 mmio_write_32(ari_base + reg, val); 68 } 69 70 static inline uint32_t ari_get_request_low(uint32_t ari_base) 71 { 72 return ari_read_32(ari_base, ARI_REQUEST_DATA_LO); 73 } 74 75 static inline uint32_t ari_get_request_high(uint32_t ari_base) 76 { 77 return ari_read_32(ari_base, ARI_REQUEST_DATA_HI); 78 } 79 80 static inline uint32_t ari_get_response_low(uint32_t ari_base) 81 { 82 return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO); 83 } 84 85 static inline uint32_t ari_get_response_high(uint32_t ari_base) 86 { 87 return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI); 88 } 89 90 static inline void ari_clobber_response(uint32_t ari_base) 91 { 92 ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); 93 ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); 94 } 95 96 static int ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, 97 uint32_t lo, uint32_t hi) 98 { 99 int status; 100 101 /* program the request, event_mask, hi and lo registers */ 102 ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO); 103 ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI); 104 ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK); 105 ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST); 106 107 /* 108 * For commands that have an event trigger, we should bypass 109 * ARI_STATUS polling, since MCE is waiting for SW to trigger 110 * the event. 111 */ 112 if (evt_mask) 113 return 0; 114 115 /* NOTE: add timeout check if needed */ 116 status = ari_read_32(ari_base, ARI_STATUS); 117 while (status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) 118 status = ari_read_32(ari_base, ARI_STATUS); 119 120 return 0; 121 } 122 123 int ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) 124 { 125 /* check for allowed power state */ 126 if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && 127 state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { 128 ERROR("%s: unknown cstate (%d)\n", __func__, state); 129 return EINVAL; 130 } 131 132 /* Enter the cstate, to be woken up after wake_time (TSC ticks) */ 133 return ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT, 134 TEGRA_ARI_ENTER_CSTATE, state, wake_time); 135 } 136 137 int ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, 138 uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, 139 uint8_t update_wake_mask) 140 { 141 uint32_t val = 0; 142 143 /* update CLUSTER_CSTATE? */ 144 if (cluster) 145 val |= (cluster & CLUSTER_CSTATE_MASK) | 146 CLUSTER_CSTATE_UPDATE_BIT; 147 148 /* update CCPLEX_CSTATE? */ 149 if (ccplex) 150 val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | 151 CCPLEX_CSTATE_UPDATE_BIT; 152 153 /* update SYSTEM_CSTATE? */ 154 if (system) 155 val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | 156 ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | 157 SYSTEM_CSTATE_UPDATE_BIT); 158 159 /* update wake mask value? */ 160 if (update_wake_mask) 161 val |= CSTATE_WAKE_MASK_UPDATE_BIT; 162 163 /* set the updated cstate info */ 164 return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CSTATE_INFO, val, 165 wake_mask); 166 } 167 168 int ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) 169 { 170 /* sanity check crossover type */ 171 if ((type == TEGRA_ARI_CROSSOVER_C1_C6) || 172 (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) 173 return EINVAL; 174 175 /* update crossover threshold time */ 176 return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CROSSOVER, 177 type, time); 178 } 179 180 uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state) 181 { 182 int ret; 183 184 /* sanity check crossover type */ 185 if (state == 0) 186 return EINVAL; 187 188 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_CSTATE_STATS, state, 0); 189 if (ret != 0) 190 return EINVAL; 191 192 return (uint64_t)ari_get_response_low(ari_base); 193 } 194 195 int ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) 196 { 197 /* write the cstate stats */ 198 return ari_request_wait(ari_base, 0, TEGRA_ARI_WRITE_CSTATE_STATS, state, 199 stats); 200 } 201 202 uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data) 203 { 204 uint64_t resp; 205 int ret; 206 207 /* clean the previous response state */ 208 ari_clobber_response(ari_base); 209 210 /* ARI_REQUEST_DATA_HI is reserved for commands other than 'ECHO' */ 211 if (cmd != TEGRA_ARI_MISC_ECHO) 212 data = 0; 213 214 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MISC, cmd, data); 215 if (ret) 216 return (uint64_t)ret; 217 218 /* get the command response */ 219 resp = ari_get_response_low(ari_base); 220 resp |= ((uint64_t)ari_get_response_high(ari_base) << 32); 221 222 return resp; 223 } 224 225 int ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 226 { 227 int ret; 228 229 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_CCX_ALLOWED, state & 0x7, 230 wake_time); 231 if (ret) { 232 ERROR("%s: failed (%d)\n", __func__, ret); 233 return 0; 234 } 235 236 /* 1 = CCx allowed, 0 = CCx not allowed */ 237 return (ari_get_response_low(ari_base) & 0x1); 238 } 239 240 int ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 241 { 242 int ret; 243 244 /* check for allowed power state */ 245 if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && 246 state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { 247 ERROR("%s: unknown cstate (%d)\n", __func__, state); 248 return EINVAL; 249 } 250 251 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_SC7_ALLOWED, state, 252 wake_time); 253 if (ret) { 254 ERROR("%s: failed (%d)\n", __func__, ret); 255 return 0; 256 } 257 258 /* 1 = SC7 allowed, 0 = SC7 not allowed */ 259 return !!ari_get_response_low(ari_base); 260 } 261 262 int ari_online_core(uint32_t ari_base, uint32_t core) 263 { 264 int cpu = read_mpidr() & MPIDR_CPU_MASK; 265 int cluster = (read_mpidr() & MPIDR_CLUSTER_MASK) >> 266 MPIDR_AFFINITY_BITS; 267 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 268 269 /* construct the current CPU # */ 270 cpu |= (cluster << 2); 271 272 /* sanity check target core id */ 273 if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { 274 ERROR("%s: unsupported core id (%d)\n", __func__, core); 275 return EINVAL; 276 } 277 278 /* 279 * The Denver cluster has 2 CPUs only - 0, 1. 280 */ 281 if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { 282 ERROR("%s: unknown core id (%d)\n", __func__, core); 283 return EINVAL; 284 } 285 286 return ari_request_wait(ari_base, 0, TEGRA_ARI_ONLINE_CORE, core, 0); 287 } 288 289 int ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) 290 { 291 int val; 292 293 /* 294 * If the enable bit is cleared, Auto-CC3 will be disabled by setting 295 * the SW visible voltage/frequency request registers for all non 296 * floorswept cores valid independent of StandbyWFI and disabling 297 * the IDLE voltage/frequency request register. If set, Auto-CC3 298 * will be enabled by setting the ARM SW visible voltage/frequency 299 * request registers for all non floorswept cores to be enabled by 300 * StandbyWFI or the equivalent signal, and always keeping the IDLE 301 * voltage/frequency request register enabled. 302 */ 303 val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ 304 ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ 305 (enable ? MCE_AUTO_CC3_ENABLE_BIT : 0)); 306 307 return ari_request_wait(ari_base, 0, TEGRA_ARI_CC3_CTRL, val, 0); 308 } 309 310 int ari_reset_vector_update(uint32_t ari_base, uint32_t lo, uint32_t hi) 311 { 312 /* 313 * Need to program the CPU reset vector one time during cold boot 314 * and SC7 exit 315 */ 316 ari_request_wait(ari_base, 0, TEGRA_ARI_COPY_MISCREG_AA64_RST, lo, hi); 317 318 return 0; 319 } 320 321 int ari_roc_flush_cache_trbits(uint32_t ari_base) 322 { 323 return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, 324 0, 0); 325 } 326 327 int ari_roc_flush_cache(uint32_t ari_base) 328 { 329 return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, 330 0, 0); 331 } 332 333 int ari_roc_clean_cache(uint32_t ari_base) 334 { 335 return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, 336 0, 0); 337 } 338 339 uint64_t ari_read_write_mca(uint32_t ari_base, mca_cmd_t cmd, uint64_t *data) 340 { 341 mca_arg_t mca_arg; 342 int ret; 343 344 /* Set data (write) */ 345 mca_arg.data = data ? *data : 0ull; 346 347 /* Set command */ 348 ari_write_32(ari_base, cmd.input.low, ARI_RESPONSE_DATA_LO); 349 ari_write_32(ari_base, cmd.input.high, ARI_RESPONSE_DATA_HI); 350 351 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MCA, mca_arg.arg.low, 352 mca_arg.arg.high); 353 if (!ret) { 354 mca_arg.arg.low = ari_get_response_low(ari_base); 355 mca_arg.arg.high = ari_get_response_high(ari_base); 356 if (!mca_arg.err.finish) 357 return (uint64_t)mca_arg.err.error; 358 359 if (data) { 360 mca_arg.arg.low = ari_get_request_low(ari_base); 361 mca_arg.arg.high = ari_get_request_high(ari_base); 362 *data = mca_arg.data; 363 } 364 } 365 366 return 0; 367 } 368 369 int ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) 370 { 371 /* sanity check GSC ID */ 372 if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) 373 return EINVAL; 374 375 /* 376 * The MCE code will read the GSC carveout value, corrseponding to 377 * the ID, from the MC registers and update the internal GSC registers 378 * of the CCPLEX. 379 */ 380 ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0); 381 382 return 0; 383 } 384 385 void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx) 386 { 387 /* 388 * The MCE will shutdown or restart the entire system 389 */ 390 (void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, state_idx, 0); 391 } 392