1cd7890d7SBo-Chen Chen /* 2917abdd9SJames Liao * Copyright (c) 2020-2023, MediaTek Inc. All rights reserved. 3cd7890d7SBo-Chen Chen * 4cd7890d7SBo-Chen Chen * SPDX-License-Identifier: BSD-3-Clause 5cd7890d7SBo-Chen Chen */ 6cd7890d7SBo-Chen Chen 7cd7890d7SBo-Chen Chen #include <stddef.h> 8917abdd9SJames Liao #include <lpm/mt_lp_rm.h> 9cd7890d7SBo-Chen Chen 10cd7890d7SBo-Chen Chen struct platform_mt_resource_manager { 11cd7890d7SBo-Chen Chen unsigned int count; 12cd7890d7SBo-Chen Chen struct mt_resource_manager *plat_rm; 13cd7890d7SBo-Chen Chen }; 14cd7890d7SBo-Chen Chen 15cd7890d7SBo-Chen Chen static struct platform_mt_resource_manager plat_mt_rm; 16cd7890d7SBo-Chen Chen 17cd7890d7SBo-Chen Chen int mt_lp_rm_register(struct mt_resource_manager *rm) 18cd7890d7SBo-Chen Chen { 19cd7890d7SBo-Chen Chen unsigned int i; 20cd7890d7SBo-Chen Chen struct mt_resource_constraint *const *rc; 21cd7890d7SBo-Chen Chen 22cd7890d7SBo-Chen Chen if ((rm == NULL) || (rm->consts == NULL) || 23cd7890d7SBo-Chen Chen (plat_mt_rm.plat_rm != NULL)) { 24cd7890d7SBo-Chen Chen return MT_RM_STATUS_BAD; 25cd7890d7SBo-Chen Chen } 26cd7890d7SBo-Chen Chen 27cd7890d7SBo-Chen Chen for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) { 28cd7890d7SBo-Chen Chen if ((*rc)->init != NULL) { 29cd7890d7SBo-Chen Chen (*rc)->init(); 30cd7890d7SBo-Chen Chen } 31cd7890d7SBo-Chen Chen } 32cd7890d7SBo-Chen Chen 33cd7890d7SBo-Chen Chen plat_mt_rm.plat_rm = rm; 34cd7890d7SBo-Chen Chen plat_mt_rm.count = i; 35cd7890d7SBo-Chen Chen 36cd7890d7SBo-Chen Chen return MT_RM_STATUS_OK; 37cd7890d7SBo-Chen Chen } 38cd7890d7SBo-Chen Chen 39*a321337bSLiju-Clr Chen int mt_lp_rm_reset_constraint(unsigned int idx, unsigned int cpuid, int stateid) 40cd7890d7SBo-Chen Chen { 41cd7890d7SBo-Chen Chen struct mt_resource_constraint const *rc = NULL; 42cd7890d7SBo-Chen Chen 43*a321337bSLiju-Clr Chen if ((plat_mt_rm.plat_rm == NULL) || (idx >= plat_mt_rm.count)) { 44cd7890d7SBo-Chen Chen return MT_RM_STATUS_BAD; 45cd7890d7SBo-Chen Chen } 46cd7890d7SBo-Chen Chen 47cd7890d7SBo-Chen Chen rc = plat_mt_rm.plat_rm->consts[idx]; 48cd7890d7SBo-Chen Chen 49cd7890d7SBo-Chen Chen if ((rc == NULL) || (rc->reset == NULL)) { 50cd7890d7SBo-Chen Chen return MT_RM_STATUS_BAD; 51cd7890d7SBo-Chen Chen } 52cd7890d7SBo-Chen Chen 53cd7890d7SBo-Chen Chen return rc->reset(cpuid, stateid); 54cd7890d7SBo-Chen Chen } 55cd7890d7SBo-Chen Chen 56917abdd9SJames Liao int mt_lp_rm_get_status(unsigned int type, void *priv) 57917abdd9SJames Liao { 58917abdd9SJames Liao int res = 0; 59917abdd9SJames Liao struct mt_resource_constraint *const *con; 60917abdd9SJames Liao struct mt_resource_manager *rm = plat_mt_rm.plat_rm; 61917abdd9SJames Liao 62917abdd9SJames Liao if ((rm == NULL) || (type >= PLAT_RC_MAX)) { 63917abdd9SJames Liao return -1; 64917abdd9SJames Liao } 65917abdd9SJames Liao 66917abdd9SJames Liao for (con = rm->consts; *con != NULL; con++) { 67917abdd9SJames Liao if ((*con)->get_status == NULL) { 68917abdd9SJames Liao continue; 69917abdd9SJames Liao } 70917abdd9SJames Liao res = (*con)->get_status(type, priv); 71917abdd9SJames Liao if (res == MT_RM_STATUS_STOP) { 72917abdd9SJames Liao break; 73917abdd9SJames Liao } 74917abdd9SJames Liao } 75917abdd9SJames Liao 76917abdd9SJames Liao return res; 77917abdd9SJames Liao } 78917abdd9SJames Liao 79*a321337bSLiju-Clr Chen int mt_lp_rm_do_constraint(unsigned int constraint_id, unsigned int cpuid, int stateid) 80*a321337bSLiju-Clr Chen { 81*a321337bSLiju-Clr Chen int res = MT_RM_STATUS_BAD; 82*a321337bSLiju-Clr Chen struct mt_resource_constraint const *rc; 83*a321337bSLiju-Clr Chen struct mt_resource_manager *rm = plat_mt_rm.plat_rm; 84*a321337bSLiju-Clr Chen 85*a321337bSLiju-Clr Chen if ((rm == NULL) || (constraint_id >= plat_mt_rm.count)) { 86*a321337bSLiju-Clr Chen return res; 87*a321337bSLiju-Clr Chen } 88*a321337bSLiju-Clr Chen 89*a321337bSLiju-Clr Chen rc = rm->consts[constraint_id]; 90*a321337bSLiju-Clr Chen if ((rc != NULL) && (rc->run != NULL)) { 91*a321337bSLiju-Clr Chen res = rc->run(cpuid, stateid); 92*a321337bSLiju-Clr Chen } 93*a321337bSLiju-Clr Chen 94*a321337bSLiju-Clr Chen return res; 95*a321337bSLiju-Clr Chen } 96*a321337bSLiju-Clr Chen 97*a321337bSLiju-Clr Chen int mt_lp_rm_find_constraint(unsigned int idx, unsigned int cpuid, 98cd7890d7SBo-Chen Chen int stateid, void *priv) 99cd7890d7SBo-Chen Chen { 100*a321337bSLiju-Clr Chen unsigned int i; 101*a321337bSLiju-Clr Chen int res = MT_RM_STATUS_BAD; 102cd7890d7SBo-Chen Chen struct mt_resource_constraint *const *rc; 103cd7890d7SBo-Chen Chen struct mt_resource_manager *rm = plat_mt_rm.plat_rm; 104cd7890d7SBo-Chen Chen 105*a321337bSLiju-Clr Chen if ((rm == NULL) || (idx >= plat_mt_rm.count)) { 106cd7890d7SBo-Chen Chen return res; 107cd7890d7SBo-Chen Chen } 108cd7890d7SBo-Chen Chen 109cd7890d7SBo-Chen Chen /* If subsys clk/mtcmos is on, add block-resource-off flag */ 110cd7890d7SBo-Chen Chen if (rm->update != NULL) { 111b0208c73SLiju-Clr Chen res = rm->update(rm->consts, plat_mt_rm.count, stateid, priv); 112cd7890d7SBo-Chen Chen if (res != 0) { 113*a321337bSLiju-Clr Chen return MT_RM_STATUS_BAD; 114cd7890d7SBo-Chen Chen } 115cd7890d7SBo-Chen Chen } 116cd7890d7SBo-Chen Chen 117*a321337bSLiju-Clr Chen res = MT_RM_STATUS_BAD; 118cd7890d7SBo-Chen Chen for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) { 119cd7890d7SBo-Chen Chen if (((*rc)->is_valid != NULL) && 120cd7890d7SBo-Chen Chen ((*rc)->is_valid(cpuid, stateid))) { 121cd7890d7SBo-Chen Chen res = i; 122cd7890d7SBo-Chen Chen break; 123cd7890d7SBo-Chen Chen } 124cd7890d7SBo-Chen Chen } 125*a321337bSLiju-Clr Chen 126*a321337bSLiju-Clr Chen return res; 127*a321337bSLiju-Clr Chen } 128*a321337bSLiju-Clr Chen 129*a321337bSLiju-Clr Chen int mt_lp_rm_find_and_run_constraint(unsigned int idx, unsigned int cpuid, 130*a321337bSLiju-Clr Chen int stateid, void *priv) 131*a321337bSLiju-Clr Chen { 132*a321337bSLiju-Clr Chen int res = MT_RM_STATUS_BAD; 133*a321337bSLiju-Clr Chen 134*a321337bSLiju-Clr Chen res = mt_lp_rm_find_constraint(idx, cpuid, stateid, priv); 135*a321337bSLiju-Clr Chen if (res != MT_RM_STATUS_BAD) { 136*a321337bSLiju-Clr Chen mt_lp_rm_do_constraint(res, cpuid, stateid); 137cd7890d7SBo-Chen Chen } 138cd7890d7SBo-Chen Chen 139cd7890d7SBo-Chen Chen return res; 140cd7890d7SBo-Chen Chen } 141cd7890d7SBo-Chen Chen 142cd7890d7SBo-Chen Chen int mt_lp_rm_do_update(int stateid, int type, void const *p) 143cd7890d7SBo-Chen Chen { 144cd7890d7SBo-Chen Chen int res = MT_RM_STATUS_BAD; 145cd7890d7SBo-Chen Chen struct mt_resource_constraint *const *rc; 146cd7890d7SBo-Chen Chen struct mt_resource_manager *rm = plat_mt_rm.plat_rm; 147cd7890d7SBo-Chen Chen 148cd7890d7SBo-Chen Chen if (rm == NULL) { 149cd7890d7SBo-Chen Chen return res; 150cd7890d7SBo-Chen Chen } 151cd7890d7SBo-Chen Chen 152cd7890d7SBo-Chen Chen for (rc = rm->consts; *rc != NULL; rc++) { 153cd7890d7SBo-Chen Chen if ((*rc)->update != NULL) { 154cd7890d7SBo-Chen Chen res = (*rc)->update(stateid, type, p); 155cd7890d7SBo-Chen Chen if (res != MT_RM_STATUS_OK) { 156cd7890d7SBo-Chen Chen break; 157cd7890d7SBo-Chen Chen } 158cd7890d7SBo-Chen Chen } 159cd7890d7SBo-Chen Chen } 160cd7890d7SBo-Chen Chen 161cd7890d7SBo-Chen Chen return res; 162cd7890d7SBo-Chen Chen } 163