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