xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/version/notifier/v4/mt_spm_sspm_notifier.c (revision cf2df874cd09305ac7282fadb0fef6be597dfffb)
1 /*
2  * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <lib/libc/errno.h>
8 
9 #include <lib/mmio.h>
10 #include <platform_def.h>
11 
12 #include <mtk_mmap_pool.h>
13 #include <notifier/inc/mt_spm_notifier.h>
14 #include <notifier/v4/mt_spm_sspm_intc.h>
15 
16 #define MT_SPM_SSPM_MBOX_OFF(x)		(SSPM_MBOX_3_BASE + x)
17 #define MT_SPM_MBOX(slot)		MT_SPM_SSPM_MBOX_OFF((slot<<2UL))
18 
19 /* LOOKUP SSPM_MBOX_SPM_LP1 */
20 #define SSPM_MBOX_SPM_LP_LOOKUP1	MT_SPM_MBOX(0)
21 /* LOOKUP SSPM_MBOX_SPM_LP2 */
22 #define SSPM_MBOX_SPM_LP_LOOKUP2	MT_SPM_MBOX(1)
23 #define SSPM_MBOX_SPM_LP1		MT_SPM_MBOX(2)
24 #define SSPM_MBOX_SPM_LP2		MT_SPM_MBOX(3)
25 #define SSPM_MBOX_SPM_SIZE		16
26 /* 4 mbox is in usage */
27 #define MT_SPM_MBOX_OFFSET(slot)	MT_SPM_MBOX((slot + 4))
28 
29 enum SSPM_SLEEP_CMD {
30 	SLP_TASK_NONE = 0,
31 	SLP_TASK_AP_SUSPEND,
32 	SLP_TASK_AP_RESUME,
33 	SLP_TASK_APSRC_OFF,
34 	SLP_TASK_APSRC_ON,
35 	SLP_TASK_INFRA_OFF,
36 	SLP_TASK_INFRA_ON,
37 	SLP_TASK_VCORE_OFF,
38 	SLP_TASK_VCORE_ON,
39 	SLP_TASK_IDLE_OFF,
40 	SLP_TASK_IDLE_ON,
41 	SLP_TASK_INFRA_noPERI_OFF,
42 	SLP_TASK_INFRA_noPERI_ON,
43 	SLP_TASK_ERR = 32,
44 };
45 
46 static unsigned int cur_mbox_index;
47 
__mt_spm_is_available_index(int cur_idx)48 static int __mt_spm_is_available_index(int cur_idx)
49 {
50 	unsigned int val;
51 
52 	val = mmio_read_32(MT_SPM_MBOX_OFFSET(cur_idx));
53 	val = (val >> 30);
54 	if (val == 0 || val == 3)
55 		return 1;
56 	return 0;
57 }
58 
__mt_spm_get_available_index(void)59 static int __mt_spm_get_available_index(void)
60 {
61 	unsigned int idx = cur_mbox_index;
62 	int i = 0;
63 
64 	for (i = 0 ; i < SSPM_MBOX_SPM_SIZE ; i++) {
65 		if (__mt_spm_is_available_index(idx)) {
66 			cur_mbox_index = (idx + 1) % SSPM_MBOX_SPM_SIZE;
67 			return idx;
68 		}
69 		idx = (idx + 1) % SSPM_MBOX_SPM_SIZE;
70 	}
71 	return -EBUSY;
72 }
73 
__mt_spm_sspm_write_cmd_queue(int idx,int value)74 static int __mt_spm_sspm_write_cmd_queue(int idx, int value)
75 {
76 	unsigned int val;
77 
78 	val = mmio_read_32(MT_SPM_MBOX_OFFSET(idx));
79 	val = val ^ BIT(31);
80 	val = (value & 0x3fffffff) | (val & 0xc0000000);
81 
82 	mmio_write_32(MT_SPM_MBOX_OFFSET(idx), val);
83 
84 	return 0;
85 }
86 
mt_spm_sspm_cmd_enqueue(int cmd)87 void mt_spm_sspm_cmd_enqueue(int cmd)
88 {
89 	int idx;
90 
91 	idx = __mt_spm_get_available_index();
92 
93 	/* Block when queue full */
94 	if (idx == -EBUSY) {
95 		while (!__mt_spm_is_available_index(cur_mbox_index))
96 			;
97 		idx = cur_mbox_index;
98 		cur_mbox_index = (cur_mbox_index+1) % SSPM_MBOX_SPM_SIZE;
99 	}
100 	__mt_spm_sspm_write_cmd_queue(idx, cmd);
101 
102 }
103 
mt_spm_sspm_notify_u32(int type,unsigned int val)104 int mt_spm_sspm_notify_u32(int type, unsigned int val)
105 {
106 	switch (type) {
107 	case MT_SPM_NOTIFY_LP_ENTER:
108 		mmio_write_32(SSPM_MBOX_SPM_LP1, val);
109 		mt_spm_sspm_cmd_enqueue(SLP_TASK_AP_SUSPEND);
110 		DO_SPM_SSPM_LP_NOTIFY();
111 		break;
112 	case MT_SPM_NOTIFY_LP_LEAVE:
113 		mmio_write_32(SSPM_MBOX_SPM_LP1, val);
114 		mt_spm_sspm_cmd_enqueue(SLP_TASK_AP_RESUME);
115 		DO_SPM_SSPM_LP_NOTIFY();
116 		break;
117 	case MT_SPM_NOTIFY_IDLE_ENTER:
118 		mmio_write_32(SSPM_MBOX_SPM_LP1, val);
119 		mt_spm_sspm_cmd_enqueue(SLP_TASK_IDLE_OFF);
120 		DO_SPM_SSPM_LP_NOTIFY();
121 		break;
122 	case MT_SPM_NOTIFY_IDLE_LEAVE:
123 		mmio_write_32(SSPM_MBOX_SPM_LP1, val);
124 		mt_spm_sspm_cmd_enqueue(SLP_TASK_IDLE_ON);
125 		DO_SPM_SSPM_LP_NOTIFY();
126 		break;
127 	default:
128 		break;
129 	}
130 	return 0;
131 }
132