xref: /rk3399_ARM-atf/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c (revision 723c4c2d511cb6ffa534bc879d1edc2e3a691a63)
1 /*
2  * Copyright (c) 2021, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stdint.h>
9 
10 #include <arch_helpers.h>
11 #include <lib/psci/psci.h>
12 #include <lib/spinlock.h>
13 
14 #include <mt_cpu_pm_cpc.h>
15 #include <mt_lp_irqremain.h>
16 #include <mt_lp_rm.h>
17 #include <mt_mcdi.h>
18 #include <plat_mtk_lpm.h>
19 #include <plat_pm.h>
20 
21 static int plat_mt_lp_cpu_rc;
22 
pwr_state_prompt(unsigned int cpu,const psci_power_state_t * state)23 static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
24 {
25 	return 0;
26 }
27 
pwr_state_reflect(unsigned int cpu,const psci_power_state_t * state)28 static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
29 {
30 	mtk_cpc_core_on_hint_clr(cpu);
31 
32 	if (IS_SYSTEM_SUSPEND_STATE(state)) {
33 		mtk_cpc_time_sync();
34 	}
35 
36 	return 0;
37 }
38 
pwr_cpu_pwron(unsigned int cpu,const psci_power_state_t * state)39 static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
40 {
41 	return 0;
42 }
43 
pwr_cpu_pwrdwn(unsigned int cpu,const psci_power_state_t * state)44 static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
45 {
46 	/* clear DBGPRCR.CORENPDRQ to allow CPU power down  */
47 	write_dbgprcr_el1(0ULL);
48 
49 	return 0;
50 }
51 
pwr_cluster_pwron(unsigned int cpu,const psci_power_state_t * state)52 static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
53 {
54 	return 0;
55 }
56 
pwr_cluster_pwrdwn(unsigned int cpu,const psci_power_state_t * state)57 static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
58 {
59 	return 0;
60 }
61 
pwr_mcusys_pwron(unsigned int cpu,const psci_power_state_t * state)62 static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
63 {
64 	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
65 		return -1;
66 	}
67 
68 	mtk_cpc_mcusys_off_reflect();
69 
70 	return 0;
71 }
72 
pwr_mcusys_pwron_finished(unsigned int cpu,const psci_power_state_t * state)73 static int pwr_mcusys_pwron_finished(unsigned int cpu,
74 					const psci_power_state_t *state)
75 {
76 	int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
77 
78 	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
79 		return -1;
80 	}
81 
82 	mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
83 	mt_lp_irqremain_release();
84 
85 	return 0;
86 }
87 
pwr_mcusys_pwrdwn(unsigned int cpu,const psci_power_state_t * state)88 static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
89 {
90 	int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
91 
92 	if (!IS_MCUSYS_OFF_STATE(state)) {
93 		goto mt_pwr_mcusysoff_break;
94 	}
95 
96 	if (mcdi_try_init() != 0) {
97 		goto mt_pwr_mcusysoff_break;
98 	}
99 
100 	if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
101 		goto mt_pwr_mcusysoff_break;
102 	}
103 
104 	plat_mt_lp_cpu_rc =
105 		mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
106 
107 	if (plat_mt_lp_cpu_rc < 0) {
108 		goto mt_pwr_mcusysoff_reflect;
109 	}
110 
111 	mt_lp_irqremain_aquire();
112 
113 	return 0;
114 
115 mt_pwr_mcusysoff_reflect:
116 	mtk_cpc_mcusys_off_reflect();
117 
118 mt_pwr_mcusysoff_break:
119 
120 	plat_mt_lp_cpu_rc = -1;
121 
122 	return -1;
123 }
124 
125 static const struct mt_lpm_tz plat_pm = {
126 	.pwr_prompt			= pwr_state_prompt,
127 	.pwr_reflect			= pwr_state_reflect,
128 	.pwr_cpu_on			= pwr_cpu_pwron,
129 	.pwr_cpu_dwn			= pwr_cpu_pwrdwn,
130 	.pwr_cluster_on			= pwr_cluster_pwron,
131 	.pwr_cluster_dwn		= pwr_cluster_pwrdwn,
132 	.pwr_mcusys_dwn			= pwr_mcusys_pwrdwn,
133 	.pwr_mcusys_on			= pwr_mcusys_pwron,
134 	.pwr_mcusys_on_finished		= pwr_mcusys_pwron_finished
135 };
136 
mt_plat_cpu_pm_init(void)137 const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
138 {
139 	mtk_cpc_init();
140 
141 	if (mcdi_try_init() == 0) {
142 		INFO("MCDI init done.\n");
143 	}
144 
145 	mt_lp_irqremain_init();
146 
147 	return &plat_pm;
148 }
149