xref: /rk3399_ARM-atf/plat/mediatek/common/lpm/mt_lp_rm.c (revision b0208c73af8b9b6a3286cc846e0715aed6f75c4f)
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 
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 
39cd7890d7SBo-Chen Chen int mt_lp_rm_reset_constraint(int idx, unsigned int cpuid, int stateid)
40cd7890d7SBo-Chen Chen {
41cd7890d7SBo-Chen Chen 	struct mt_resource_constraint const *rc = NULL;
42cd7890d7SBo-Chen Chen 
43cd7890d7SBo-Chen Chen 	if ((plat_mt_rm.plat_rm == NULL) || (idx < 0) ||
44cd7890d7SBo-Chen Chen 	    (idx >= plat_mt_rm.count)) {
45cd7890d7SBo-Chen Chen 		return MT_RM_STATUS_BAD;
46cd7890d7SBo-Chen Chen 	}
47cd7890d7SBo-Chen Chen 
48cd7890d7SBo-Chen Chen 	rc = plat_mt_rm.plat_rm->consts[idx];
49cd7890d7SBo-Chen Chen 
50cd7890d7SBo-Chen Chen 	if ((rc == NULL) || (rc->reset == NULL)) {
51cd7890d7SBo-Chen Chen 		return MT_RM_STATUS_BAD;
52cd7890d7SBo-Chen Chen 	}
53cd7890d7SBo-Chen Chen 
54cd7890d7SBo-Chen Chen 	return rc->reset(cpuid, stateid);
55cd7890d7SBo-Chen Chen }
56cd7890d7SBo-Chen Chen 
57917abdd9SJames Liao int mt_lp_rm_get_status(unsigned int type, void *priv)
58917abdd9SJames Liao {
59917abdd9SJames Liao 	int res = 0;
60917abdd9SJames Liao 	struct mt_resource_constraint *const *con;
61917abdd9SJames Liao 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
62917abdd9SJames Liao 
63917abdd9SJames Liao 	if ((rm == NULL) || (type >= PLAT_RC_MAX)) {
64917abdd9SJames Liao 		return -1;
65917abdd9SJames Liao 	}
66917abdd9SJames Liao 
67917abdd9SJames Liao 	for (con = rm->consts; *con != NULL; con++) {
68917abdd9SJames Liao 		if ((*con)->get_status == NULL) {
69917abdd9SJames Liao 			continue;
70917abdd9SJames Liao 		}
71917abdd9SJames Liao 		res = (*con)->get_status(type, priv);
72917abdd9SJames Liao 		if (res == MT_RM_STATUS_STOP) {
73917abdd9SJames Liao 			break;
74917abdd9SJames Liao 		}
75917abdd9SJames Liao 	}
76917abdd9SJames Liao 
77917abdd9SJames Liao 	return res;
78917abdd9SJames Liao }
79917abdd9SJames Liao 
80cd7890d7SBo-Chen Chen int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
81cd7890d7SBo-Chen Chen 				     int stateid, void *priv)
82cd7890d7SBo-Chen Chen {
83cd7890d7SBo-Chen Chen 	int i, res = MT_RM_STATUS_BAD;
84cd7890d7SBo-Chen Chen 	struct mt_resource_constraint *const *rc;
85cd7890d7SBo-Chen Chen 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
86cd7890d7SBo-Chen Chen 
87cd7890d7SBo-Chen Chen 	if ((rm == NULL) || (idx < 0) || (idx >= plat_mt_rm.count)) {
88cd7890d7SBo-Chen Chen 		return res;
89cd7890d7SBo-Chen Chen 	}
90cd7890d7SBo-Chen Chen 
91cd7890d7SBo-Chen Chen 	/* If subsys clk/mtcmos is on, add block-resource-off flag */
92cd7890d7SBo-Chen Chen 	if (rm->update != NULL) {
93*b0208c73SLiju-Clr Chen 		res = rm->update(rm->consts, plat_mt_rm.count, stateid, priv);
94cd7890d7SBo-Chen Chen 		if (res != 0) {
95cd7890d7SBo-Chen Chen 			return res;
96cd7890d7SBo-Chen Chen 		}
97cd7890d7SBo-Chen Chen 	}
98cd7890d7SBo-Chen Chen 
99cd7890d7SBo-Chen Chen 	for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) {
100cd7890d7SBo-Chen Chen 		if (((*rc)->is_valid != NULL) &&
101cd7890d7SBo-Chen Chen 		    ((*rc)->is_valid(cpuid, stateid))) {
102cd7890d7SBo-Chen Chen 			if (((*rc)->run != NULL) &&
103cd7890d7SBo-Chen Chen 			    ((*rc)->run(cpuid, stateid) == 0)) {
104cd7890d7SBo-Chen Chen 				res = i;
105cd7890d7SBo-Chen Chen 				break;
106cd7890d7SBo-Chen Chen 			}
107cd7890d7SBo-Chen Chen 		}
108cd7890d7SBo-Chen Chen 	}
109cd7890d7SBo-Chen Chen 
110cd7890d7SBo-Chen Chen 	return res;
111cd7890d7SBo-Chen Chen }
112cd7890d7SBo-Chen Chen 
113cd7890d7SBo-Chen Chen int mt_lp_rm_do_update(int stateid, int type, void const *p)
114cd7890d7SBo-Chen Chen {
115cd7890d7SBo-Chen Chen 	int res = MT_RM_STATUS_BAD;
116cd7890d7SBo-Chen Chen 	struct mt_resource_constraint *const *rc;
117cd7890d7SBo-Chen Chen 	struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
118cd7890d7SBo-Chen Chen 
119cd7890d7SBo-Chen Chen 	if (rm == NULL) {
120cd7890d7SBo-Chen Chen 		return res;
121cd7890d7SBo-Chen Chen 	}
122cd7890d7SBo-Chen Chen 
123cd7890d7SBo-Chen Chen 	for (rc = rm->consts; *rc != NULL; rc++) {
124cd7890d7SBo-Chen Chen 		if ((*rc)->update != NULL) {
125cd7890d7SBo-Chen Chen 			res = (*rc)->update(stateid, type, p);
126cd7890d7SBo-Chen Chen 			if (res != MT_RM_STATUS_OK) {
127cd7890d7SBo-Chen Chen 				break;
128cd7890d7SBo-Chen Chen 			}
129cd7890d7SBo-Chen Chen 		}
130cd7890d7SBo-Chen Chen 	}
131cd7890d7SBo-Chen Chen 
132cd7890d7SBo-Chen Chen 	return res;
133cd7890d7SBo-Chen Chen }
134