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