2 * Copyright (c) 2019, MediaTek Inc. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
8 #include <arch_helpers.h>
10 #include <common/debug.h>
12 #include <lib/psci/psci.h>
15 /* mediatek platform specific headers */
16 #include <platform_def.h>
18 #include <mt_gic_v3.h>
19 #include <mtk_plat_common.h>
21 #include <power_tracer.h>
23 #include <plat_debug.h>
24 #include <plat_private.h>
26 #define MTK_LOCAL_STATE_OFF 2
28 static uintptr_t secure_entrypoint
;
30 static void mp1_L2_desel_config(void)
32 mmio_write_64(MCUCFG_BASE
+ 0x2200, 0x2092c820);
37 static int plat_mtk_power_domain_on(unsigned long mpidr
)
39 int cpu
= MPIDR_AFFLVL0_VAL(mpidr
);
40 int cluster
= MPIDR_AFFLVL1_VAL(mpidr
);
42 INFO("%s():%d: mpidr: %lx, c.c: %d.%d\n",
43 __func__
, __LINE__
, mpidr
, cluster
, cpu
);
45 /* power on cluster */
46 if (!spm_get_cluster_powerstate(cluster
)) {
47 spm_poweron_cluster(cluster
);
49 l2c_parity_check_setup();
50 circular_buffer_setup();
51 mp1_L2_desel_config();
52 mt_gic_sync_dcm_disable();
56 /* init cpu reset arch as AARCH64 */
57 mcucfg_init_archstate(cluster
, cpu
, 1);
58 mcucfg_set_bootaddr(cluster
, cpu
, secure_entrypoint
);
60 spm_poweron_cpu(cluster
, cpu
);
62 return PSCI_E_SUCCESS
;
65 static void plat_mtk_power_domain_off(const psci_power_state_t
*state
)
67 uint64_t mpidr
= read_mpidr();
68 int cpu
= MPIDR_AFFLVL0_VAL(mpidr
);
69 int cluster
= MPIDR_AFFLVL1_VAL(mpidr
);
71 INFO("%s():%d: c.c: %d.%d\n", __func__
, __LINE__
, cluster
, cpu
);
73 /* Prevent interrupts from spuriously waking up this cpu */
74 mt_gic_cpuif_disable();
76 spm_enable_cpu_auto_off(cluster
, cpu
);
78 if (state
->pwr_domain_state
[MPIDR_AFFLVL1
] == MTK_LOCAL_STATE_OFF
) {
80 mt_gic_sync_dcm_enable();
82 plat_mtk_cci_disable();
83 spm_enable_cluster_auto_off(cluster
);
86 spm_set_cpu_power_off(cluster
, cpu
);
89 static void plat_mtk_power_domain_on_finish(const psci_power_state_t
*state
)
91 uint64_t mpidr
= read_mpidr();
92 int cpu
= MPIDR_AFFLVL0_VAL(mpidr
);
93 int cluster
= MPIDR_AFFLVL1_VAL(mpidr
);
95 INFO("%s():%d: c.c: %d.%d\n", __func__
, __LINE__
, cluster
, cpu
);
97 assert(state
->pwr_domain_state
[MPIDR_AFFLVL0
] == MTK_LOCAL_STATE_OFF
);
99 if (state
->pwr_domain_state
[MPIDR_AFFLVL1
] == MTK_LOCAL_STATE_OFF
) {
102 /* Enable coherency if this cluster was off */
103 plat_mtk_cci_enable();
104 /* Enable big core dcm if this cluster was on */
105 plat_dcm_restore_cluster_on(mpidr
);
106 /* Enable rgu dcm if this cluster was off */
107 plat_dcm_rgu_enable();
110 spm_disable_cpu_auto_off(cluster
, cpu
);
112 /* Enable the gic cpu interface */
114 mt_gic_cpuif_enable();
117 /*******************************************************************************
118 * MTK_platform handler called when an affinity instance is about to be turned
119 * on. The level and mpidr determine the affinity instance.
120 ******************************************************************************/
121 static const plat_psci_ops_t plat_plat_pm_ops
= {
123 .pwr_domain_on
= plat_mtk_power_domain_on
,
124 .pwr_domain_on_finish
= plat_mtk_power_domain_on_finish
,
125 .pwr_domain_off
= plat_mtk_power_domain_off
,
126 .pwr_domain_suspend
= NULL
,
127 .pwr_domain_suspend_finish
= NULL
,
129 .system_reset
= NULL
,
130 .validate_power_state
= NULL
,
131 .get_sys_suspend_power_state
= NULL
,
134 int plat_setup_psci_ops(uintptr_t sec_entrypoint
,
135 const plat_psci_ops_t
**psci_ops
)
137 *psci_ops
= &plat_plat_pm_ops
;
138 secure_entrypoint
= sec_entrypoint
;