xref: /rk3399_ARM-atf/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c (revision 723c4c2d511cb6ffa534bc879d1edc2e3a691a63)
106cb65efSGarmin.Chang /*
206cb65efSGarmin.Chang  * Copyright (c) 2021, MediaTek Inc. All rights reserved.
306cb65efSGarmin.Chang  *
406cb65efSGarmin.Chang  * SPDX-License-Identifier: BSD-3-Clause
506cb65efSGarmin.Chang  */
606cb65efSGarmin.Chang 
706cb65efSGarmin.Chang #include <assert.h>
806cb65efSGarmin.Chang #include <stdint.h>
906cb65efSGarmin.Chang 
1006cb65efSGarmin.Chang #include <arch_helpers.h>
1106cb65efSGarmin.Chang #include <lib/psci/psci.h>
1206cb65efSGarmin.Chang #include <lib/spinlock.h>
1306cb65efSGarmin.Chang 
1406cb65efSGarmin.Chang #include <mt_cpu_pm_cpc.h>
15*7ac6a76cSjason-ch chen #include <mt_lp_irqremain.h>
16*7ac6a76cSjason-ch chen #include <mt_lp_rm.h>
1706cb65efSGarmin.Chang #include <mt_mcdi.h>
1806cb65efSGarmin.Chang #include <plat_mtk_lpm.h>
1906cb65efSGarmin.Chang #include <plat_pm.h>
2006cb65efSGarmin.Chang 
2106cb65efSGarmin.Chang static int plat_mt_lp_cpu_rc;
2206cb65efSGarmin.Chang 
pwr_state_prompt(unsigned int cpu,const psci_power_state_t * state)2306cb65efSGarmin.Chang static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
2406cb65efSGarmin.Chang {
2506cb65efSGarmin.Chang 	return 0;
2606cb65efSGarmin.Chang }
2706cb65efSGarmin.Chang 
pwr_state_reflect(unsigned int cpu,const psci_power_state_t * state)2806cb65efSGarmin.Chang static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
2906cb65efSGarmin.Chang {
3006cb65efSGarmin.Chang 	mtk_cpc_core_on_hint_clr(cpu);
3106cb65efSGarmin.Chang 
3206cb65efSGarmin.Chang 	if (IS_SYSTEM_SUSPEND_STATE(state)) {
3306cb65efSGarmin.Chang 		mtk_cpc_time_sync();
3406cb65efSGarmin.Chang 	}
3506cb65efSGarmin.Chang 
3606cb65efSGarmin.Chang 	return 0;
3706cb65efSGarmin.Chang }
3806cb65efSGarmin.Chang 
pwr_cpu_pwron(unsigned int cpu,const psci_power_state_t * state)3906cb65efSGarmin.Chang static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
4006cb65efSGarmin.Chang {
4106cb65efSGarmin.Chang 	return 0;
4206cb65efSGarmin.Chang }
4306cb65efSGarmin.Chang 
pwr_cpu_pwrdwn(unsigned int cpu,const psci_power_state_t * state)4406cb65efSGarmin.Chang static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
4506cb65efSGarmin.Chang {
4606cb65efSGarmin.Chang 	/* clear DBGPRCR.CORENPDRQ to allow CPU power down  */
4706cb65efSGarmin.Chang 	write_dbgprcr_el1(0ULL);
4806cb65efSGarmin.Chang 
4906cb65efSGarmin.Chang 	return 0;
5006cb65efSGarmin.Chang }
5106cb65efSGarmin.Chang 
pwr_cluster_pwron(unsigned int cpu,const psci_power_state_t * state)5206cb65efSGarmin.Chang static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
5306cb65efSGarmin.Chang {
5406cb65efSGarmin.Chang 	return 0;
5506cb65efSGarmin.Chang }
5606cb65efSGarmin.Chang 
pwr_cluster_pwrdwn(unsigned int cpu,const psci_power_state_t * state)5706cb65efSGarmin.Chang static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
5806cb65efSGarmin.Chang {
5906cb65efSGarmin.Chang 	return 0;
6006cb65efSGarmin.Chang }
6106cb65efSGarmin.Chang 
pwr_mcusys_pwron(unsigned int cpu,const psci_power_state_t * state)6206cb65efSGarmin.Chang static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
6306cb65efSGarmin.Chang {
6406cb65efSGarmin.Chang 	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
6506cb65efSGarmin.Chang 		return -1;
6606cb65efSGarmin.Chang 	}
6706cb65efSGarmin.Chang 
6806cb65efSGarmin.Chang 	mtk_cpc_mcusys_off_reflect();
6906cb65efSGarmin.Chang 
7006cb65efSGarmin.Chang 	return 0;
7106cb65efSGarmin.Chang }
7206cb65efSGarmin.Chang 
pwr_mcusys_pwron_finished(unsigned int cpu,const psci_power_state_t * state)7306cb65efSGarmin.Chang static int pwr_mcusys_pwron_finished(unsigned int cpu,
7406cb65efSGarmin.Chang 					const psci_power_state_t *state)
7506cb65efSGarmin.Chang {
76*7ac6a76cSjason-ch chen 	int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
77*7ac6a76cSjason-ch chen 
7806cb65efSGarmin.Chang 	if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
7906cb65efSGarmin.Chang 		return -1;
8006cb65efSGarmin.Chang 	}
8106cb65efSGarmin.Chang 
82*7ac6a76cSjason-ch chen 	mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
83*7ac6a76cSjason-ch chen 	mt_lp_irqremain_release();
84*7ac6a76cSjason-ch chen 
8506cb65efSGarmin.Chang 	return 0;
8606cb65efSGarmin.Chang }
8706cb65efSGarmin.Chang 
pwr_mcusys_pwrdwn(unsigned int cpu,const psci_power_state_t * state)8806cb65efSGarmin.Chang static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
8906cb65efSGarmin.Chang {
90*7ac6a76cSjason-ch chen 	int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
91*7ac6a76cSjason-ch chen 
9206cb65efSGarmin.Chang 	if (!IS_MCUSYS_OFF_STATE(state)) {
9306cb65efSGarmin.Chang 		goto mt_pwr_mcusysoff_break;
9406cb65efSGarmin.Chang 	}
9506cb65efSGarmin.Chang 
9606cb65efSGarmin.Chang 	if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
9706cb65efSGarmin.Chang 		goto mt_pwr_mcusysoff_break;
9806cb65efSGarmin.Chang 	}
9906cb65efSGarmin.Chang 
100*7ac6a76cSjason-ch chen 	if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
101*7ac6a76cSjason-ch chen 		goto mt_pwr_mcusysoff_break;
102*7ac6a76cSjason-ch chen 	}
103*7ac6a76cSjason-ch chen 
104*7ac6a76cSjason-ch chen 	plat_mt_lp_cpu_rc =
105*7ac6a76cSjason-ch chen 		mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
106*7ac6a76cSjason-ch chen 
107*7ac6a76cSjason-ch chen 	if (plat_mt_lp_cpu_rc < 0) {
108*7ac6a76cSjason-ch chen 		goto mt_pwr_mcusysoff_reflect;
109*7ac6a76cSjason-ch chen 	}
110*7ac6a76cSjason-ch chen 
111*7ac6a76cSjason-ch chen 	mt_lp_irqremain_aquire();
112*7ac6a76cSjason-ch chen 
11306cb65efSGarmin.Chang 	return 0;
11406cb65efSGarmin.Chang 
115*7ac6a76cSjason-ch chen mt_pwr_mcusysoff_reflect:
116*7ac6a76cSjason-ch chen 	mtk_cpc_mcusys_off_reflect();
11706cb65efSGarmin.Chang 
118*7ac6a76cSjason-ch chen mt_pwr_mcusysoff_break:
11906cb65efSGarmin.Chang 	plat_mt_lp_cpu_rc = -1;
12006cb65efSGarmin.Chang 
12106cb65efSGarmin.Chang 	return -1;
12206cb65efSGarmin.Chang }
12306cb65efSGarmin.Chang 
12406cb65efSGarmin.Chang static const struct mt_lpm_tz plat_pm = {
12506cb65efSGarmin.Chang 	.pwr_prompt			= pwr_state_prompt,
12606cb65efSGarmin.Chang 	.pwr_reflect			= pwr_state_reflect,
12706cb65efSGarmin.Chang 	.pwr_cpu_on			= pwr_cpu_pwron,
12806cb65efSGarmin.Chang 	.pwr_cpu_dwn			= pwr_cpu_pwrdwn,
12906cb65efSGarmin.Chang 	.pwr_cluster_on			= pwr_cluster_pwron,
13006cb65efSGarmin.Chang 	.pwr_cluster_dwn		= pwr_cluster_pwrdwn,
13106cb65efSGarmin.Chang 	.pwr_mcusys_dwn			= pwr_mcusys_pwrdwn,
13206cb65efSGarmin.Chang 	.pwr_mcusys_on			= pwr_mcusys_pwron,
13306cb65efSGarmin.Chang 	.pwr_mcusys_on_finished		= pwr_mcusys_pwron_finished
13406cb65efSGarmin.Chang };
13506cb65efSGarmin.Chang 
mt_plat_cpu_pm_init(void)13606cb65efSGarmin.Chang const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
13706cb65efSGarmin.Chang {
13806cb65efSGarmin.Chang 	mtk_cpc_init();
13906cb65efSGarmin.Chang 
14006cb65efSGarmin.Chang 	if (mcdi_try_init() == 0) {
14106cb65efSGarmin.Chang 		INFO("MCDI init done.\n");
14206cb65efSGarmin.Chang 	}
14306cb65efSGarmin.Chang 
144*7ac6a76cSjason-ch chen 	mt_lp_irqremain_init();
145*7ac6a76cSjason-ch chen 
14606cb65efSGarmin.Chang 	return &plat_pm;
14706cb65efSGarmin.Chang }
148