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