/* * Copyright (c) 2023, MediaTek Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "mt_spm_rc_api.h" #include "mt_spm_rc_internal.h" int 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) { unsigned int rc_id, cond_id, cond; int res = 0; spin_lock(&spm_lock); rc_id = SPM_RC_UPDATE_COND_RC_ID_GET(id); cond_id = SPM_RC_UPDATE_COND_ID_GET(id); do { if ((dest_rc_id != rc_id) || (val == NULL) || (tlb == NULL)) { res = -1; break; } cond = *((unsigned int *)val); if (cond_id < PLAT_SPM_COND_MAX) { if ((act & MT_LPM_SMC_ACT_SET) > 0U) { SPM_RC_BITS_SET(tlb->table_cg[cond_id], cond); } else if ((act & MT_LPM_SMC_ACT_CLR) > 0U) { SPM_RC_BITS_CLR(tlb->table_cg[cond_id], cond); } else { res = -1; } } else if ((cond_id - PLAT_SPM_COND_MAX) < PLAT_SPM_COND_PLL_MAX) { unsigned int pll_idx = cond_id - PLAT_SPM_COND_MAX; cond = !!cond; if ((act & MT_LPM_SMC_ACT_SET) > 0U) { SPM_RC_BITS_SET(tlb->table_pll, (cond << pll_idx)); } else if ((act & MT_LPM_SMC_ACT_CLR) > 0U) { SPM_RC_BITS_CLR(tlb->table_pll, (cond << pll_idx)); } else { res = -1; } } else { res = -1; } } while (0); spin_unlock(&spm_lock); return res; } int 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) { if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL) || (src == NULL)) { return -1; } spin_lock(&spm_lock); switch (type) { case CONSTRAINT_GET_ENTER_CNT: if (id == MT_RM_CONSTRAINT_ID_ALL) { dest->enter_cnt += src->enter_cnt; } else { dest->enter_cnt = src->enter_cnt; } break; case CONSTRAINT_GET_VALID: dest->is_valid = src->is_valid; break; case CONSTRAINT_COND_BLOCK: dest->is_cond_block = src->is_cond_block; dest->all_pll_dump = src->all_pll_dump; break; case CONSTRAINT_GET_COND_BLOCK_DETAIL: dest->cond_res = src->cond_res; break; case CONSTRAINT_GET_RESIDNECY: dest->residency = src->residency; if (act & MT_LPM_SMC_ACT_CLR) { src->residency = 0; } break; default: break; } spin_unlock(&spm_lock); return 0; } int 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) { if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL)) { return -1; } spin_lock(&spm_lock); switch (type) { case CONSTRAINT_UPDATE_VALID: if (src != NULL) { if ((act & MT_LPM_SMC_ACT_SET) > 0U) { SPM_RC_BITS_SET(dest->is_valid, src->is_valid); } else if ((act & MT_LPM_SMC_ACT_CLR) > 0U) { SPM_RC_BITS_CLR(dest->is_valid, src->is_valid); } } break; case CONSTRAINT_RESIDNECY: if (act & MT_LPM_SMC_ACT_CLR) { dest->residency = 0; } break; default: break; } spin_unlock(&spm_lock); return 0; } int 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) { if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL)) { return -1; } spin_lock(&spm_lock); SPM_RC_BITS_SET(dest->is_valid, valid); spin_unlock(&spm_lock); return 0; } int 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) { if (((id != MT_RM_CONSTRAINT_ID_ALL) && (id != dest_rc_id)) || (dest == NULL)) { return -1; } spin_lock(&spm_lock); SPM_RC_BITS_CLR(dest->is_valid, valid); spin_unlock(&spm_lock); return 0; }