1*532ac057SKun Lu /*
2*532ac057SKun Lu * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3*532ac057SKun Lu *
4*532ac057SKun Lu * SPDX-License-Identifier: BSD-3-Clause
5*532ac057SKun Lu */
6*532ac057SKun Lu
7*532ac057SKun Lu #include <lpm_v2/mt_lpm_smc.h>
8*532ac057SKun Lu #include <mt_spm_common.h>
9*532ac057SKun Lu #include <mt_spm_hwreq.h>
10*532ac057SKun Lu #include <mt_spm_rc_api_common.h>
11*532ac057SKun Lu
12*532ac057SKun Lu #define SPM_RC_VALID_SET(dest, src) ({ (dest) |= (src); })
13*532ac057SKun Lu #define SPM_RC_VALID_CLR(dest, src) ({ (dest) &= ~(src); })
14*532ac057SKun Lu
spm_rc_constraint_status_get(uint32_t id,uint32_t type,uint32_t act,enum mt_spm_rm_rc_type dest_rc_id,struct constraint_status * const src,struct constraint_status * const dest)15*532ac057SKun Lu int spm_rc_constraint_status_get(uint32_t id, uint32_t type,
16*532ac057SKun Lu uint32_t act,
17*532ac057SKun Lu enum mt_spm_rm_rc_type dest_rc_id,
18*532ac057SKun Lu struct constraint_status * const src,
19*532ac057SKun Lu struct constraint_status * const dest)
20*532ac057SKun Lu {
21*532ac057SKun Lu if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
22*532ac057SKun Lu (id != dest_rc_id)) || !dest || !src)
23*532ac057SKun Lu return -1;
24*532ac057SKun Lu spm_lock_get();
25*532ac057SKun Lu
26*532ac057SKun Lu switch (type) {
27*532ac057SKun Lu case CONSTRAINT_GET_ENTER_CNT:
28*532ac057SKun Lu if (id == MT_RM_CONSTRAINT_ID_ALL)
29*532ac057SKun Lu dest->enter_cnt += src->enter_cnt;
30*532ac057SKun Lu else
31*532ac057SKun Lu dest->enter_cnt = src->enter_cnt;
32*532ac057SKun Lu break;
33*532ac057SKun Lu case CONSTRAINT_GET_VALID:
34*532ac057SKun Lu dest->is_valid = src->is_valid;
35*532ac057SKun Lu break;
36*532ac057SKun Lu case CONSTRAINT_COND_BLOCK:
37*532ac057SKun Lu dest->is_cond_block = src->is_cond_block;
38*532ac057SKun Lu dest->all_pll_dump = src->all_pll_dump;
39*532ac057SKun Lu break;
40*532ac057SKun Lu case CONSTRAINT_GET_COND_BLOCK_DETAIL:
41*532ac057SKun Lu dest->cond_res = src->cond_res;
42*532ac057SKun Lu break;
43*532ac057SKun Lu case CONSTRAINT_GET_RESIDNECY:
44*532ac057SKun Lu dest->residency = src->residency;
45*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_CLR)
46*532ac057SKun Lu src->residency = 0;
47*532ac057SKun Lu break;
48*532ac057SKun Lu default:
49*532ac057SKun Lu break;
50*532ac057SKun Lu }
51*532ac057SKun Lu
52*532ac057SKun Lu spm_lock_release();
53*532ac057SKun Lu return 0;
54*532ac057SKun Lu }
55*532ac057SKun Lu
spm_rc_constraint_status_set(uint32_t id,uint32_t type,uint32_t act,enum mt_spm_rm_rc_type dest_rc_id,struct constraint_status * const src,struct constraint_status * const dest)56*532ac057SKun Lu int spm_rc_constraint_status_set(uint32_t id, uint32_t type,
57*532ac057SKun Lu uint32_t act,
58*532ac057SKun Lu enum mt_spm_rm_rc_type dest_rc_id,
59*532ac057SKun Lu struct constraint_status * const src,
60*532ac057SKun Lu struct constraint_status * const dest)
61*532ac057SKun Lu {
62*532ac057SKun Lu if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
63*532ac057SKun Lu (id != dest_rc_id)) || !dest)
64*532ac057SKun Lu return -1;
65*532ac057SKun Lu
66*532ac057SKun Lu spm_lock_get();
67*532ac057SKun Lu
68*532ac057SKun Lu switch (type) {
69*532ac057SKun Lu case CONSTRAINT_UPDATE_VALID:
70*532ac057SKun Lu if (src) {
71*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_SET)
72*532ac057SKun Lu SPM_RC_VALID_SET(dest->is_valid, src->is_valid);
73*532ac057SKun Lu else if (act & MT_LPM_SMC_ACT_CLR)
74*532ac057SKun Lu SPM_RC_VALID_CLR(dest->is_valid, src->is_valid);
75*532ac057SKun Lu }
76*532ac057SKun Lu break;
77*532ac057SKun Lu case CONSTRAINT_RESIDNECY:
78*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_CLR)
79*532ac057SKun Lu dest->residency = 0;
80*532ac057SKun Lu break;
81*532ac057SKun Lu default:
82*532ac057SKun Lu break;
83*532ac057SKun Lu }
84*532ac057SKun Lu
85*532ac057SKun Lu spm_lock_release();
86*532ac057SKun Lu
87*532ac057SKun Lu return 0;
88*532ac057SKun Lu }
89*532ac057SKun Lu
spm_rc_constraint_valid_set(enum mt_spm_rm_rc_type id,enum mt_spm_rm_rc_type dest_rc_id,uint32_t valid,struct constraint_status * const dest)90*532ac057SKun Lu int spm_rc_constraint_valid_set(enum mt_spm_rm_rc_type id,
91*532ac057SKun Lu enum mt_spm_rm_rc_type dest_rc_id,
92*532ac057SKun Lu uint32_t valid,
93*532ac057SKun Lu struct constraint_status * const dest)
94*532ac057SKun Lu {
95*532ac057SKun Lu if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
96*532ac057SKun Lu (id != dest_rc_id)) || !dest)
97*532ac057SKun Lu return -1;
98*532ac057SKun Lu
99*532ac057SKun Lu spm_lock_get();
100*532ac057SKun Lu SPM_RC_VALID_SET(dest->is_valid, valid);
101*532ac057SKun Lu spm_lock_release();
102*532ac057SKun Lu
103*532ac057SKun Lu return 0;
104*532ac057SKun Lu }
105*532ac057SKun Lu
spm_rc_constraint_valid_clr(enum mt_spm_rm_rc_type id,enum mt_spm_rm_rc_type dest_rc_id,uint32_t valid,struct constraint_status * const dest)106*532ac057SKun Lu int spm_rc_constraint_valid_clr(enum mt_spm_rm_rc_type id,
107*532ac057SKun Lu enum mt_spm_rm_rc_type dest_rc_id,
108*532ac057SKun Lu uint32_t valid,
109*532ac057SKun Lu struct constraint_status * const dest)
110*532ac057SKun Lu {
111*532ac057SKun Lu if (((id != MT_RM_CONSTRAINT_ID_ALL) &&
112*532ac057SKun Lu (id != dest_rc_id)) || !dest)
113*532ac057SKun Lu return -1;
114*532ac057SKun Lu
115*532ac057SKun Lu spm_lock_get();
116*532ac057SKun Lu SPM_RC_VALID_CLR(dest->is_valid, valid);
117*532ac057SKun Lu spm_lock_release();
118*532ac057SKun Lu
119*532ac057SKun Lu return 0;
120*532ac057SKun Lu }
121*532ac057SKun Lu
122*532ac057SKun Lu #define PMIC_WRAP_REG_1 0x3E8
123*532ac057SKun Lu #define PMIC_WRAP_REG_STEP 0x4
124*532ac057SKun Lu #define PMIC_WRAP_REG_2 0xC28
125*532ac057SKun Lu #define PMIC_WRAP_REG_3 0xF54
126*532ac057SKun Lu
127*532ac057SKun Lu #ifndef MTK_PLAT_SPM_PMIC_WRAP_DUMP_UNSUPPORT
mt_spm_dump_pmic_warp_reg(void)128*532ac057SKun Lu void mt_spm_dump_pmic_warp_reg(void)
129*532ac057SKun Lu {
130*532ac057SKun Lu uint32_t temp;
131*532ac057SKun Lu uint32_t i;
132*532ac057SKun Lu
133*532ac057SKun Lu for (i = 0; i <= PMIC_WRAP_REG_1; i += PMIC_WRAP_REG_STEP) {
134*532ac057SKun Lu temp = mmio_read_32(PMIC_WRAP_BASE + i);
135*532ac057SKun Lu }
136*532ac057SKun Lu
137*532ac057SKun Lu for (i = 0xC00; i <= PMIC_WRAP_REG_2; i += PMIC_WRAP_REG_STEP) {
138*532ac057SKun Lu temp = mmio_read_32(PMIC_WRAP_BASE + i);
139*532ac057SKun Lu }
140*532ac057SKun Lu
141*532ac057SKun Lu for (i = 0xF00; i <= PMIC_WRAP_REG_3; i += PMIC_WRAP_REG_STEP) {
142*532ac057SKun Lu temp = mmio_read_32(PMIC_WRAP_BASE + i);
143*532ac057SKun Lu }
144*532ac057SKun Lu }
145*532ac057SKun Lu #endif
146*532ac057SKun Lu
spm_allow_rc_vcore(int state_id)147*532ac057SKun Lu uint32_t spm_allow_rc_vcore(int state_id)
148*532ac057SKun Lu {
149*532ac057SKun Lu return CONSTRAINT_VCORE_ALLOW;
150*532ac057SKun Lu }
151*532ac057SKun Lu
spm_hwcg_name(uint32_t idex,char * name,size_t sz)152*532ac057SKun Lu int spm_hwcg_name(uint32_t idex, char *name, size_t sz)
153*532ac057SKun Lu {
154*532ac057SKun Lu int ret = 0;
155*532ac057SKun Lu
156*532ac057SKun Lu if (!name)
157*532ac057SKun Lu return -1;
158*532ac057SKun Lu
159*532ac057SKun Lu switch (idex) {
160*532ac057SKun Lu case HWCG_DDREN:
161*532ac057SKun Lu ret = snprintf(name, sz - 1, "dram");
162*532ac057SKun Lu break;
163*532ac057SKun Lu case HWCG_VRF18:
164*532ac057SKun Lu ret = snprintf(name, sz - 1, "vrf18");
165*532ac057SKun Lu break;
166*532ac057SKun Lu case HWCG_INFRA:
167*532ac057SKun Lu ret = snprintf(name, sz - 1, "infra");
168*532ac057SKun Lu break;
169*532ac057SKun Lu case HWCG_PMIC:
170*532ac057SKun Lu ret = snprintf(name, sz - 1, "pmic");
171*532ac057SKun Lu break;
172*532ac057SKun Lu case HWCG_F26M:
173*532ac057SKun Lu ret = snprintf(name, sz - 1, "26m");
174*532ac057SKun Lu break;
175*532ac057SKun Lu case HWCG_VCORE:
176*532ac057SKun Lu ret = snprintf(name, sz - 1, "vcore");
177*532ac057SKun Lu break;
178*532ac057SKun Lu default:
179*532ac057SKun Lu ret = -1;
180*532ac057SKun Lu break;
181*532ac057SKun Lu }
182*532ac057SKun Lu
183*532ac057SKun Lu if (ret < 0)
184*532ac057SKun Lu ret = -1;
185*532ac057SKun Lu
186*532ac057SKun Lu name[sz - 1] = '\0';
187*532ac057SKun Lu
188*532ac057SKun Lu return ret;
189*532ac057SKun Lu }
190