xref: /rk3399_ARM-atf/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c (revision 258f6a2d40ede90127abfefa9af594a4943789d7)
1ebb44440SRoger Lu /*
2ebb44440SRoger Lu  * Copyright (c) 2020, MediaTek Inc. All rights reserved.
3ebb44440SRoger Lu  *
4ebb44440SRoger Lu  * SPDX-License-Identifier: BSD-3-Clause
5ebb44440SRoger Lu  */
6ebb44440SRoger Lu 
7ebb44440SRoger Lu #include <common/debug.h>
8ebb44440SRoger Lu #include <lib/mmio.h>
9ebb44440SRoger Lu 
10ebb44440SRoger Lu #include <mt_spm.h>
11ebb44440SRoger Lu #include <mt_spm_conservation.h>
12ebb44440SRoger Lu #include <mt_spm_internal.h>
13ebb44440SRoger Lu #include <mt_spm_reg.h>
14*f3febccaSRoger Lu #include <mt_spm_vcorefs.h>
15ebb44440SRoger Lu #include <plat_mtk_lpm.h>
16ebb44440SRoger Lu #include <plat_pm.h>
17ebb44440SRoger Lu #include <plat/common/platform.h>
18ebb44440SRoger Lu #include <platform_def.h>
19ebb44440SRoger Lu 
20ebb44440SRoger Lu struct wake_status spm_wakesta; /* record last wakesta */
21ebb44440SRoger Lu 
go_to_spm_before_wfi(int state_id,unsigned int ext_opand,struct spm_lp_scen * spm_lp,unsigned int resource_req)22ebb44440SRoger Lu static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
23ebb44440SRoger Lu 				struct spm_lp_scen *spm_lp,
24ebb44440SRoger Lu 				unsigned int resource_req)
25ebb44440SRoger Lu {
26ebb44440SRoger Lu 	int ret = 0;
27ebb44440SRoger Lu 	struct pwr_ctrl *pwrctrl;
28ebb44440SRoger Lu 	uint32_t cpu = plat_my_core_pos();
29ebb44440SRoger Lu 
30ebb44440SRoger Lu 	pwrctrl = spm_lp->pwrctrl;
31ebb44440SRoger Lu 
32ebb44440SRoger Lu 	__spm_set_cpu_status(cpu);
33ebb44440SRoger Lu 	__spm_set_power_control(pwrctrl);
34ebb44440SRoger Lu 	__spm_set_wakeup_event(pwrctrl);
35*f3febccaSRoger Lu 	__spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl);
36ebb44440SRoger Lu 	__spm_set_pcm_flags(pwrctrl);
37ebb44440SRoger Lu 	__spm_src_req_update(pwrctrl, resource_req);
38ebb44440SRoger Lu 
39ebb44440SRoger Lu 	if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
40ebb44440SRoger Lu 		__spm_set_pcm_wdt(1);
41ebb44440SRoger Lu 	}
42ebb44440SRoger Lu 
43ebb44440SRoger Lu 	if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
44ebb44440SRoger Lu 		__spm_xo_soc_bblpm(1);
45ebb44440SRoger Lu 	}
46ebb44440SRoger Lu 
47ebb44440SRoger Lu 	if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
48ebb44440SRoger Lu 		spm_hw_s1_state_monitor_resume();
49ebb44440SRoger Lu 	}
50ebb44440SRoger Lu 
51ebb44440SRoger Lu 	/* Disable auto resume by PCM in system suspend stage */
52ebb44440SRoger Lu 	if (IS_PLAT_SUSPEND_ID(state_id)) {
53ebb44440SRoger Lu 		__spm_disable_pcm_timer();
54ebb44440SRoger Lu 		__spm_set_pcm_wdt(0);
55ebb44440SRoger Lu 	}
56ebb44440SRoger Lu 
57ebb44440SRoger Lu 	__spm_send_cpu_wakeup_event();
58ebb44440SRoger Lu 
59ebb44440SRoger Lu 	INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
60ebb44440SRoger Lu 	     cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
61ebb44440SRoger Lu 	     mmio_read_32(PCM_TIMER_VAL) / 32768);
62ebb44440SRoger Lu 	INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
63ebb44440SRoger Lu 	     pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
64ebb44440SRoger Lu 	     mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
65ebb44440SRoger Lu 	     mmio_read_32(PWR_STATUS_2ND));
66ebb44440SRoger Lu 
67ebb44440SRoger Lu 	return ret;
68ebb44440SRoger Lu }
69ebb44440SRoger Lu 
go_to_spm_after_wfi(int state_id,unsigned int ext_opand,struct spm_lp_scen * spm_lp,struct wake_status ** status)70ebb44440SRoger Lu static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
71ebb44440SRoger Lu 				struct spm_lp_scen *spm_lp,
72ebb44440SRoger Lu 				struct wake_status **status)
73ebb44440SRoger Lu {
74ebb44440SRoger Lu 	unsigned int ext_status = 0U;
75ebb44440SRoger Lu 
76ebb44440SRoger Lu 	/* system watchdog will be resumed at kernel stage */
77ebb44440SRoger Lu 	if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
78ebb44440SRoger Lu 		__spm_set_pcm_wdt(0);
79ebb44440SRoger Lu 	}
80ebb44440SRoger Lu 
81ebb44440SRoger Lu 	if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
82ebb44440SRoger Lu 		__spm_xo_soc_bblpm(0);
83ebb44440SRoger Lu 	}
84ebb44440SRoger Lu 
85ebb44440SRoger Lu 	if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
86ebb44440SRoger Lu 		spm_hw_s1_state_monitor_pause(&ext_status);
87ebb44440SRoger Lu 	}
88ebb44440SRoger Lu 
89ebb44440SRoger Lu 	__spm_ext_int_wakeup_req_clr();
90ebb44440SRoger Lu 	__spm_get_wakeup_status(&spm_wakesta, ext_status);
91ebb44440SRoger Lu 
92ebb44440SRoger Lu 	if (status != NULL) {
93ebb44440SRoger Lu 		*status = &spm_wakesta;
94ebb44440SRoger Lu 	}
95ebb44440SRoger Lu 
96ebb44440SRoger Lu 	__spm_clean_after_wakeup();
97ebb44440SRoger Lu 
98ebb44440SRoger Lu 	if (IS_PLAT_SUSPEND_ID(state_id)) {
99ebb44440SRoger Lu 		__spm_output_wake_reason(state_id, &spm_wakesta);
100ebb44440SRoger Lu 	}
101ebb44440SRoger Lu }
102ebb44440SRoger Lu 
spm_conservation(int state_id,unsigned int ext_opand,struct spm_lp_scen * spm_lp,unsigned int resource_req)103ebb44440SRoger Lu int spm_conservation(int state_id, unsigned int ext_opand,
104ebb44440SRoger Lu 		     struct spm_lp_scen *spm_lp, unsigned int resource_req)
105ebb44440SRoger Lu {
106ebb44440SRoger Lu 	if (spm_lp == NULL) {
107ebb44440SRoger Lu 		return -1;
108ebb44440SRoger Lu 	}
109ebb44440SRoger Lu 
110ebb44440SRoger Lu 	spm_lock_get();
111ebb44440SRoger Lu 	go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req);
112ebb44440SRoger Lu 	spm_lock_release();
113ebb44440SRoger Lu 
114ebb44440SRoger Lu 	return 0;
115ebb44440SRoger Lu }
116ebb44440SRoger Lu 
spm_conservation_finish(int state_id,unsigned int ext_opand,struct spm_lp_scen * spm_lp,struct wake_status ** status)117ebb44440SRoger Lu void spm_conservation_finish(int state_id, unsigned int ext_opand,
118ebb44440SRoger Lu 			     struct spm_lp_scen *spm_lp,
119ebb44440SRoger Lu 			     struct wake_status **status)
120ebb44440SRoger Lu {
121ebb44440SRoger Lu 	spm_lock_get();
122ebb44440SRoger Lu 	go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
123ebb44440SRoger Lu 	spm_lock_release();
124ebb44440SRoger Lu }
125ebb44440SRoger Lu 
spm_conservation_get_result(struct wake_status ** res)126ebb44440SRoger Lu int spm_conservation_get_result(struct wake_status **res)
127ebb44440SRoger Lu {
128ebb44440SRoger Lu 	if (res == NULL) {
129ebb44440SRoger Lu 		return -1;
130ebb44440SRoger Lu 	}
131ebb44440SRoger Lu 
132ebb44440SRoger Lu 	*res = &spm_wakesta;
133ebb44440SRoger Lu 
134ebb44440SRoger Lu 	return 0;
135ebb44440SRoger Lu }
136ebb44440SRoger Lu 
137ebb44440SRoger Lu #define GPIO_BANK	(GPIO_BASE + 0x6F0)
138ebb44440SRoger Lu #define TRAP_UFS_FIRST	BIT(11) /* bit 11, 0: UFS, 1: eMMC */
139ebb44440SRoger Lu 
spm_conservation_pwrctrl_init(struct pwr_ctrl * pwrctrl)140ebb44440SRoger Lu void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl)
141ebb44440SRoger Lu {
142ebb44440SRoger Lu 	if (pwrctrl == NULL) {
143ebb44440SRoger Lu 		return;
144ebb44440SRoger Lu 	}
145ebb44440SRoger Lu 
146ebb44440SRoger Lu 	/* For ufs, emmc storage type */
147ebb44440SRoger Lu 	if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) {
148ebb44440SRoger Lu 		/* If eMMC is used, mask UFS req */
149ebb44440SRoger Lu 		pwrctrl->reg_ufs_srcclkena_mask_b = 0;
150ebb44440SRoger Lu 		pwrctrl->reg_ufs_infra_req_mask_b = 0;
151ebb44440SRoger Lu 		pwrctrl->reg_ufs_apsrc_req_mask_b = 0;
152ebb44440SRoger Lu 		pwrctrl->reg_ufs_vrf18_req_mask_b = 0;
153ebb44440SRoger Lu 		pwrctrl->reg_ufs_ddr_en_mask_b = 0;
154ebb44440SRoger Lu 	}
155ebb44440SRoger Lu }
156