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