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