1 /*
2 * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <common/debug.h>
8
9 #include <constraints/mt_spm_rc_api.h>
10 #include <lpm_v2/mt_lpm_smc.h>
11 #ifndef MTK_PLAT_CIRQ_UNSUPPORT
12 #include <mt_gic_v3.h>
13 #endif
14 #include <mt_plat_spm_setting.h>
15 #include <mt_spm_common.h>
16
spm_rc_condition_modifier(uint32_t id,uint32_t act,const void * val,enum mt_spm_rm_rc_type dest_rc_id,struct mt_spm_cond_tables * const tlb)17 int spm_rc_condition_modifier(uint32_t id, uint32_t act, const void *val,
18 enum mt_spm_rm_rc_type dest_rc_id,
19 struct mt_spm_cond_tables *const tlb)
20 {
21 uint32_t rc_id, cond_id, cond = 0;
22 int res = 0;
23
24 plat_spm_lock();
25 rc_id = SPM_RC_UPDATE_COND_RC_ID_GET(id);
26 cond_id = SPM_RC_UPDATE_COND_ID_GET(id);
27
28 do {
29 if ((dest_rc_id != rc_id) || !val || !tlb) {
30 res = -1;
31 break;
32 }
33
34 cond = *((uint32_t *)val);
35
36 if ((cond_id - PLAT_SPM_COND_MAX) < PLAT_SPM_COND_PLL_MAX) {
37 uint32_t pll_idx = cond_id - PLAT_SPM_COND_MAX;
38
39 cond = !!cond;
40 if (act & MT_LPM_SMC_ACT_SET)
41 tlb->table_pll |= (cond << pll_idx);
42 else if (act & MT_LPM_SMC_ACT_CLR)
43 tlb->table_pll &= ~(cond << pll_idx);
44 else
45 res = -1;
46 } else
47 res = -1;
48 } while (0);
49
50 plat_spm_unlock();
51
52 return res;
53 }
54
55 /*
56 * CIRQ will respresent interrupt which type is edge
57 * when gic mask. But if the 26 clk have turned off before
58 * then cirq won't work normally.
59 * So we need to set irq pending for specific wakeup source.
60 */
61 #ifndef MTK_PLAT_CIRQ_UNSUPPORT
mt_spm_irq_remain_dump(struct mt_irqremain * irqs,uint32_t irq_index,struct wake_status * wakeup)62 static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs,
63 uint32_t irq_index,
64 struct wake_status *wakeup)
65 {
66 INFO("[SPM] r12=0x%08x(0x%08x), irq:%u(0x%08x) set pending\n",
67 wakeup->tr.comm.r12,
68 wakeup->md32pcm_wakeup_sta,
69 irqs->wakeupsrc[irq_index],
70 irqs->irqs[irq_index]);
71 }
72
do_irqs_delivery(struct mt_irqremain * irqs,struct wake_status * wakeup)73 void do_irqs_delivery(struct mt_irqremain *irqs, struct wake_status *wakeup)
74 {
75 uint32_t idx;
76
77 if (!irqs || !wakeup)
78 return;
79
80 for (idx = 0; idx < irqs->count; idx++) {
81 if ((wakeup->tr.comm.raw_sta & irqs->wakeupsrc[idx]) ||
82 (wakeup->tr.comm.r12 & irqs->wakeupsrc[idx])) {
83 if ((irqs->wakeupsrc_cat[idx] & MT_IRQ_REMAIN_CAT_LOG))
84 mt_spm_irq_remain_dump(irqs, idx, wakeup);
85
86 mt_irq_set_pending(irqs->irqs[idx]);
87 }
88 }
89 }
90 #endif
91