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