1 /*
2  * Copyright (c) 2023, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <lpm/mt_lpm_smc.h>
8 #include <mt_spm.h>
9 #include "mt_spm_rc_api.h"
10 #include "mt_spm_rc_internal.h"
11 
spm_rc_condition_modifier(unsigned int id,unsigned int act,const void * val,enum mt_spm_rm_rc_type dest_rc_id,struct mt_spm_cond_tables * const tlb)12 int spm_rc_condition_modifier(unsigned int id, unsigned int act,
13 			      const void *val,
14 			      enum mt_spm_rm_rc_type dest_rc_id,
15 			      struct mt_spm_cond_tables * const tlb)
16 {
17 	unsigned int rc_id, cond_id, cond;
18 	int res = 0;
19 
20 	spin_lock(&spm_lock);
21 	rc_id = SPM_RC_UPDATE_COND_RC_ID_GET(id);
22 	cond_id = SPM_RC_UPDATE_COND_ID_GET(id);
23 
24 	do {
25 		if ((dest_rc_id != rc_id) || (val == NULL) || (tlb == NULL)) {
26 			res = -1;
27 			break;
28 		}
29 
30 		cond = *((unsigned int *)val);
31 
32 		if (cond_id < PLAT_SPM_COND_MAX) {
33 			if ((act & MT_LPM_SMC_ACT_SET) > 0U) {
34 				SPM_RC_BITS_SET(tlb->table_cg[cond_id], cond);
35 			} else if ((act & MT_LPM_SMC_ACT_CLR) > 0U) {
36 				SPM_RC_BITS_CLR(tlb->table_cg[cond_id], cond);
37 			} else {
38 				res = -1;
39 			}
40 		} else if ((cond_id - PLAT_SPM_COND_MAX) < PLAT_SPM_COND_PLL_MAX) {
41 			unsigned int pll_idx = cond_id - PLAT_SPM_COND_MAX;
42 
43 			cond = !!cond;
44 			if ((act & MT_LPM_SMC_ACT_SET) > 0U) {
45 				SPM_RC_BITS_SET(tlb->table_pll, (cond << pll_idx));
46 			} else if ((act & MT_LPM_SMC_ACT_CLR) > 0U) {
47 				SPM_RC_BITS_CLR(tlb->table_pll, (cond << pll_idx));
48 			} else {
49 				res = -1;
50 			}
51 		} else {
52 			res = -1;
53 		}
54 	} while (0);
55 
56 	spin_unlock(&spm_lock);
57 
58 	return res;
59 }
60 
spm_rc_constraint_status_get(unsigned int id,unsigned int type,unsigned int act,enum mt_spm_rm_rc_type dest_rc_id,struct constraint_status * const src,struct constraint_status * const dest)61 int spm_rc_constraint_status_get(unsigned int id, unsigned int type,
62 				 unsigned int act,
63 				 enum mt_spm_rm_rc_type dest_rc_id,
64 				 struct constraint_status * const src,
65 				 struct constraint_status * const dest)
66 {
67 	if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL) ||
68 	    (src == NULL)) {
69 		return -1;
70 	}
71 	spin_lock(&spm_lock);
72 
73 	switch (type) {
74 	case CONSTRAINT_GET_ENTER_CNT:
75 		if (id == MT_RM_CONSTRAINT_ID_ALL) {
76 			dest->enter_cnt += src->enter_cnt;
77 		} else {
78 			dest->enter_cnt = src->enter_cnt;
79 		}
80 		break;
81 	case CONSTRAINT_GET_VALID:
82 		dest->is_valid = src->is_valid;
83 		break;
84 	case CONSTRAINT_COND_BLOCK:
85 		dest->is_cond_block = src->is_cond_block;
86 		dest->all_pll_dump = src->all_pll_dump;
87 		break;
88 	case CONSTRAINT_GET_COND_BLOCK_DETAIL:
89 		dest->cond_res = src->cond_res;
90 		break;
91 	case CONSTRAINT_GET_RESIDNECY:
92 		dest->residency = src->residency;
93 		if (act & MT_LPM_SMC_ACT_CLR) {
94 			src->residency = 0;
95 		}
96 		break;
97 	default:
98 		break;
99 	}
100 
101 	spin_unlock(&spm_lock);
102 	return 0;
103 }
104 
spm_rc_constraint_status_set(unsigned int id,unsigned int type,unsigned int act,enum mt_spm_rm_rc_type dest_rc_id,struct constraint_status * const src,struct constraint_status * const dest)105 int spm_rc_constraint_status_set(unsigned int id, unsigned int type,
106 				 unsigned int act,
107 				 enum mt_spm_rm_rc_type dest_rc_id,
108 				 struct constraint_status * const src,
109 				 struct constraint_status * const dest)
110 {
111 	if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL)) {
112 		return -1;
113 	}
114 
115 	spin_lock(&spm_lock);
116 
117 	switch (type) {
118 	case CONSTRAINT_UPDATE_VALID:
119 		if (src != NULL) {
120 			if ((act & MT_LPM_SMC_ACT_SET) > 0U) {
121 				SPM_RC_BITS_SET(dest->is_valid, src->is_valid);
122 			} else if ((act & MT_LPM_SMC_ACT_CLR) > 0U) {
123 				SPM_RC_BITS_CLR(dest->is_valid, src->is_valid);
124 			}
125 		}
126 		break;
127 	case CONSTRAINT_RESIDNECY:
128 		if (act & MT_LPM_SMC_ACT_CLR) {
129 			dest->residency = 0;
130 		}
131 		break;
132 	default:
133 		break;
134 	}
135 
136 	spin_unlock(&spm_lock);
137 
138 	return 0;
139 }
140 
spm_rc_constraint_valid_set(enum mt_spm_rm_rc_type id,enum mt_spm_rm_rc_type dest_rc_id,unsigned int valid,struct constraint_status * const dest)141 int spm_rc_constraint_valid_set(enum mt_spm_rm_rc_type id,
142 				enum mt_spm_rm_rc_type dest_rc_id,
143 				unsigned int valid,
144 				struct constraint_status * const dest)
145 {
146 	if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL)) {
147 		return -1;
148 	}
149 
150 	spin_lock(&spm_lock);
151 	SPM_RC_BITS_SET(dest->is_valid, valid);
152 	spin_unlock(&spm_lock);
153 
154 	return 0;
155 }
156 
spm_rc_constraint_valid_clr(enum mt_spm_rm_rc_type id,enum mt_spm_rm_rc_type dest_rc_id,unsigned int valid,struct constraint_status * const dest)157 int spm_rc_constraint_valid_clr(enum mt_spm_rm_rc_type id,
158 				enum mt_spm_rm_rc_type dest_rc_id,
159 				unsigned int valid,
160 				struct constraint_status * const dest)
161 {
162 	if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL)) {
163 		return -1;
164 	}
165 
166 	spin_lock(&spm_lock);
167 	SPM_RC_BITS_CLR(dest->is_valid, valid);
168 	spin_unlock(&spm_lock);
169 
170 	return 0;
171 }
172