1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2023, MediaTek Inc. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <stdint.h> 8*91f16700Schasinglulu #include <string.h> 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <drivers/console.h> 11*91f16700Schasinglulu #include <lib/spinlock.h> 12*91f16700Schasinglulu #include <lpm/mt_lp_rqm.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu struct mt_lp_res_req_m { 15*91f16700Schasinglulu unsigned int uname[MT_LP_RQ_USER_MAX]; 16*91f16700Schasinglulu unsigned int user_num; 17*91f16700Schasinglulu unsigned int user_valid; 18*91f16700Schasinglulu unsigned int resource_num; 19*91f16700Schasinglulu unsigned int generic_resource_req; 20*91f16700Schasinglulu unsigned int flag; 21*91f16700Schasinglulu struct mt_resource_req_manager *plat_rqm; 22*91f16700Schasinglulu }; 23*91f16700Schasinglulu 24*91f16700Schasinglulu static struct mt_lp_res_req_m plat_mt_rqm; 25*91f16700Schasinglulu static spinlock_t mt_lp_rq_lock; 26*91f16700Schasinglulu 27*91f16700Schasinglulu static int mt_lp_resource_request(struct mt_lp_resource_user *this, unsigned int resource) 28*91f16700Schasinglulu { 29*91f16700Schasinglulu int i; 30*91f16700Schasinglulu struct mt_lp_res_req *const *rs; 31*91f16700Schasinglulu 32*91f16700Schasinglulu if ((this == NULL) || (resource == 0) || (resource > MT_LP_RQ_ALL)) { 33*91f16700Schasinglulu ERROR("invalid request(%x)\n", resource); 34*91f16700Schasinglulu return MT_LP_RQ_STA_BAD; 35*91f16700Schasinglulu } 36*91f16700Schasinglulu 37*91f16700Schasinglulu spin_lock(&mt_lp_rq_lock); 38*91f16700Schasinglulu 39*91f16700Schasinglulu rs = (plat_mt_rqm.plat_rqm)->res; 40*91f16700Schasinglulu for (i = 0; i < plat_mt_rqm.resource_num; i++) { 41*91f16700Schasinglulu if ((resource & rs[i]->res_id) != 0) { 42*91f16700Schasinglulu rs[i]->res_usage |= this->umask; 43*91f16700Schasinglulu } 44*91f16700Schasinglulu } 45*91f16700Schasinglulu 46*91f16700Schasinglulu plat_mt_rqm.flag = MT_LP_RQ_FLAG_NEED_UPDATE; 47*91f16700Schasinglulu spin_unlock(&mt_lp_rq_lock); 48*91f16700Schasinglulu 49*91f16700Schasinglulu return MT_LP_RQ_STA_OK; 50*91f16700Schasinglulu } 51*91f16700Schasinglulu 52*91f16700Schasinglulu static int mt_lp_resource_release(struct mt_lp_resource_user *this) 53*91f16700Schasinglulu { 54*91f16700Schasinglulu int i; 55*91f16700Schasinglulu struct mt_lp_res_req *const *rs; 56*91f16700Schasinglulu 57*91f16700Schasinglulu if (this == NULL) { 58*91f16700Schasinglulu return MT_LP_RQ_STA_BAD; 59*91f16700Schasinglulu } 60*91f16700Schasinglulu 61*91f16700Schasinglulu spin_lock(&mt_lp_rq_lock); 62*91f16700Schasinglulu 63*91f16700Schasinglulu rs = (plat_mt_rqm.plat_rqm)->res; 64*91f16700Schasinglulu for (i = 0; i < plat_mt_rqm.resource_num; i++) { 65*91f16700Schasinglulu rs[i]->res_usage &= ~(this->umask); 66*91f16700Schasinglulu } 67*91f16700Schasinglulu 68*91f16700Schasinglulu plat_mt_rqm.flag = MT_LP_RQ_FLAG_NEED_UPDATE; 69*91f16700Schasinglulu spin_unlock(&mt_lp_rq_lock); 70*91f16700Schasinglulu 71*91f16700Schasinglulu return MT_LP_RQ_STA_OK; 72*91f16700Schasinglulu } 73*91f16700Schasinglulu 74*91f16700Schasinglulu int mt_lp_resource_request_manager_register(struct mt_resource_req_manager *rqm) 75*91f16700Schasinglulu { 76*91f16700Schasinglulu unsigned int count; 77*91f16700Schasinglulu struct mt_lp_res_req *const *rs; 78*91f16700Schasinglulu 79*91f16700Schasinglulu if ((rqm == NULL) || (rqm->res == NULL) || (plat_mt_rqm.plat_rqm != NULL)) { 80*91f16700Schasinglulu return MT_LP_RQ_STA_BAD; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu rs = rqm->res; 84*91f16700Schasinglulu count = 0; 85*91f16700Schasinglulu while (*rs != NULL) { 86*91f16700Schasinglulu count++; 87*91f16700Schasinglulu rs++; 88*91f16700Schasinglulu } 89*91f16700Schasinglulu 90*91f16700Schasinglulu plat_mt_rqm.plat_rqm = rqm; 91*91f16700Schasinglulu plat_mt_rqm.resource_num = count; 92*91f16700Schasinglulu 93*91f16700Schasinglulu return MT_LP_RQ_STA_OK; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu int mt_lp_resource_user_register(char *user, struct mt_lp_resource_user *ru) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu int i, len; 99*91f16700Schasinglulu unsigned int uname; 100*91f16700Schasinglulu 101*91f16700Schasinglulu if ((plat_mt_rqm.plat_rqm == NULL) || (plat_mt_rqm.user_num >= MT_LP_RQ_USER_MAX) || 102*91f16700Schasinglulu (user == NULL)) { 103*91f16700Schasinglulu ru->uid = MT_LP_RQ_USER_INVALID; 104*91f16700Schasinglulu ru->umask = 0; 105*91f16700Schasinglulu ru->request = NULL; 106*91f16700Schasinglulu ru->release = NULL; 107*91f16700Schasinglulu ERROR("rqm register user invalid\n"); 108*91f16700Schasinglulu return MT_LP_RQ_STA_BAD; 109*91f16700Schasinglulu } 110*91f16700Schasinglulu 111*91f16700Schasinglulu len = strnlen(user, MT_LP_RQ_USER_NAME_LEN); 112*91f16700Schasinglulu 113*91f16700Schasinglulu uname = 0; 114*91f16700Schasinglulu for (i = 0; i < len; i++) { 115*91f16700Schasinglulu uname |= (user[i] << (MT_LP_RQ_USER_CHAR_U * i)); 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu spin_lock(&mt_lp_rq_lock); 119*91f16700Schasinglulu i = plat_mt_rqm.user_num; 120*91f16700Schasinglulu plat_mt_rqm.user_num += 1; 121*91f16700Schasinglulu plat_mt_rqm.uname[i] = uname; 122*91f16700Schasinglulu plat_mt_rqm.user_valid |= BIT(i); 123*91f16700Schasinglulu spin_unlock(&mt_lp_rq_lock); 124*91f16700Schasinglulu 125*91f16700Schasinglulu ru->umask = BIT(i); 126*91f16700Schasinglulu ru->uid = i; 127*91f16700Schasinglulu ru->request = mt_lp_resource_request; 128*91f16700Schasinglulu ru->release = mt_lp_resource_release; 129*91f16700Schasinglulu INFO("%s register by %s, uid = %d\n", __func__, user, ru->uid); 130*91f16700Schasinglulu 131*91f16700Schasinglulu return MT_LP_RQ_STA_OK; 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu int mt_lp_rq_get_status(int type, void *p) 135*91f16700Schasinglulu { 136*91f16700Schasinglulu int i; 137*91f16700Schasinglulu unsigned int update_sta; 138*91f16700Schasinglulu struct mt_lp_res_req *const *rs; 139*91f16700Schasinglulu struct resource_req_status *rq_sta = (struct resource_req_status *)p; 140*91f16700Schasinglulu 141*91f16700Schasinglulu if (plat_mt_rqm.flag != 0) { 142*91f16700Schasinglulu spin_lock(&mt_lp_rq_lock); 143*91f16700Schasinglulu 144*91f16700Schasinglulu update_sta = 0; 145*91f16700Schasinglulu rs = (plat_mt_rqm.plat_rqm)->res; 146*91f16700Schasinglulu for (i = 0; i < plat_mt_rqm.resource_num; i++) { 147*91f16700Schasinglulu update_sta |= ((rs[i]->res_usage & plat_mt_rqm.user_valid) != 0) ? 148*91f16700Schasinglulu rs[i]->res_rq : 0; 149*91f16700Schasinglulu } 150*91f16700Schasinglulu 151*91f16700Schasinglulu plat_mt_rqm.generic_resource_req = update_sta; 152*91f16700Schasinglulu plat_mt_rqm.flag = MT_LP_RQ_FLAG_DONE; 153*91f16700Schasinglulu spin_unlock(&mt_lp_rq_lock); 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu switch (type) { 157*91f16700Schasinglulu case PLAT_RQ_REQ_USAGE: 158*91f16700Schasinglulu rs = (plat_mt_rqm.plat_rqm)->res; 159*91f16700Schasinglulu rq_sta->val = (rq_sta->id < plat_mt_rqm.resource_num) ? 160*91f16700Schasinglulu rs[rq_sta->id]->res_usage : plat_mt_rqm.generic_resource_req; 161*91f16700Schasinglulu break; 162*91f16700Schasinglulu case PLAT_RQ_USER_NUM: 163*91f16700Schasinglulu rq_sta->val = plat_mt_rqm.user_num; 164*91f16700Schasinglulu break; 165*91f16700Schasinglulu case PLAT_RQ_USER_VALID: 166*91f16700Schasinglulu rq_sta->val = plat_mt_rqm.user_valid; 167*91f16700Schasinglulu break; 168*91f16700Schasinglulu case PLAT_RQ_PER_USER_NAME: 169*91f16700Schasinglulu rq_sta->val = (rq_sta->id < plat_mt_rqm.user_num) ? 170*91f16700Schasinglulu plat_mt_rqm.uname[rq_sta->id] : 0; 171*91f16700Schasinglulu break; 172*91f16700Schasinglulu case PLAT_RQ_REQ_NUM: 173*91f16700Schasinglulu rq_sta->val = plat_mt_rqm.resource_num; 174*91f16700Schasinglulu break; 175*91f16700Schasinglulu default: 176*91f16700Schasinglulu break; 177*91f16700Schasinglulu } 178*91f16700Schasinglulu 179*91f16700Schasinglulu return MT_LP_RQ_STA_OK; 180*91f16700Schasinglulu } 181*91f16700Schasinglulu 182*91f16700Schasinglulu int mt_lp_rq_update_status(int type, void *p) 183*91f16700Schasinglulu { 184*91f16700Schasinglulu unsigned int user_mask; 185*91f16700Schasinglulu struct resource_req_status *rq_sta = (struct resource_req_status *)p; 186*91f16700Schasinglulu 187*91f16700Schasinglulu switch (type) { 188*91f16700Schasinglulu case PLAT_RQ_USER_VALID: 189*91f16700Schasinglulu if (rq_sta->id < plat_mt_rqm.user_num) { 190*91f16700Schasinglulu user_mask = BIT(rq_sta->id); 191*91f16700Schasinglulu spin_lock(&mt_lp_rq_lock); 192*91f16700Schasinglulu plat_mt_rqm.user_valid = (rq_sta->val == 0) ? 193*91f16700Schasinglulu (plat_mt_rqm.user_valid & ~(user_mask)) : 194*91f16700Schasinglulu (plat_mt_rqm.user_valid | user_mask); 195*91f16700Schasinglulu plat_mt_rqm.flag = MT_LP_RQ_FLAG_NEED_UPDATE; 196*91f16700Schasinglulu spin_unlock(&mt_lp_rq_lock); 197*91f16700Schasinglulu } 198*91f16700Schasinglulu break; 199*91f16700Schasinglulu default: 200*91f16700Schasinglulu break; 201*91f16700Schasinglulu } 202*91f16700Schasinglulu 203*91f16700Schasinglulu return MT_LP_RQ_STA_OK; 204*91f16700Schasinglulu } 205