1 /*
2  * Copyright (c) 2020-2023, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stddef.h>
8 #include <lpm/mt_lp_rm.h>
9 
10 struct platform_mt_resource_manager {
11 	unsigned int count;
12 	struct mt_resource_manager *plat_rm;
13 };
14 
15 static struct platform_mt_resource_manager plat_mt_rm;
16 
mt_lp_rm_register(struct mt_resource_manager * rm)17 int mt_lp_rm_register(struct mt_resource_manager *rm)
18 {
19 	unsigned int i;
20 	struct mt_resource_constraint *const *rc;
21 
22 	if ((rm == NULL) || (rm->consts == NULL) ||
23 	    (plat_mt_rm.plat_rm != NULL)) {
24 		return MT_RM_STATUS_BAD;
25 	}
26 
27 	for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) {
28 		if ((*rc)->init != NULL) {
29 			(*rc)->init();
30 		}
31 	}
32 
33 	plat_mt_rm.plat_rm = rm;
34 	plat_mt_rm.count = i;
35 
36 	return MT_RM_STATUS_OK;
37 }
38 
mt_lp_rm_reset_constraint(unsigned int idx,unsigned int cpuid,int stateid)39 int mt_lp_rm_reset_constraint(unsigned int idx, unsigned int cpuid, int stateid)
40 {
41 	struct mt_resource_constraint const *rc = NULL;
42 
43 	if ((plat_mt_rm.plat_rm == NULL) || (idx >= plat_mt_rm.count)) {
44 		return MT_RM_STATUS_BAD;
45 	}
46 
47 	rc = plat_mt_rm.plat_rm->consts[idx];
48 
49 	if ((rc == NULL) || (rc->reset == NULL)) {
50 		return MT_RM_STATUS_BAD;
51 	}
52 
53 	return rc->reset(cpuid, stateid);
54 }
55 
mt_lp_rm_get_status(unsigned int type,void * priv)56 int mt_lp_rm_get_status(unsigned int type, void *priv)
57 {
58 	int res = 0;
59 	struct mt_resource_constraint *const *con;
60 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
61 
62 	if ((rm == NULL) || (type >= PLAT_RC_MAX)) {
63 		return -1;
64 	}
65 
66 	for (con = rm->consts; *con != NULL; con++) {
67 		if ((*con)->get_status == NULL) {
68 			continue;
69 		}
70 		res = (*con)->get_status(type, priv);
71 		if (res == MT_RM_STATUS_STOP) {
72 			break;
73 		}
74 	}
75 
76 	return res;
77 }
78 
mt_lp_rm_do_constraint(unsigned int constraint_id,unsigned int cpuid,int stateid)79 int mt_lp_rm_do_constraint(unsigned int constraint_id, unsigned int cpuid, int stateid)
80 {
81 	int res = MT_RM_STATUS_BAD;
82 	struct mt_resource_constraint const *rc;
83 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
84 
85 	if ((rm == NULL) || (constraint_id >= plat_mt_rm.count)) {
86 		return res;
87 	}
88 
89 	rc = rm->consts[constraint_id];
90 	if ((rc != NULL) && (rc->run != NULL)) {
91 		res = rc->run(cpuid, stateid);
92 	}
93 
94 	return res;
95 }
96 
mt_lp_rm_find_constraint(unsigned int idx,unsigned int cpuid,int stateid,void * priv)97 int mt_lp_rm_find_constraint(unsigned int idx, unsigned int cpuid,
98 			     int stateid, void *priv)
99 {
100 	unsigned int i;
101 	int res = MT_RM_STATUS_BAD;
102 	struct mt_resource_constraint *const *rc;
103 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
104 
105 	if ((rm == NULL) || (idx >= plat_mt_rm.count)) {
106 		return res;
107 	}
108 
109 	/* If subsys clk/mtcmos is on, add block-resource-off flag */
110 	if (rm->update != NULL) {
111 		res = rm->update(rm->consts, plat_mt_rm.count, stateid, priv);
112 		if (res != 0) {
113 			return MT_RM_STATUS_BAD;
114 		}
115 	}
116 
117 	res = MT_RM_STATUS_BAD;
118 	for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) {
119 		if (((*rc)->is_valid != NULL) &&
120 		    ((*rc)->is_valid(cpuid, stateid))) {
121 			res = i;
122 			break;
123 		}
124 	}
125 
126 	return res;
127 }
128 
mt_lp_rm_find_and_run_constraint(unsigned int idx,unsigned int cpuid,int stateid,void * priv)129 int mt_lp_rm_find_and_run_constraint(unsigned int idx, unsigned int cpuid,
130 				     int stateid, void *priv)
131 {
132 	int res = MT_RM_STATUS_BAD;
133 
134 	res = mt_lp_rm_find_constraint(idx, cpuid, stateid, priv);
135 	if (res != MT_RM_STATUS_BAD) {
136 		mt_lp_rm_do_constraint(res, cpuid, stateid);
137 	}
138 
139 	return res;
140 }
141 
mt_lp_rm_do_update(int stateid,int type,void const * p)142 int mt_lp_rm_do_update(int stateid, int type, void const *p)
143 {
144 	int res = MT_RM_STATUS_BAD;
145 	struct mt_resource_constraint *const *rc;
146 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
147 
148 	if (rm == NULL) {
149 		return res;
150 	}
151 
152 	for (rc = rm->consts; *rc != NULL; rc++) {
153 		if ((*rc)->update != NULL) {
154 			res = (*rc)->update(stateid, type, p);
155 			if (res != MT_RM_STATUS_OK) {
156 				break;
157 			}
158 		}
159 	}
160 
161 	return res;
162 }
163