1 /* 2 * Copyright (c) 2015-2017, 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 <assert.h> 34 #include <debug.h> 35 #include <delay_timer.h> 36 #include <denver.h> 37 #include <mmio.h> 38 #include <mce_private.h> 39 #include <platform.h> 40 #include <sys/errno.h> 41 #include <t18x_ari.h> 42 43 /******************************************************************************* 44 * Register offsets for ARI request/results 45 ******************************************************************************/ 46 #define ARI_REQUEST 0x0 47 #define ARI_REQUEST_EVENT_MASK 0x4 48 #define ARI_STATUS 0x8 49 #define ARI_REQUEST_DATA_LO 0xC 50 #define ARI_REQUEST_DATA_HI 0x10 51 #define ARI_RESPONSE_DATA_LO 0x14 52 #define ARI_RESPONSE_DATA_HI 0x18 53 54 /* Status values for the current request */ 55 #define ARI_REQ_PENDING 1U 56 #define ARI_REQ_ONGOING 3U 57 #define ARI_REQUEST_VALID_BIT (1U << 8) 58 #define ARI_EVT_MASK_STANDBYWFI_BIT (1U << 7) 59 60 /* default timeout (ms) to wait for ARI completion */ 61 #define ARI_MAX_RETRY_COUNT 2000 62 63 /******************************************************************************* 64 * ARI helper functions 65 ******************************************************************************/ 66 static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg) 67 { 68 return mmio_read_32(ari_base + reg); 69 } 70 71 static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg) 72 { 73 mmio_write_32(ari_base + reg, val); 74 } 75 76 static inline uint32_t ari_get_request_low(uint32_t ari_base) 77 { 78 return ari_read_32(ari_base, ARI_REQUEST_DATA_LO); 79 } 80 81 static inline uint32_t ari_get_request_high(uint32_t ari_base) 82 { 83 return ari_read_32(ari_base, ARI_REQUEST_DATA_HI); 84 } 85 86 static inline uint32_t ari_get_response_low(uint32_t ari_base) 87 { 88 return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO); 89 } 90 91 static inline uint32_t ari_get_response_high(uint32_t ari_base) 92 { 93 return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI); 94 } 95 96 static inline void ari_clobber_response(uint32_t ari_base) 97 { 98 ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); 99 ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); 100 } 101 102 static int ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, 103 uint32_t lo, uint32_t hi) 104 { 105 uint32_t retries = ARI_MAX_RETRY_COUNT; 106 uint32_t status; 107 108 /* program the request, event_mask, hi and lo registers */ 109 ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO); 110 ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI); 111 ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK); 112 ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST); 113 114 /* 115 * For commands that have an event trigger, we should bypass 116 * ARI_STATUS polling, since MCE is waiting for SW to trigger 117 * the event. 118 */ 119 if (evt_mask) 120 return 0; 121 122 /* For shutdown/reboot commands, we dont have to check for timeouts */ 123 if ((req == (uint32_t)TEGRA_ARI_MISC_CCPLEX) && 124 ((lo == (uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) || 125 (lo == (uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT))) { 126 return 0; 127 } 128 129 /* 130 * Wait for the command response for not more than the timeout 131 */ 132 while (retries != 0U) { 133 134 /* read the command status */ 135 status = ari_read_32(ari_base, ARI_STATUS); 136 if ((status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) == 0U) 137 break; 138 139 /* delay 1 ms */ 140 mdelay(1); 141 142 /* decrement the retry count */ 143 retries--; 144 } 145 146 /* assert if the command timed out */ 147 if (retries == 0U) { 148 ERROR("ARI request timed out: req %d on CPU %d\n", 149 req, plat_my_core_pos()); 150 assert(retries != 0U); 151 } 152 153 return 0; 154 } 155 156 int ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) 157 { 158 /* check for allowed power state */ 159 if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && 160 state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { 161 ERROR("%s: unknown cstate (%d)\n", __func__, state); 162 return EINVAL; 163 } 164 165 /* clean the previous response state */ 166 ari_clobber_response(ari_base); 167 168 /* Enter the cstate, to be woken up after wake_time (TSC ticks) */ 169 return ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT, 170 TEGRA_ARI_ENTER_CSTATE, state, wake_time); 171 } 172 173 int ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, 174 uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, 175 uint8_t update_wake_mask) 176 { 177 uint32_t val = 0; 178 179 /* clean the previous response state */ 180 ari_clobber_response(ari_base); 181 182 /* update CLUSTER_CSTATE? */ 183 if (cluster) 184 val |= (cluster & CLUSTER_CSTATE_MASK) | 185 CLUSTER_CSTATE_UPDATE_BIT; 186 187 /* update CCPLEX_CSTATE? */ 188 if (ccplex) 189 val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | 190 CCPLEX_CSTATE_UPDATE_BIT; 191 192 /* update SYSTEM_CSTATE? */ 193 if (system) 194 val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | 195 ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | 196 SYSTEM_CSTATE_UPDATE_BIT); 197 198 /* update wake mask value? */ 199 if (update_wake_mask) 200 val |= CSTATE_WAKE_MASK_UPDATE_BIT; 201 202 /* set the updated cstate info */ 203 return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CSTATE_INFO, val, 204 wake_mask); 205 } 206 207 int ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) 208 { 209 /* sanity check crossover type */ 210 if ((type == TEGRA_ARI_CROSSOVER_C1_C6) || 211 (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) 212 return EINVAL; 213 214 /* clean the previous response state */ 215 ari_clobber_response(ari_base); 216 217 /* update crossover threshold time */ 218 return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CROSSOVER, 219 type, time); 220 } 221 222 uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state) 223 { 224 int ret; 225 226 /* sanity check crossover type */ 227 if (state == 0) 228 return EINVAL; 229 230 /* clean the previous response state */ 231 ari_clobber_response(ari_base); 232 233 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_CSTATE_STATS, state, 0); 234 if (ret != 0) 235 return EINVAL; 236 237 return (uint64_t)ari_get_response_low(ari_base); 238 } 239 240 int ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) 241 { 242 /* clean the previous response state */ 243 ari_clobber_response(ari_base); 244 245 /* write the cstate stats */ 246 return ari_request_wait(ari_base, 0, TEGRA_ARI_WRITE_CSTATE_STATS, state, 247 stats); 248 } 249 250 uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data) 251 { 252 uint64_t resp; 253 int ret; 254 255 /* clean the previous response state */ 256 ari_clobber_response(ari_base); 257 258 /* ARI_REQUEST_DATA_HI is reserved for commands other than 'ECHO' */ 259 if (cmd != TEGRA_ARI_MISC_ECHO) 260 data = 0; 261 262 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MISC, cmd, data); 263 if (ret) 264 return (uint64_t)ret; 265 266 /* get the command response */ 267 resp = ari_get_response_low(ari_base); 268 resp |= ((uint64_t)ari_get_response_high(ari_base) << 32); 269 270 return resp; 271 } 272 273 int ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 274 { 275 int ret; 276 277 /* clean the previous response state */ 278 ari_clobber_response(ari_base); 279 280 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_CCX_ALLOWED, state & 0x7, 281 wake_time); 282 if (ret) { 283 ERROR("%s: failed (%d)\n", __func__, ret); 284 return 0; 285 } 286 287 /* 1 = CCx allowed, 0 = CCx not allowed */ 288 return (ari_get_response_low(ari_base) & 0x1); 289 } 290 291 int ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) 292 { 293 int ret; 294 295 /* check for allowed power state */ 296 if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && 297 state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { 298 ERROR("%s: unknown cstate (%d)\n", __func__, state); 299 return EINVAL; 300 } 301 302 /* clean the previous response state */ 303 ari_clobber_response(ari_base); 304 305 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_SC7_ALLOWED, state, 306 wake_time); 307 if (ret) { 308 ERROR("%s: failed (%d)\n", __func__, ret); 309 return 0; 310 } 311 312 /* 1 = SC7 allowed, 0 = SC7 not allowed */ 313 return !!ari_get_response_low(ari_base); 314 } 315 316 int ari_online_core(uint32_t ari_base, uint32_t core) 317 { 318 int cpu = read_mpidr() & MPIDR_CPU_MASK; 319 int cluster = (read_mpidr() & MPIDR_CLUSTER_MASK) >> 320 MPIDR_AFFINITY_BITS; 321 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 322 323 /* construct the current CPU # */ 324 cpu |= (cluster << 2); 325 326 /* sanity check target core id */ 327 if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { 328 ERROR("%s: unsupported core id (%d)\n", __func__, core); 329 return EINVAL; 330 } 331 332 /* 333 * The Denver cluster has 2 CPUs only - 0, 1. 334 */ 335 if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { 336 ERROR("%s: unknown core id (%d)\n", __func__, core); 337 return EINVAL; 338 } 339 340 /* clean the previous response state */ 341 ari_clobber_response(ari_base); 342 343 return ari_request_wait(ari_base, 0, TEGRA_ARI_ONLINE_CORE, core, 0); 344 } 345 346 int ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) 347 { 348 int val; 349 350 /* clean the previous response state */ 351 ari_clobber_response(ari_base); 352 353 /* 354 * If the enable bit is cleared, Auto-CC3 will be disabled by setting 355 * the SW visible voltage/frequency request registers for all non 356 * floorswept cores valid independent of StandbyWFI and disabling 357 * the IDLE voltage/frequency request register. If set, Auto-CC3 358 * will be enabled by setting the ARM SW visible voltage/frequency 359 * request registers for all non floorswept cores to be enabled by 360 * StandbyWFI or the equivalent signal, and always keeping the IDLE 361 * voltage/frequency request register enabled. 362 */ 363 val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ 364 ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ 365 (enable ? MCE_AUTO_CC3_ENABLE_BIT : 0)); 366 367 return ari_request_wait(ari_base, 0, TEGRA_ARI_CC3_CTRL, val, 0); 368 } 369 370 int ari_reset_vector_update(uint32_t ari_base) 371 { 372 /* clean the previous response state */ 373 ari_clobber_response(ari_base); 374 375 /* 376 * Need to program the CPU reset vector one time during cold boot 377 * and SC7 exit 378 */ 379 ari_request_wait(ari_base, 0, TEGRA_ARI_COPY_MISCREG_AA64_RST, 0, 0); 380 381 return 0; 382 } 383 384 int ari_roc_flush_cache_trbits(uint32_t ari_base) 385 { 386 /* clean the previous response state */ 387 ari_clobber_response(ari_base); 388 389 return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, 390 0, 0); 391 } 392 393 int ari_roc_flush_cache(uint32_t ari_base) 394 { 395 /* clean the previous response state */ 396 ari_clobber_response(ari_base); 397 398 return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, 399 0, 0); 400 } 401 402 int ari_roc_clean_cache(uint32_t ari_base) 403 { 404 /* clean the previous response state */ 405 ari_clobber_response(ari_base); 406 407 return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, 408 0, 0); 409 } 410 411 uint64_t ari_read_write_mca(uint32_t ari_base, mca_cmd_t cmd, uint64_t *data) 412 { 413 mca_arg_t mca_arg; 414 int ret; 415 416 /* Set data (write) */ 417 mca_arg.data = data ? *data : 0ull; 418 419 /* Set command */ 420 ari_write_32(ari_base, cmd.input.low, ARI_RESPONSE_DATA_LO); 421 ari_write_32(ari_base, cmd.input.high, ARI_RESPONSE_DATA_HI); 422 423 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MCA, mca_arg.arg.low, 424 mca_arg.arg.high); 425 if (!ret) { 426 mca_arg.arg.low = ari_get_response_low(ari_base); 427 mca_arg.arg.high = ari_get_response_high(ari_base); 428 if (!mca_arg.err.finish) 429 return (uint64_t)mca_arg.err.error; 430 431 if (data) { 432 mca_arg.arg.low = ari_get_request_low(ari_base); 433 mca_arg.arg.high = ari_get_request_high(ari_base); 434 *data = mca_arg.data; 435 } 436 } 437 438 return 0; 439 } 440 441 int ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) 442 { 443 /* sanity check GSC ID */ 444 if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) 445 return EINVAL; 446 447 /* clean the previous response state */ 448 ari_clobber_response(ari_base); 449 450 /* 451 * The MCE code will read the GSC carveout value, corrseponding to 452 * the ID, from the MC registers and update the internal GSC registers 453 * of the CCPLEX. 454 */ 455 ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0); 456 457 return 0; 458 } 459 460 void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx) 461 { 462 /* clean the previous response state */ 463 ari_clobber_response(ari_base); 464 465 /* 466 * The MCE will shutdown or restart the entire system 467 */ 468 (void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, state_idx, 0); 469 } 470 471 int ari_read_write_uncore_perfmon(uint32_t ari_base, 472 uncore_perfmon_req_t req, uint64_t *data) 473 { 474 int ret; 475 uint32_t val; 476 477 /* clean the previous response state */ 478 ari_clobber_response(ari_base); 479 480 /* sanity check input parameters */ 481 if (req.perfmon_command.cmd == UNCORE_PERFMON_CMD_READ && !data) { 482 ERROR("invalid parameters\n"); 483 return EINVAL; 484 } 485 486 /* 487 * For "write" commands get the value that has to be written 488 * to the uncore perfmon registers 489 */ 490 val = (req.perfmon_command.cmd == UNCORE_PERFMON_CMD_WRITE) ? 491 *data : 0; 492 493 ret = ari_request_wait(ari_base, 0, TEGRA_ARI_PERFMON, val, req.data); 494 if (ret) 495 return ret; 496 497 /* read the command status value */ 498 req.perfmon_status.val = ari_get_response_high(ari_base) & 499 UNCORE_PERFMON_RESP_STATUS_MASK; 500 501 /* 502 * For "read" commands get the data from the uncore 503 * perfmon registers 504 */ 505 if ((req.perfmon_status.val == 0) && (req.perfmon_command.cmd == 506 UNCORE_PERFMON_CMD_READ)) 507 *data = ari_get_response_low(ari_base); 508 509 return (int)req.perfmon_status.val; 510 } 511 512 void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value) 513 { 514 /* 515 * This invokes the ARI_MISC_CCPLEX commands. This can be 516 * used to enable/disable coresight clock gating. 517 */ 518 519 if ((index > TEGRA_ARI_MISC_CCPLEX_EDBGREQ) || 520 ((index == TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL) && 521 (value > 1))) { 522 ERROR("%s: invalid parameters \n", __func__); 523 return; 524 } 525 526 /* clean the previous response state */ 527 ari_clobber_response(ari_base); 528 (void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, index, value); 529 } 530