xref: /rk3399_ARM-atf/plat/mediatek/mt8183/plat_pm.c (revision 301d27d998892c054dec925264f81b11dcd64822)
1 /*
2  * Copyright (c) 2019, MediaTek Inc. All rights reserved.
3  *
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>
18 #include <mt_gic_v3.h>
19 #include <mtk_plat_common.h>
20 #include <mtgpio.h>
21 #include <mtspmc.h>
22 #include <plat_dcm.h>
23 #include <plat_debug.h>
24 #include <plat_params.h>
25 #include <plat_private.h>
26 #include <power_tracer.h>
27 #include <pmic.h>
28 #include <rtc.h>
29 
30 #define MTK_LOCAL_STATE_OFF     2
31 
32 static uintptr_t secure_entrypoint;
33 
34 static void mp1_L2_desel_config(void)
35 {
36 	mmio_write_64(MCUCFG_BASE + 0x2200, 0x2092c820);
37 
38 	dsb();
39 }
40 
41 static int plat_mtk_power_domain_on(unsigned long mpidr)
42 {
43 	int cpu = MPIDR_AFFLVL0_VAL(mpidr);
44 	int cluster = MPIDR_AFFLVL1_VAL(mpidr);
45 
46 	INFO("%s():%d: mpidr: %lx, c.c: %d.%d\n",
47 		__func__, __LINE__, mpidr, cluster, cpu);
48 
49 	/* power on cluster */
50 	if (!spm_get_cluster_powerstate(cluster)) {
51 		spm_poweron_cluster(cluster);
52 		if (cluster == 1) {
53 			l2c_parity_check_setup();
54 			circular_buffer_setup();
55 			mp1_L2_desel_config();
56 			mt_gic_sync_dcm_disable();
57 		}
58 	}
59 
60 	/* init cpu reset arch as AARCH64 */
61 	mcucfg_init_archstate(cluster, cpu, 1);
62 	mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
63 
64 	spm_poweron_cpu(cluster, cpu);
65 
66 	return PSCI_E_SUCCESS;
67 }
68 
69 static void plat_mtk_power_domain_off(const psci_power_state_t *state)
70 {
71 	uint64_t mpidr = read_mpidr();
72 	int cpu = MPIDR_AFFLVL0_VAL(mpidr);
73 	int cluster = MPIDR_AFFLVL1_VAL(mpidr);
74 
75 	INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
76 
77 	/* Prevent interrupts from spuriously waking up this cpu */
78 	mt_gic_cpuif_disable();
79 
80 	spm_enable_cpu_auto_off(cluster, cpu);
81 
82 	if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
83 		if (cluster == 1)
84 			mt_gic_sync_dcm_enable();
85 
86 		plat_mtk_cci_disable();
87 		spm_enable_cluster_auto_off(cluster);
88 	}
89 
90 	spm_set_cpu_power_off(cluster, cpu);
91 }
92 
93 static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
94 {
95 	uint64_t mpidr = read_mpidr();
96 	int cpu = MPIDR_AFFLVL0_VAL(mpidr);
97 	int cluster = MPIDR_AFFLVL1_VAL(mpidr);
98 
99 	INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
100 
101 	assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF);
102 
103 	if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
104 		enable_scu(mpidr);
105 
106 		/* Enable coherency if this cluster was off */
107 		plat_mtk_cci_enable();
108 		/* Enable big core dcm if this cluster was on */
109 		plat_dcm_restore_cluster_on(mpidr);
110 		/* Enable rgu dcm if this cluster was off */
111 		plat_dcm_rgu_enable();
112 	}
113 
114 	spm_disable_cpu_auto_off(cluster, cpu);
115 
116 	/* Enable the gic cpu interface */
117 	mt_gic_pcpu_init();
118 	mt_gic_cpuif_enable();
119 }
120 
121 /*******************************************************************************
122  * MTK handlers to shutdown/reboot the system
123  ******************************************************************************/
124 static void __dead2 plat_mtk_system_off(void)
125 {
126 	INFO("MTK System Off\n");
127 
128 	rtc_power_off_sequence();
129 	wk_pmic_enable_sdn_delay();
130 	pmic_power_off();
131 
132 	wfi();
133 	ERROR("MTK System Off: operation not handled.\n");
134 	panic();
135 }
136 
137 static void __dead2 plat_mtk_system_reset(void)
138 {
139 	struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
140 
141 	INFO("MTK System Reset\n");
142 
143 	mt_set_gpio_out(gpio_reset->index, gpio_reset->polarity);
144 
145 	wfi();
146 	ERROR("MTK System Reset: operation not handled.\n");
147 	panic();
148 }
149 
150 /*******************************************************************************
151  * MTK_platform handler called when an affinity instance is about to be turned
152  * on. The level and mpidr determine the affinity instance.
153  ******************************************************************************/
154 static const plat_psci_ops_t plat_plat_pm_ops = {
155 	.cpu_standby			= NULL,
156 	.pwr_domain_on			= plat_mtk_power_domain_on,
157 	.pwr_domain_on_finish		= plat_mtk_power_domain_on_finish,
158 	.pwr_domain_off			= plat_mtk_power_domain_off,
159 	.pwr_domain_suspend		= NULL,
160 	.pwr_domain_suspend_finish	= NULL,
161 	.system_off			= plat_mtk_system_off,
162 	.system_reset			= plat_mtk_system_reset,
163 	.validate_power_state		= NULL,
164 	.get_sys_suspend_power_state	= NULL,
165 };
166 
167 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
168 			const plat_psci_ops_t **psci_ops)
169 {
170 	*psci_ops = &plat_plat_pm_ops;
171 	secure_entrypoint = sec_entrypoint;
172 	return 0;
173 }
174