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