blob: fb33c13e15b0ff402255fb37d6a25c18795b7405 [file] [log] [blame]
Varun Wadekarecd6a5a2018-04-09 17:48:58 -07001/*
2 * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <arch_helpers.h>
9#include <assert.h>
10#include <common/bl_common.h>
11#include <context.h>
12#include <lib/el3_runtime/context_mgmt.h>
13#include <common/debug.h>
14#include <denver.h>
15#include <mce.h>
16#include <plat/common/platform.h>
17#include <lib/psci/psci.h>
18#include <smmu.h>
19#include <string.h>
20#include <tegra_private.h>
21
22extern void prepare_core_pwr_dwn(void);
23
24#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
25extern void tegra186_cpu_reset_handler(void);
26extern uint32_t __tegra186_cpu_reset_handler_data,
27 __tegra186_cpu_reset_handler_end;
28
29/* TZDRAM offset for saving SMMU context */
30#define TEGRA186_SMMU_CTX_OFFSET 16
31#endif
32
33/* state id mask */
34#define TEGRA186_STATE_ID_MASK 0xF
35/* constants to get power state's wake time */
36#define TEGRA186_WAKE_TIME_MASK 0x0FFFFFF0
37#define TEGRA186_WAKE_TIME_SHIFT 4
38/* default core wake mask for CPU_SUSPEND */
39#define TEGRA186_CORE_WAKE_MASK 0x180c
40/* context size to save during system suspend */
41#define TEGRA186_SE_CONTEXT_SIZE 3
42
43static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE];
44static struct t18x_psci_percpu_data {
45 unsigned int wake_time;
46} __aligned(CACHE_WRITEBACK_GRANULE) percpu_data[PLATFORM_CORE_COUNT];
47
48int32_t tegra_soc_validate_power_state(unsigned int power_state,
49 psci_power_state_t *req_state)
50{
51 int state_id = psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK;
52 int cpu = plat_my_core_pos();
53
54 /* save the core wake time (in TSC ticks)*/
55 percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK)
56 << TEGRA186_WAKE_TIME_SHIFT;
57
58 /*
59 * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that
60 * the correct value is read in tegra_soc_pwr_domain_suspend(), which
61 * is called with caches disabled. It is possible to read a stale value
62 * from DRAM in that function, because the L2 cache is not flushed
63 * unless the cluster is entering CC6/CC7.
64 */
65 clean_dcache_range((uint64_t)&percpu_data[cpu],
66 sizeof(percpu_data[cpu]));
67
68 /* Sanity check the requested state id */
69 switch (state_id) {
70 case PSTATE_ID_CORE_IDLE:
71 case PSTATE_ID_CORE_POWERDN:
72
73 /* Core powerdown request */
74 req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
75 req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
76
77 break;
78
79 default:
80 ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
81 return PSCI_E_INVALID_PARAMS;
82 }
83
84 return PSCI_E_SUCCESS;
85}
86
87int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
88{
89 const plat_local_state_t *pwr_domain_state;
90 unsigned int stateid_afflvl0, stateid_afflvl2;
91#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
92 plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
93 uint64_t smmu_ctx_base;
94#endif
95 uint32_t val;
96
97 /* get the state ID */
98 pwr_domain_state = target_state->pwr_domain_state;
99 stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
100 TEGRA186_STATE_ID_MASK;
101 stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
102 TEGRA186_STATE_ID_MASK;
103
104 if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ||
105 (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
106
107 /* Enter CPU idle/powerdown */
108
109 } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
110
111 /* save SE registers */
112 se_regs[0] = mmio_read_32(TEGRA_SE0_BASE +
113 SE_MUTEX_WATCHDOG_NS_LIMIT);
114 se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE +
115 RNG_MUTEX_WATCHDOG_NS_LIMIT);
116 se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE +
117 PKA_MUTEX_WATCHDOG_NS_LIMIT);
118
119 /* save 'Secure Boot' Processor Feature Config Register */
120 val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
121 mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV6, val);
122
123#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
124 /* save SMMU context */
125 smmu_ctx_base = params_from_bl2->tzdram_base +
126 ((uintptr_t)&__tegra186_cpu_reset_handler_data -
127 (uintptr_t)tegra186_cpu_reset_handler) +
128 TEGRA186_SMMU_CTX_OFFSET;
129 tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
130#else
131 tegra_smmu_save_context(0);
132#endif
133
134 /* Instruct the MCE to enter system suspend state */
135 }
136
137 return PSCI_E_SUCCESS;
138}
139
140/*******************************************************************************
141 * Platform handler to calculate the proper target power level at the
142 * specified affinity level
143 ******************************************************************************/
144plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
145 const plat_local_state_t *states,
146 unsigned int ncpu)
147{
148 plat_local_state_t target = *states;
149 int cluster_powerdn = 1;
150 int core_pos = read_mpidr() & MPIDR_CPU_MASK;
151
152 /* get the current core's power state */
153 target = *(states + core_pos);
154
155 /* CPU suspend */
156 if (lvl == MPIDR_AFFLVL1 && target == PSTATE_ID_CORE_POWERDN) {
157
158 /* Program default wake mask */
159
160 /* Check if CCx state is allowed. */
161 }
162
163 /* CPU off */
164 if (lvl == MPIDR_AFFLVL1 && target == PLAT_MAX_OFF_STATE) {
165
166 /* find out the number of ON cpus in the cluster */
167 do {
168 target = *states++;
169 if (target != PLAT_MAX_OFF_STATE)
170 cluster_powerdn = 0;
171 } while (--ncpu);
172
173 /* Enable cluster powerdn from last CPU in the cluster */
174 if (cluster_powerdn) {
175
176 /* Enable CC7 state and turn off wake mask */
177
178 } else {
179
180 /* Turn off wake_mask */
181 }
182 }
183
184 /* System Suspend */
185 if ((lvl == MPIDR_AFFLVL2) || (target == PSTATE_ID_SOC_POWERDN))
186 return PSTATE_ID_SOC_POWERDN;
187
188 /* default state */
189 return PSCI_LOCAL_STATE_RUN;
190}
191
192#if ENABLE_SYSTEM_SUSPEND_CTX_SAVE_TZDRAM
193int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
194{
195 const plat_local_state_t *pwr_domain_state =
196 target_state->pwr_domain_state;
197 plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
198 unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
199 TEGRA186_STATE_ID_MASK;
200 uint32_t val;
201
202 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
203 /*
204 * The TZRAM loses power when we enter system suspend. To
205 * allow graceful exit from system suspend, we need to copy
206 * BL3-1 over to TZDRAM.
207 */
208 val = params_from_bl2->tzdram_base +
209 ((uintptr_t)&__tegra186_cpu_reset_handler_end -
210 (uintptr_t)tegra186_cpu_reset_handler);
211 memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
212 (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE);
213 }
214
215 return PSCI_E_SUCCESS;
216}
217#endif
218
219int tegra_soc_pwr_domain_on(u_register_t mpidr)
220{
221 int target_cpu = mpidr & MPIDR_CPU_MASK;
222 int target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
223 MPIDR_AFFINITY_BITS;
224
225 if (target_cluster > MPIDR_AFFLVL1) {
226 ERROR("%s: unsupported CPU (0x%lx)\n", __func__ , mpidr);
227 return PSCI_E_NOT_PRESENT;
228 }
229
230 /* construct the target CPU # */
231 target_cpu |= (target_cluster << 2);
232
233 mce_command_handler(MCE_CMD_ONLINE_CORE, target_cpu, 0, 0);
234
235 return PSCI_E_SUCCESS;
236}
237
238int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
239{
240 int stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
241
242 /*
243 * Reset power state info for CPUs when onlining, we set
244 * deepest power when offlining a core but that may not be
245 * requested by non-secure sw which controls idle states. It
246 * will re-init this info from non-secure software when the
247 * core come online.
248 */
249
250 /*
251 * Check if we are exiting from deep sleep and restore SE
252 * context if we are.
253 */
254 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
255
256 mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT,
257 se_regs[0]);
258 mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT,
259 se_regs[1]);
260 mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT,
261 se_regs[2]);
262
263 /* Init SMMU */
264
265 /*
266 * Reset power state info for the last core doing SC7
267 * entry and exit, we set deepest power state as CC7
268 * and SC7 for SC7 entry which may not be requested by
269 * non-secure SW which controls idle states.
270 */
271 }
272
273 return PSCI_E_SUCCESS;
274}
275
276int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
277{
278 int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
279
280 /* Disable Denver's DCO operations */
281 if (impl == DENVER_IMPL)
282 denver_disable_dco();
283
284 /* Turn off CPU */
285
286 return PSCI_E_SUCCESS;
287}
288
289__dead2 void tegra_soc_prepare_system_off(void)
290{
291 /* System power off */
292
293 /* SC8 */
294
295 wfi();
296
297 /* wait for the system to power down */
298 for (;;) {
299 ;
300 }
301}
302
303int tegra_soc_prepare_system_reset(void)
304{
305 return PSCI_E_SUCCESS;
306}