blob: 555b3895ca81d13d6bad84ad3494c82cea1c5f39 [file] [log] [blame]
developer1033ea12019-04-10 21:09:26 +08001/*
developera21d47e2019-05-02 19:29:25 +08002 * Copyright (c) 2019, MediaTek Inc. All rights reserved.
developer1033ea12019-04-10 21:09:26 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/* common headers */
8#include <arch_helpers.h>
9#include <assert.h>
10#include <common/debug.h>
11#include <lib/mmio.h>
12#include <lib/psci/psci.h>
13#include <errno.h>
14
15/* mediatek platform specific headers */
16#include <platform_def.h>
17#include <scu.h>
developera21d47e2019-05-02 19:29:25 +080018#include <mt_gic_v3.h>
developer555ed552019-08-21 22:49:49 +080019#include <mtk_mcdi.h>
developer1033ea12019-04-10 21:09:26 +080020#include <mtk_plat_common.h>
developer043c9332019-05-03 17:02:46 +080021#include <mtgpio.h>
developera21d47e2019-05-02 19:29:25 +080022#include <mtspmc.h>
developera21d47e2019-05-02 19:29:25 +080023#include <plat_dcm.h>
24#include <plat_debug.h>
developer043c9332019-05-03 17:02:46 +080025#include <plat_params.h>
developer1033ea12019-04-10 21:09:26 +080026#include <plat_private.h>
developer043c9332019-05-03 17:02:46 +080027#include <power_tracer.h>
developer6f37fd22019-05-02 20:02:05 +080028#include <pmic.h>
developer083fa242019-08-21 20:50:20 +080029#include <spm.h>
30#include <spm_suspend.h>
developer555ed552019-08-21 22:49:49 +080031#include <sspm.h>
developer6f37fd22019-05-02 20:02:05 +080032#include <rtc.h>
developer1033ea12019-04-10 21:09:26 +080033
developer555ed552019-08-21 22:49:49 +080034/* Local power state for power domains in Run state. */
35#define MTK_LOCAL_STATE_RUN 0
36/* Local power state for retention. */
37#define MTK_LOCAL_STATE_RET 1
38/* Local power state for OFF/power-down. */
39#define MTK_LOCAL_STATE_OFF 2
40
41#if PSCI_EXTENDED_STATE_ID
42/*
43 * Macros used to parse state information from State-ID if it is using the
44 * recommended encoding for State-ID.
45 */
46#define MTK_LOCAL_PSTATE_WIDTH 4
47#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1)
48
49/* Macros to construct the composite power state */
50
51/* Make composite power state parameter till power level 0 */
52
53#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
54 (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
55
56#else /* !PSCI_EXTENDED_STATE_ID */
57
58#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
59 (((lvl0_state) << PSTATE_ID_SHIFT) | \
60 ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
61 ((type) << PSTATE_TYPE_SHIFT))
62
63#endif /* PSCI_EXTENDED_STATE_ID */
64
65/* Make composite power state parameter till power level 1 */
66#define mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
67 (((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \
68 mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
69
70/* Make composite power state parameter till power level 2 */
71#define mtk_make_pwrstate_lvl2( \
72 lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
73 (((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \
74 mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
75
76#define MTK_PWR_LVL0 0
77#define MTK_PWR_LVL1 1
78#define MTK_PWR_LVL2 2
79
80/* Macros to read the MTK power domain state */
81#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0]
82#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1]
83#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ? \
84 (state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
85
86#if PSCI_EXTENDED_STATE_ID
87/*
88 * The table storing the valid idle power states. Ensure that the
89 * array entries are populated in ascending order of state-id to
90 * enable us to use binary search during power state validation.
91 * The table must be terminated by a NULL entry.
92 */
93const unsigned int mtk_pm_idle_states[] = {
94 /* State-id - 0x001 */
95 mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
96 MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY),
97 /* State-id - 0x002 */
98 mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
99 MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
100 /* State-id - 0x022 */
101 mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF,
102 MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
103#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
104 /* State-id - 0x222 */
105 mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF,
106 MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
107#endif
108 0,
109};
110#endif
111
112#define CPU_IDX(cluster, cpu) ((cluster << 2) + cpu)
113#define ON true
114#define OFF false
115
116/* Pause MCDI when CPU hotplug */
117static bool HP_SSPM_PAUSE;
118/* CPU Hotplug by SSPM */
119static bool HP_SSPM_CTRL = true;
120/* Turn off cluster when CPU hotplug off */
121static bool HP_CLUSTER_OFF = true;
122/* Turn off cluster when CPU MCDI off */
123static bool MCDI_C2 = true;
124/* Enable MCDI */
125static bool MCDI_SSPM = true;
developera21d47e2019-05-02 19:29:25 +0800126
127static uintptr_t secure_entrypoint;
128
129static void mp1_L2_desel_config(void)
130{
131 mmio_write_64(MCUCFG_BASE + 0x2200, 0x2092c820);
132
developer555ed552019-08-21 22:49:49 +0800133 dsb();
134}
135
136static bool clst_single_pwr(int cluster, int cpu)
137{
138 uint32_t cpu_mask[2] = {0x00001e00, 0x000f0000};
139 uint32_t cpu_pwr_bit[] = {9, 10, 11, 12, 16, 17, 18, 19};
140 int my_idx = (cluster << 2) + cpu;
141 uint32_t pwr_stat = mmio_read_32(0x10006180);
142
143 return !(pwr_stat & (cpu_mask[cluster] & ~BIT(cpu_pwr_bit[my_idx])));
144}
145
146static bool clst_single_on(int cluster, int cpu)
147{
148 uint32_t cpu_mask[2] = {0x0f, 0xf0};
149 int my_idx = (cluster << 2) + cpu;
150 uint32_t on_stat = mcdi_avail_cpu_mask_read();
151
152 return !(on_stat & (cpu_mask[cluster] & ~BIT(my_idx)));
153}
154
155static void plat_cluster_pwrdwn_common(uint64_t mpidr, int cluster)
156{
157 if (cluster > 0)
158 mt_gic_sync_dcm_enable();
159
160 /* Disable coherency */
161 plat_mtk_cci_disable();
162 disable_scu(mpidr);
163}
164
165static void plat_cluster_pwron_common(uint64_t mpidr, int cluster)
166{
167 if (cluster > 0) {
168 l2c_parity_check_setup();
169 circular_buffer_setup();
170 mp1_L2_desel_config();
171 mt_gic_sync_dcm_disable();
172 }
173
174 /* Enable coherency */
175 enable_scu(mpidr);
176 plat_mtk_cci_enable();
177 /* Enable big core dcm */
178 plat_dcm_restore_cluster_on(mpidr);
179 /* Enable rgu dcm */
180 plat_dcm_rgu_enable();
181}
182
183static void plat_cpu_standby(plat_local_state_t cpu_state)
184{
185 unsigned int scr;
186
187 scr = read_scr_el3();
188 write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
189
190 isb();
developera21d47e2019-05-02 19:29:25 +0800191 dsb();
developer555ed552019-08-21 22:49:49 +0800192 wfi();
193
194 write_scr_el3(scr);
195}
196
197static void mcdi_ctrl_before_hotplug_on(int cluster, int cpu)
198{
199 if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM) {
200 mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), OFF);
201 mcdi_pause_set(cluster, CPU_IDX(cluster, cpu), ON);
202 }
developera21d47e2019-05-02 19:29:25 +0800203}
204
developer555ed552019-08-21 22:49:49 +0800205static void mcdi_ctrl_before_hotplug_off(int cluster, int cpu, bool cluster_off)
206{
207 if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM)
208 mcdi_pause_set(cluster_off ? cluster : -1,
209 CPU_IDX(cluster, cpu), OFF);
210}
211
212static void mcdi_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
213{
214 if (MCDI_SSPM) {
215 sspm_set_bootaddr(secure_entrypoint);
216
217 sspm_standbywfi_irq_enable(CPU_IDX(cluster, cpu));
218
219 if (cluster_off)
220 sspm_cluster_pwr_off_notify(cluster);
221 else
222 sspm_cluster_pwr_on_notify(cluster);
223 }
224}
225
226static void mcdi_ctrl_suspend(void)
227{
228 if (MCDI_SSPM)
229 mcdi_pause();
230}
231
232static void mcdi_ctrl_resume(void)
233{
234 if (MCDI_SSPM)
235 mcdi_unpause();
236}
237
238static void hotplug_ctrl_cluster_on(int cluster, int cpu)
239{
240 if (HP_SSPM_CTRL && MCDI_SSPM) {
241 mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), OFF);
242 mcdi_hotplug_set(cluster, -1, ON);
243 mcdi_hotplug_wait_ack(cluster, -1, ON);
244 } else {
245 /* power on cluster */
246 if (!spm_get_cluster_powerstate(cluster))
247 spm_poweron_cluster(cluster);
248 }
249}
250
251static void hotplug_ctrl_cpu_on(int cluster, int cpu)
252{
253 if (HP_SSPM_CTRL && MCDI_SSPM)
254 mcdi_hotplug_set(cluster, CPU_IDX(cluster, cpu), ON);
255 else
256 spm_poweron_cpu(cluster, cpu);
257}
258
259static void hotplug_ctrl_cpu_on_finish(int cluster, int cpu)
260{
261 spm_disable_cpu_auto_off(cluster, cpu);
262
263 if (HP_SSPM_CTRL && MCDI_SSPM)
264 mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), ON);
265 else if (HP_SSPM_PAUSE && MCDI_SSPM)
266 mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), ON);
267
268 mcdi_avail_cpu_mask_set(BIT(CPU_IDX(cluster, cpu)));
269}
270
271static void hotplug_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
272{
273 mcdi_avail_cpu_mask_clr(BIT(CPU_IDX(cluster, cpu)));
274
275 if (HP_SSPM_CTRL && MCDI_SSPM) {
276 mcdi_hotplug_set(cluster_off ? cluster : -1,
277 CPU_IDX(cluster, cpu), OFF);
278 } else {
279 spm_enable_cpu_auto_off(cluster, cpu);
280
281 if (cluster_off)
282 spm_enable_cluster_auto_off(cluster);
283
284 spm_set_cpu_power_off(cluster, cpu);
285 }
286}
287
developera21d47e2019-05-02 19:29:25 +0800288static int plat_mtk_power_domain_on(unsigned long mpidr)
289{
290 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
291 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
292
developer555ed552019-08-21 22:49:49 +0800293 mcdi_ctrl_before_hotplug_on(cluster, cpu);
294 hotplug_ctrl_cluster_on(cluster, cpu);
developera21d47e2019-05-02 19:29:25 +0800295
296 /* init cpu reset arch as AARCH64 */
297 mcucfg_init_archstate(cluster, cpu, 1);
298 mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
299
developer555ed552019-08-21 22:49:49 +0800300 hotplug_ctrl_cpu_on(cluster, cpu);
developera21d47e2019-05-02 19:29:25 +0800301
302 return PSCI_E_SUCCESS;
303}
304
305static void plat_mtk_power_domain_off(const psci_power_state_t *state)
306{
307 uint64_t mpidr = read_mpidr();
308 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
309 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
developer555ed552019-08-21 22:49:49 +0800310 const plat_local_state_t *pds = state->pwr_domain_state;
311 bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
312 bool cluster_off = (HP_CLUSTER_OFF && afflvl1 &&
313 clst_single_on(cluster, cpu));
developera21d47e2019-05-02 19:29:25 +0800314
developera21d47e2019-05-02 19:29:25 +0800315 mt_gic_cpuif_disable();
316
developer555ed552019-08-21 22:49:49 +0800317 if (cluster_off)
318 plat_cluster_pwrdwn_common(mpidr, cluster);
developera21d47e2019-05-02 19:29:25 +0800319
developer555ed552019-08-21 22:49:49 +0800320 mcdi_ctrl_before_hotplug_off(cluster, cpu, cluster_off);
321 hotplug_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
322}
developera21d47e2019-05-02 19:29:25 +0800323
developer555ed552019-08-21 22:49:49 +0800324static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
325{
326 uint64_t mpidr = read_mpidr();
327 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
328 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
329 const plat_local_state_t *pds = state->pwr_domain_state;
330 bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
331
332 if (afflvl1)
333 plat_cluster_pwron_common(mpidr, cluster);
334
335 mt_gic_pcpu_init();
336 mt_gic_cpuif_enable();
developera21d47e2019-05-02 19:29:25 +0800337
developer555ed552019-08-21 22:49:49 +0800338 hotplug_ctrl_cpu_on_finish(cluster, cpu);
developera21d47e2019-05-02 19:29:25 +0800339}
340
developer555ed552019-08-21 22:49:49 +0800341static void plat_mtk_power_domain_suspend(const psci_power_state_t *state)
developera21d47e2019-05-02 19:29:25 +0800342{
343 uint64_t mpidr = read_mpidr();
344 int cpu = MPIDR_AFFLVL0_VAL(mpidr);
345 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
developer555ed552019-08-21 22:49:49 +0800346 const plat_local_state_t *pds = state->pwr_domain_state;
347 bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
348 bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
349 bool cluster_off = MCDI_C2 && afflvl1 && clst_single_pwr(cluster, cpu);
350
351 /* init cpu reset arch as AARCH64 */
352 mcucfg_init_archstate(cluster, cpu, 1);
353 mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
developera21d47e2019-05-02 19:29:25 +0800354
developer555ed552019-08-21 22:49:49 +0800355 mt_gic_cpuif_disable();
356 mt_gic_irq_save();
357 plat_dcm_mcsi_a_backup();
358
359 if (cluster_off || afflvl2)
360 plat_cluster_pwrdwn_common(mpidr, cluster);
361
362 if (afflvl2) {
363 spm_data_t spm_d = { .cmd = SPM_SUSPEND };
364 uint32_t *d = (uint32_t *)&spm_d;
365 uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
366
367 mcdi_ctrl_suspend();
368
369 spm_set_bootaddr(secure_entrypoint);
developera21d47e2019-05-02 19:29:25 +0800370
developer555ed552019-08-21 22:49:49 +0800371 if (MCDI_SSPM)
372 sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
developera21d47e2019-05-02 19:29:25 +0800373
developer555ed552019-08-21 22:49:49 +0800374 spm_system_suspend();
developera21d47e2019-05-02 19:29:25 +0800375
developer555ed552019-08-21 22:49:49 +0800376 if (MCDI_SSPM)
377 while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
378 ;
379 } else {
380 mcdi_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
developera21d47e2019-05-02 19:29:25 +0800381 }
developer555ed552019-08-21 22:49:49 +0800382}
developera21d47e2019-05-02 19:29:25 +0800383
developer555ed552019-08-21 22:49:49 +0800384static void plat_mtk_power_domain_suspend_finish(const psci_power_state_t *state)
385{
386 uint64_t mpidr = read_mpidr();
387 int cluster = MPIDR_AFFLVL1_VAL(mpidr);
388 const plat_local_state_t *pds = state->pwr_domain_state;
389 bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
developera21d47e2019-05-02 19:29:25 +0800390
developer555ed552019-08-21 22:49:49 +0800391 if (afflvl2) {
392 spm_data_t spm_d = { .cmd = SPM_RESUME };
393 uint32_t *d = (uint32_t *)&spm_d;
394 uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
395
396 mt_gic_init();
397 mt_gic_irq_restore();
398 mmio_write_32(EMI_WFIFO, 0xf);
399
400 if (MCDI_SSPM)
401 sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
402
403 spm_system_suspend_finish();
404
405 if (MCDI_SSPM)
406 while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
407 ;
408
409 mcdi_ctrl_resume();
410 }
411
412 plat_cluster_pwron_common(mpidr, cluster);
413
414 plat_dcm_mcsi_a_restore();
415}
416
417#if PSCI_EXTENDED_STATE_ID
418
419static int plat_mtk_validate_power_state(unsigned int power_state,
420 psci_power_state_t *req_state)
421{
422 unsigned int state_id;
423 int i;
424
425 assert(req_state);
426
427 if (!MCDI_SSPM)
428 return PSCI_E_INVALID_PARAMS;
429
430 /*
431 * Currently we are using a linear search for finding the matching
432 * entry in the idle power state array. This can be made a binary
433 * search if the number of entries justify the additional complexity.
434 */
435 for (i = 0; !!mtk_pm_idle_states[i]; i++) {
436 if (power_state == mtk_pm_idle_states[i])
437 break;
438 }
439
440 /* Return error if entry not found in the idle state array */
441 if (!mtk_pm_idle_states[i])
442 return PSCI_E_INVALID_PARAMS;
443
444 i = 0;
445 state_id = psci_get_pstate_id(power_state);
446
447 /* Parse the State ID and populate the state info parameter */
448 while (state_id) {
449 req_state->pwr_domain_state[i++] = state_id &
450 MTK_LOCAL_PSTATE_MASK;
451 state_id >>= MTK_LOCAL_PSTATE_WIDTH;
452 }
453
454 return PSCI_E_SUCCESS;
455}
456
457#else /* if !PSCI_EXTENDED_STATE_ID */
458
459static int plat_mtk_validate_power_state(unsigned int power_state,
460 psci_power_state_t *req_state)
461{
462 int pstate = psci_get_pstate_type(power_state);
463 int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
464 int i;
465
466 assert(req_state);
467
468 if (pwr_lvl > PLAT_MAX_PWR_LVL)
469 return PSCI_E_INVALID_PARAMS;
470
471 /* Sanity check the requested state */
472 if (pstate == PSTATE_TYPE_STANDBY) {
473 /*
474 * It's possible to enter standby only on power level 0
475 * Ignore any other power level.
476 */
477 if (pwr_lvl != 0)
478 return PSCI_E_INVALID_PARAMS;
479
480 req_state->pwr_domain_state[MTK_PWR_LVL0] = MTK_LOCAL_STATE_RET;
481 } else if (!MCDI_SSPM) {
482 return PSCI_E_INVALID_PARAMS;
483 } else {
484 for (i = 0; i <= pwr_lvl; i++)
485 req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
486 }
487
488 return PSCI_E_SUCCESS;
developera21d47e2019-05-02 19:29:25 +0800489}
490
developer555ed552019-08-21 22:49:49 +0800491#endif /* PSCI_EXTENDED_STATE_ID */
492
developer1033ea12019-04-10 21:09:26 +0800493/*******************************************************************************
developer6f37fd22019-05-02 20:02:05 +0800494 * MTK handlers to shutdown/reboot the system
495 ******************************************************************************/
496static void __dead2 plat_mtk_system_off(void)
497{
498 INFO("MTK System Off\n");
499
500 rtc_power_off_sequence();
501 wk_pmic_enable_sdn_delay();
502 pmic_power_off();
503
504 wfi();
505 ERROR("MTK System Off: operation not handled.\n");
506 panic();
507}
508
developer043c9332019-05-03 17:02:46 +0800509static void __dead2 plat_mtk_system_reset(void)
510{
511 struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
512
513 INFO("MTK System Reset\n");
514
515 mt_set_gpio_out(gpio_reset->index, gpio_reset->polarity);
516
517 wfi();
518 ERROR("MTK System Reset: operation not handled.\n");
519 panic();
520}
521
developer083fa242019-08-21 20:50:20 +0800522static void plat_mtk_get_sys_suspend_power_state(psci_power_state_t *req_state)
523{
524 assert(PLAT_MAX_PWR_LVL >= 2);
525
526 for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
527 req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
528}
529
developer6f37fd22019-05-02 20:02:05 +0800530/*******************************************************************************
developer1033ea12019-04-10 21:09:26 +0800531 * MTK_platform handler called when an affinity instance is about to be turned
532 * on. The level and mpidr determine the affinity instance.
533 ******************************************************************************/
developer1033ea12019-04-10 21:09:26 +0800534static const plat_psci_ops_t plat_plat_pm_ops = {
developer555ed552019-08-21 22:49:49 +0800535 .cpu_standby = plat_cpu_standby,
developera21d47e2019-05-02 19:29:25 +0800536 .pwr_domain_on = plat_mtk_power_domain_on,
537 .pwr_domain_on_finish = plat_mtk_power_domain_on_finish,
538 .pwr_domain_off = plat_mtk_power_domain_off,
developer083fa242019-08-21 20:50:20 +0800539 .pwr_domain_suspend = plat_mtk_power_domain_suspend,
540 .pwr_domain_suspend_finish = plat_mtk_power_domain_suspend_finish,
developer6f37fd22019-05-02 20:02:05 +0800541 .system_off = plat_mtk_system_off,
developer043c9332019-05-03 17:02:46 +0800542 .system_reset = plat_mtk_system_reset,
developer555ed552019-08-21 22:49:49 +0800543 .validate_power_state = plat_mtk_validate_power_state,
developer083fa242019-08-21 20:50:20 +0800544 .get_sys_suspend_power_state = plat_mtk_get_sys_suspend_power_state,
developer1033ea12019-04-10 21:09:26 +0800545};
546
547int plat_setup_psci_ops(uintptr_t sec_entrypoint,
548 const plat_psci_ops_t **psci_ops)
549{
550 *psci_ops = &plat_plat_pm_ops;
551 secure_entrypoint = sec_entrypoint;
developer555ed552019-08-21 22:49:49 +0800552
553 if (!check_mcdi_ctl_stat()) {
554 HP_SSPM_CTRL = false;
555 MCDI_SSPM = false;
556 }
557
developer1033ea12019-04-10 21:09:26 +0800558 return 0;
559}