xref: /rk3399_ARM-atf/plat/mediatek/drivers/mtcmos/mtcmos.c (revision 52e486f6a6192bd18d36cdcbc35c59092eefc810)
1 /*
2  * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <stdint.h>
7 
8 #include <common/debug.h>
9 #include <drivers/delay_timer.h>
10 #include <lib/mmio.h>
11 #include <lib/spinlock.h>
12 #include <platform_def.h>
13 
14 #include <mtcmos.h>
15 
16 #define SPM_PROJECT_CODE	0xB16
17 
18 #define PWR_RST_B	BIT(0)
19 #define PWR_ISO		BIT(1)
20 #define PWR_ON		BIT(2)
21 #define PWR_ON_2ND	BIT(3)
22 #define PWR_CLK_DIS	BIT(4)
23 #define PWR_ACK		BIT(30)
24 #define PWR_ACK_2ND	BIT(31)
25 
26 #define SRAM_PDN		BIT(8)
27 #define SRAM_PDN_ACK		BIT(12)
28 
29 #define MTCMOS_TIMEOUT_US	500
30 
31 #define MTCMOS_ETIMEDOUT	25
32 
33 static spinlock_t mtcmos_ctrl_lock;
34 
35 static int mtcmos_wait_for_state(uint32_t reg, uint32_t mask, bool is_set)
36 {
37 	uint32_t retry = MTCMOS_TIMEOUT_US;
38 	uint32_t expect = is_set ? mask : 0;
39 
40 	do {
41 		if ((mmio_read_32(reg) & mask) == expect)
42 			return 0;
43 		udelay(1);
44 		retry--;
45 	} while (retry);
46 
47 	ERROR("%s(0x%x, 0x%x, %d) timeout, reg_val=0x%x\n",
48 	      __func__, reg, mask, is_set, mmio_read_32(reg));
49 
50 	return -MTCMOS_ETIMEDOUT;
51 }
52 
53 
54 static int spm_mtcmos_ctrl_bus_prot(const struct bus_protect *bp_table, uint32_t bp_steps)
55 {
56 	int i;
57 
58 	for (i = 0; i < bp_steps; i++) {
59 		mmio_write_32(bp_table[i].en_addr, bp_table[i].mask);
60 		if (bp_table[i].rdy_addr) {
61 			if (mtcmos_wait_for_state(bp_table[i].rdy_addr, bp_table[i].mask, true))
62 				return -MTCMOS_ETIMEDOUT;
63 		}
64 	}
65 	return 0;
66 }
67 
68 
69 static int spm_mtcmos_ctrl(enum mtcmos_state state, uintptr_t reg,
70 			   bool has_sram, int *rtff_save_flag,
71 			   const struct bus_protect *bp_table, uint32_t bp_steps)
72 {
73 	int ret = 0;
74 
75 	spin_lock(&mtcmos_ctrl_lock);
76 
77 	mmio_write_32(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BIT(0));
78 
79 	if (state == STA_POWER_DOWN) {
80 		ret = spm_mtcmos_ctrl_bus_prot(bp_table, bp_steps);
81 		if (ret)
82 			goto exit;
83 
84 		if (has_sram) {
85 			mmio_setbits_32(reg, SRAM_PDN);
86 			ret = mtcmos_wait_for_state(reg, SRAM_PDN_ACK, true);
87 			if (ret)
88 				goto exit;
89 		}
90 
91 		mmio_setbits_32(reg, RTFF_CLK_DIS);
92 		mmio_setbits_32(reg, RTFF_SAVE);
93 		mmio_clrbits_32(reg, RTFF_SAVE);
94 		mmio_clrbits_32(reg, RTFF_CLK_DIS);
95 #ifdef RTFF_SAVE_FLAG
96 		mmio_setbits_32(reg, RTFF_SAVE_FLAG);
97 #endif
98 		*rtff_save_flag = 1;
99 
100 
101 		mmio_setbits_32(reg, PWR_ISO);
102 		mmio_setbits_32(reg, PWR_CLK_DIS);
103 		mmio_clrbits_32(reg, PWR_RST_B);
104 
105 		mmio_clrbits_32(reg, PWR_ON);
106 		ret = mtcmos_wait_for_state(reg, PWR_ACK, false);
107 		if (ret)
108 			goto exit;
109 
110 		mmio_clrbits_32(reg, PWR_ON_2ND);
111 		ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, false);
112 		if (ret)
113 			goto exit;
114 	} else if (state == STA_POWER_ON) {
115 		mmio_setbits_32(reg, PWR_ON);
116 		ret = mtcmos_wait_for_state(reg, PWR_ACK, true);
117 		if (ret)
118 			goto exit;
119 
120 		udelay(50);
121 
122 		mmio_setbits_32(reg, PWR_ON_2ND);
123 		ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, true);
124 		if (ret)
125 			goto exit;
126 
127 		mmio_clrbits_32(reg, PWR_CLK_DIS);
128 		mmio_clrbits_32(reg, PWR_ISO);
129 		udelay(10);
130 		mmio_setbits_32(reg, PWR_RST_B);
131 
132 
133 		if (*rtff_save_flag == 1) {
134 			mmio_setbits_32(reg, RTFF_CLK_DIS);
135 			mmio_clrbits_32(reg, RTFF_NRESTORE);
136 			mmio_setbits_32(reg, RTFF_NRESTORE);
137 			mmio_clrbits_32(reg, RTFF_CLK_DIS);
138 #ifdef RTFF_SAVE_FLAG
139 			mmio_clrbits_32(reg, RTFF_SAVE_FLAG);
140 #endif
141 			*rtff_save_flag = 0;
142 		}
143 
144 		if (has_sram) {
145 			mmio_clrbits_32(reg, SRAM_PDN);
146 			ret = mtcmos_wait_for_state(reg, SRAM_PDN_ACK, false);
147 			if (ret)
148 				goto exit;
149 		}
150 
151 		spm_mtcmos_ctrl_bus_prot(bp_table, bp_steps);
152 	}
153 
154 exit:
155 	spin_unlock(&mtcmos_ctrl_lock);
156 	return ret;
157 }
158 
159 int spm_mtcmos_ctrl_ufs0(enum mtcmos_state state)
160 {
161 	static int rtff_save_flag;
162 	const struct bus_protect *bp_table;
163 	uint32_t bp_steps;
164 
165 	if (state == STA_POWER_DOWN) {
166 		bp_table = &ufs0_bus_prot_set_table[0];
167 		bp_steps = ARRAY_SIZE(ufs0_bus_prot_set_table);
168 	} else {
169 		bp_table = &ufs0_bus_prot_clr_table[0];
170 		bp_steps = ARRAY_SIZE(ufs0_bus_prot_clr_table);
171 	}
172 
173 	return spm_mtcmos_ctrl(state, UFS0_PWR_CON, false, &rtff_save_flag,
174 			       bp_table, bp_steps);
175 }
176 
177 int spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state)
178 {
179 	static int rtff_save_flag;
180 	const struct bus_protect *bp_table;
181 	uint32_t bp_steps;
182 
183 	if (state == STA_POWER_DOWN) {
184 		bp_table = &ufs0_phy_bus_prot_set_table[0];
185 		bp_steps = ARRAY_SIZE(ufs0_phy_bus_prot_set_table);
186 	} else {
187 		bp_table = &ufs0_phy_bus_prot_clr_table[0];
188 		bp_steps = ARRAY_SIZE(ufs0_phy_bus_prot_clr_table);
189 	}
190 
191 	return spm_mtcmos_ctrl(state, UFS0_PHY_PWR_CON, true, &rtff_save_flag,
192 			       bp_table, bp_steps);
193 }
194