xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8189/mt_spm_cond.c (revision af0370f25a6663a0d737bbfb3985df4232eaaa55)
1*083cfadbSKun Lu /*
2*083cfadbSKun Lu  * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3*083cfadbSKun Lu  *
4*083cfadbSKun Lu  * SPDX-License-Identifier: BSD-3-Clause
5*083cfadbSKun Lu  */
6*083cfadbSKun Lu 
7*083cfadbSKun Lu #include <lib/libc/errno.h>
8*083cfadbSKun Lu #include <stdbool.h>
9*083cfadbSKun Lu 
10*083cfadbSKun Lu #include <lib/mmio.h>
11*083cfadbSKun Lu 
12*083cfadbSKun Lu #include <lib/pm/mtk_pm.h>
13*083cfadbSKun Lu #include <lpm_v2/mt_lpm_smc.h>
14*083cfadbSKun Lu #include <mt_spm_cond.h>
15*083cfadbSKun Lu #include <platform_def.h>
16*083cfadbSKun Lu 
17*083cfadbSKun Lu static struct plat_cond_info_t *cond_info;
18*083cfadbSKun Lu 
mt_spm_cond_check(const struct mt_spm_cond_tables * src,const struct mt_spm_cond_tables * dest,struct mt_spm_cond_tables * res)19*083cfadbSKun Lu uint64_t mt_spm_cond_check(const struct mt_spm_cond_tables *src,
20*083cfadbSKun Lu 			   const struct mt_spm_cond_tables *dest,
21*083cfadbSKun Lu 			   struct mt_spm_cond_tables *res)
22*083cfadbSKun Lu {
23*083cfadbSKun Lu 	uint64_t b_res = 0;
24*083cfadbSKun Lu 	unsigned int i = 0;
25*083cfadbSKun Lu 
26*083cfadbSKun Lu 	if (!src || !dest)
27*083cfadbSKun Lu 		return SPM_COND_CHECK_FAIL;
28*083cfadbSKun Lu 
29*083cfadbSKun Lu 	if (cond_info && src->table_cg && dest->table_cg) {
30*083cfadbSKun Lu 		for (i = 0; i < cond_info->idle_cond_num; i++) {
31*083cfadbSKun Lu 			if (res && res->table_cg) {
32*083cfadbSKun Lu 				res->table_cg[i] =
33*083cfadbSKun Lu 					(src->table_cg[i] & dest->table_cg[i]);
34*083cfadbSKun Lu 
35*083cfadbSKun Lu 				if (res->table_cg[i])
36*083cfadbSKun Lu 					b_res |= (((uint64_t)1) << i);
37*083cfadbSKun Lu 
38*083cfadbSKun Lu 			} else if (src->table_cg[i] & dest->table_cg[i]) {
39*083cfadbSKun Lu 				b_res |= (((uint64_t)1) << i);
40*083cfadbSKun Lu 				break;
41*083cfadbSKun Lu 			}
42*083cfadbSKun Lu 		}
43*083cfadbSKun Lu 	}
44*083cfadbSKun Lu 
45*083cfadbSKun Lu 	if (res) {
46*083cfadbSKun Lu 		res->table_pll = (src->table_pll & dest->table_pll);
47*083cfadbSKun Lu 
48*083cfadbSKun Lu 		if (res->table_pll)
49*083cfadbSKun Lu 			b_res |= (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) |
50*083cfadbSKun Lu 				 SPM_COND_CHECK_BLOCKED_PLL;
51*083cfadbSKun Lu 	} else if (src->table_pll & dest->table_pll)
52*083cfadbSKun Lu 		b_res |= SPM_COND_CHECK_BLOCKED_PLL;
53*083cfadbSKun Lu 
54*083cfadbSKun Lu 	return b_res;
55*083cfadbSKun Lu }
56*083cfadbSKun Lu 
mt_spm_dump_all_pll(const struct mt_spm_cond_tables * src,const struct mt_spm_cond_tables * dest,struct mt_spm_cond_tables * res)57*083cfadbSKun Lu uint64_t mt_spm_dump_all_pll(const struct mt_spm_cond_tables *src,
58*083cfadbSKun Lu 			     const struct mt_spm_cond_tables *dest,
59*083cfadbSKun Lu 			     struct mt_spm_cond_tables *res)
60*083cfadbSKun Lu {
61*083cfadbSKun Lu 	uint64_t b_res = 0;
62*083cfadbSKun Lu 
63*083cfadbSKun Lu 	if (res) {
64*083cfadbSKun Lu 		res->table_pll = src->table_pll;
65*083cfadbSKun Lu 		if (res->table_pll)
66*083cfadbSKun Lu 			b_res |= (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) |
67*083cfadbSKun Lu 				 SPM_COND_CHECK_BLOCKED_PLL;
68*083cfadbSKun Lu 	} else if (src->table_pll & dest->table_pll)
69*083cfadbSKun Lu 		b_res |= SPM_COND_CHECK_BLOCKED_PLL;
70*083cfadbSKun Lu 
71*083cfadbSKun Lu 	return b_res;
72*083cfadbSKun Lu }
73*083cfadbSKun Lu 
mt_spm_cond_update(struct mt_resource_constraint ** con,int num,int stateid,void * priv)74*083cfadbSKun Lu int mt_spm_cond_update(struct mt_resource_constraint **con, int num,
75*083cfadbSKun Lu 		       int stateid, void *priv)
76*083cfadbSKun Lu {
77*083cfadbSKun Lu 	int i, res;
78*083cfadbSKun Lu 	struct mt_resource_constraint *const *_con;
79*083cfadbSKun Lu 	struct plat_idle_cond_info *cg_table;
80*083cfadbSKun Lu 	struct plat_pll_cond_info *pll_table;
81*083cfadbSKun Lu 	struct mt_spm_cond_tables *spm_cond;
82*083cfadbSKun Lu 
83*083cfadbSKun Lu 	if (!cond_info)
84*083cfadbSKun Lu 		return -ENODEV;
85*083cfadbSKun Lu 
86*083cfadbSKun Lu 	cg_table = cond_info->idle_cond_table;
87*083cfadbSKun Lu 	pll_table = cond_info->pll_cond_table;
88*083cfadbSKun Lu 	spm_cond = &cond_info->cond_table_buf;
89*083cfadbSKun Lu 
90*083cfadbSKun Lu 	if (cg_table && spm_cond->table_cg) {
91*083cfadbSKun Lu 		for (i = 0; i < cond_info->idle_cond_num; i++) {
92*083cfadbSKun Lu 			spm_cond->table_cg[i] = 0;
93*083cfadbSKun Lu 			/* check mtcmos, if off set idle_value and clk to 0 disable */
94*083cfadbSKun Lu 			if (cond_info->spm_pwr_status_addr)
95*083cfadbSKun Lu 				if (!(mmio_read_32(
96*083cfadbSKun Lu 					      cond_info->spm_pwr_status_addr) &
97*083cfadbSKun Lu 				      cg_table[i].pwr_status_mask))
98*083cfadbSKun Lu 					continue;
99*083cfadbSKun Lu 
100*083cfadbSKun Lu 			if (cond_info->spm_pwr_status_2nd_addr)
101*083cfadbSKun Lu 				if (!(mmio_read_32(
102*083cfadbSKun Lu 					      cond_info->spm_pwr_status_2nd_addr) &
103*083cfadbSKun Lu 				      cg_table[i].pwr_status_mask))
104*083cfadbSKun Lu 					continue;
105*083cfadbSKun Lu 			/* check clkmux */
106*083cfadbSKun Lu 			if (cg_table[i].clkmux_addr)
107*083cfadbSKun Lu 				if (mmio_read_32(cg_table[i].clkmux_addr) &
108*083cfadbSKun Lu 				    cg_table[i].clkmux_mask)
109*083cfadbSKun Lu 					continue;
110*083cfadbSKun Lu 
111*083cfadbSKun Lu 			spm_cond->table_cg[i] =
112*083cfadbSKun Lu 				cg_table[i].bBitflip ?
113*083cfadbSKun Lu 					~mmio_read_32(cg_table[i].cg_addr) :
114*083cfadbSKun Lu 					mmio_read_32(cg_table[i].cg_addr);
115*083cfadbSKun Lu 		}
116*083cfadbSKun Lu 	}
117*083cfadbSKun Lu 
118*083cfadbSKun Lu 	if (pll_table) {
119*083cfadbSKun Lu 		spm_cond->table_pll = 0;
120*083cfadbSKun Lu 		for (i = 0; pll_table[i].pll_bit_set != PLL_BIT_MAX; i++) {
121*083cfadbSKun Lu 			if (mmio_read_32(pll_table[i].pll_addr) &
122*083cfadbSKun Lu 			    pll_table[i].pll_mask) {
123*083cfadbSKun Lu 				spm_cond->table_pll |= pll_table[i].pll_bit_set;
124*083cfadbSKun Lu 			}
125*083cfadbSKun Lu 		}
126*083cfadbSKun Lu 	}
127*083cfadbSKun Lu 
128*083cfadbSKun Lu 	spm_cond->priv = priv;
129*083cfadbSKun Lu 
130*083cfadbSKun Lu 	for (i = 0, _con = con; *_con && (*_con)->update && (i < num);
131*083cfadbSKun Lu 	     _con++, i++) {
132*083cfadbSKun Lu 		res = (*_con)->update(stateid, PLAT_RC_UPDATE_CONDITION,
133*083cfadbSKun Lu 				      (void const *)spm_cond);
134*083cfadbSKun Lu 		if (res != MT_RM_STATUS_OK)
135*083cfadbSKun Lu 			break;
136*083cfadbSKun Lu 	}
137*083cfadbSKun Lu 
138*083cfadbSKun Lu 	return 0;
139*083cfadbSKun Lu }
140*083cfadbSKun Lu 
register_plat_cond_info(struct plat_cond_info_t * cond)141*083cfadbSKun Lu int register_plat_cond_info(struct plat_cond_info_t *cond)
142*083cfadbSKun Lu {
143*083cfadbSKun Lu 	if (!cond)
144*083cfadbSKun Lu 		return -EINVAL;
145*083cfadbSKun Lu 
146*083cfadbSKun Lu 	cond_info = cond;
147*083cfadbSKun Lu 
148*083cfadbSKun Lu 	return 0;
149*083cfadbSKun Lu }
150