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