xref: /arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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