blob: 257caa3d5ea0e7d70f72b6400c168daccc17954c [file] [log] [blame]
/*
* Copyright (c) 2023, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lpm/mt_lpm_smc.h>
#include <mt_spm.h>
#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;
}