blob: 1bcd5095441cd40b8e00acae50b85a9f94d9662b [file] [log] [blame]
developer451d49d2022-11-16 21:52:21 +08001/*
2 * Copyright (c) 2023, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <common/debug.h>
8#include <drivers/spm/mt_spm_resource_req.h>
9#include <lib/pm/mtk_pm.h>
10#include <lpm/mt_lpm_smc.h>
11#include <mt_spm.h>
12#include <mt_spm_cond.h>
13#include <mt_spm_conservation.h>
14#include <mt_spm_constraint.h>
15#include <mt_spm_idle.h>
16#include <mt_spm_internal.h>
17#include <mt_spm_notifier.h>
18#include "mt_spm_rc_api.h"
19#include "mt_spm_rc_internal.h"
20#include <mt_spm_reg.h>
21#include <mt_spm_suspend.h>
22
23#define CONSTRAINT_CPU_BUCK_PCM_FLAG (SPM_FLAG_DISABLE_INFRA_PDN | \
24 SPM_FLAG_DISABLE_VCORE_DVS | \
25 SPM_FLAG_DISABLE_VCORE_DFS | \
26 SPM_FLAG_SRAM_SLEEP_CTRL | \
27 SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
28 SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
29
30#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 (0)
31
32#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ (MT_SPM_DRAM_S1 | \
33 MT_SPM_DRAM_S0 | \
34 MT_SPM_SYSPLL | \
35 MT_SPM_INFRA | \
36 MT_SPM_26M | \
37 MT_SPM_XO_FPM)
38
39static unsigned int cpubuckldo_status = (MT_SPM_RC_VALID_SW | MT_SPM_RC_VALID_TRACE_TIME);
40static unsigned int cpubuckldo_enter_cnt;
41
42int spm_cpu_bcuk_ldo_conduct(int state_id,
43 struct spm_lp_scen *spm_lp,
44 unsigned int *resource_req)
45{
46 unsigned int res_req = CONSTRAINT_CPU_BUCK_RESOURCE_REQ;
47
48 if ((spm_lp == NULL) || (resource_req == NULL)) {
49 return -1;
50 }
51
52 spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG;
53 spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1;
54
55 *resource_req |= res_req;
56 return 0;
57}
58
59bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
60{
61 return IS_MT_RM_RC_READY(cpubuckldo_status);
62}
63
64static void update_rc_status(const void *val)
65{
66 const struct rc_common_state *st = (const struct rc_common_state *)val;
67
68 if (st == NULL) {
69 return;
70 }
71
72 if ((st->type == CONSTRAINT_UPDATE_VALID) && st->value) {
73 if ((st->id == MT_RM_CONSTRAINT_ID_ALL) ||
74 (st->id == MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO)) {
75 struct constraint_status *con = (struct constraint_status *)st->value;
76
77 if ((st->act & MT_LPM_SMC_ACT_CLR) > 0U) {
78 SPM_RC_BITS_CLR(cpubuckldo_status, con->is_valid);
79 } else {
80 SPM_RC_BITS_SET(cpubuckldo_status, con->is_valid);
81 }
82 }
83 }
84}
85
86int spm_update_rc_cpu_buck_ldo(int state_id, int type, const void *val)
87{
88 if (type == PLAT_RC_STATUS) {
89 update_rc_status(val);
90 }
91 return MT_RM_STATUS_OK;
92}
93
94unsigned int spm_allow_rc_cpu_buck_ldo(int state_id)
95{
96 return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF;
97}
98
99int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
100{
101 (void)cpu;
102 unsigned int ext_op = 0U;
103
104#ifndef MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
105 mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER,
106 (IS_PLAT_SUSPEND_ID(state_id) ?
107 MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : (0U)));
108#endif
109 if (cpubuckldo_status & MT_SPM_RC_VALID_TRACE_TIME) {
110 ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
111 }
112
113 if (IS_PLAT_SUSPEND_ID(state_id)) {
114 mt_spm_suspend_enter(state_id,
115 (MT_SPM_EX_OP_CLR_26M_RECORD |
116 MT_SPM_EX_OP_SET_SUSPEND_MODE |
117 MT_SPM_EX_OP_SET_WDT),
118 CONSTRAINT_CPU_BUCK_RESOURCE_REQ);
119 } else {
120 mt_spm_idle_generic_enter(state_id, ext_op, spm_cpu_bcuk_ldo_conduct);
121 }
122
123 cpubuckldo_enter_cnt++;
124
125 return 0;
126}
127
128int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
129{
130 (void)cpu;
131 unsigned int ext_op = 0U;
132
133#ifndef MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
134 mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
135#endif
136 if (cpubuckldo_status & MT_SPM_RC_VALID_TRACE_TIME) {
137 ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
138 }
139
140 if (IS_PLAT_SUSPEND_ID(state_id)) {
141 mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL);
142 } else {
143 mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL);
144 }
145
146 return 0;
147}
148
149int spm_get_status_rc_cpu_buck_ldo(unsigned int type, void *priv)
150{
151 int ret = MT_RM_STATUS_OK;
152
153 if (type != PLAT_RC_STATUS) {
154 return ret;
155 }
156
157 struct rc_common_state *st = (struct rc_common_state *)priv;
158
159 if (st == NULL) {
160 return MT_RM_STATUS_BAD;
161 }
162
163 if ((st->id == MT_RM_CONSTRAINT_ID_ALL) ||
164 (st->id == MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO)) {
165 struct constraint_status *dest;
166
167 dest = (struct constraint_status *)st->value;
168 do {
169 if (dest == NULL) {
170 break;
171 }
172 if (st->type == CONSTRAINT_GET_VALID) {
173 dest->is_valid = cpubuckldo_status;
174 } else if (st->type == CONSTRAINT_COND_BLOCK) {
175 dest->is_cond_block = 0;
176 } else if (st->type == CONSTRAINT_GET_ENTER_CNT) {
177 if (st->id == MT_RM_CONSTRAINT_ID_ALL) {
178 dest->enter_cnt += cpubuckldo_enter_cnt;
179 } else {
180 dest->enter_cnt = cpubuckldo_enter_cnt;
181 }
182 } else {
183 break;
184 }
185 if (st->id != MT_RM_CONSTRAINT_ID_ALL) {
186 ret = MT_RM_STATUS_STOP;
187 }
188 } while (0);
189 }
190 return ret;
191}