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