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