xref: /rk3399_ARM-atf/plat/mediatek/drivers/mtcmos/mtcmos.c (revision 1727d690d29ef604f1fcf183e35c06d33d974e63)
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 RTFF_SAVE	BIT(24)
24 #define RTFF_NRESTORE	BIT(25)
25 #define RTFF_CLK_DIS	BIT(26)
26 #define RTFF_SAVE_FLAG	BIT(27)
27 #define PWR_ACK		BIT(30)
28 #define PWR_ACK_2ND	BIT(31)
29 
30 #define UFS0_SRAM_PDN		BIT(8)
31 #define UFS0_SRAM_PDN_ACK	BIT(12)
32 
33 #define POWERON_CONFIG_EN	(SPM_BASE + 0x0)
34 #define UFS0_PWR_CON		(SPM_BASE + 0xE2C)
35 #define UFS0_PHY_PWR_CON	(SPM_BASE + 0xE30)
36 
37 #define SPM_BUS_PROTECT_EN_SET		(SPM_BASE + 0x90DC)
38 #define SPM_BUS_PROTECT_EN_CLR		(SPM_BASE + 0x90E0)
39 #define SPM_BUS_PROTECT_CG_EN_SET	(SPM_BASE + 0x90F4)
40 #define SPM_BUS_PROTECT_CG_EN_CLR	(SPM_BASE + 0x90F8)
41 #define SPM_BUS_PROTECT_RDY_STA		(SPM_BASE + 0x9208)
42 
43 #define UFS0_PROT_STEP1_MASK		BIT(11)
44 #define UFS0_PHY_PROT_STEP1_MASK	BIT(12)
45 
46 enum {
47 	RELEASE_BUS_PROTECT,
48 	SET_BUS_PROTECT
49 };
50 
51 #define MTCMOS_TIMEOUT_US	500
52 
53 #define MTCMOS_ETIMEDOUT	25
54 
55 static spinlock_t mtcmos_ctrl_lock;
56 
57 static int mtcmos_wait_for_state(uint32_t reg, uint32_t mask, bool is_set)
58 {
59 	uint32_t retry = MTCMOS_TIMEOUT_US;
60 	uint32_t expect = is_set ? mask : 0;
61 
62 	do {
63 		if ((mmio_read_32(reg) & mask) == expect)
64 			return 0;
65 		udelay(1);
66 		retry--;
67 	} while (retry);
68 
69 	ERROR("%s(0x%x, 0x%x, %d) timeout, reg_val=0x%x\n",
70 	      __func__, reg, mask, is_set, mmio_read_32(reg));
71 
72 	return -MTCMOS_ETIMEDOUT;
73 }
74 
75 
76 static int spm_mtcmos_ctrl_bus_prot(int state, uint32_t mask)
77 {
78 	mmio_write_32(SPM_BUS_PROTECT_CG_EN_SET, mask);
79 
80 	if (state == SET_BUS_PROTECT) {
81 		mmio_write_32(SPM_BUS_PROTECT_EN_SET, mask);
82 		if (mtcmos_wait_for_state(SPM_BUS_PROTECT_RDY_STA, mask,
83 					  true))
84 			return -MTCMOS_ETIMEDOUT;
85 	} else if (state == RELEASE_BUS_PROTECT) {
86 		mmio_write_32(SPM_BUS_PROTECT_EN_CLR, mask);
87 	}
88 
89 	mmio_write_32(SPM_BUS_PROTECT_CG_EN_CLR, mask);
90 
91 	return 0;
92 }
93 
94 static int spm_mtcmos_ctrl(enum mtcmos_state state, uintptr_t reg, uint32_t mask)
95 {
96 	int ret = 0;
97 
98 	spin_lock(&mtcmos_ctrl_lock);
99 
100 	mmio_write_32(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BIT(0));
101 
102 	if (state == STA_POWER_DOWN) {
103 		ret = spm_mtcmos_ctrl_bus_prot(SET_BUS_PROTECT, mask);
104 		if (ret)
105 			goto exit;
106 
107 		if (reg == UFS0_PWR_CON) {
108 			mmio_setbits_32(reg, UFS0_SRAM_PDN);
109 			ret = mtcmos_wait_for_state(reg, UFS0_SRAM_PDN_ACK,
110 						    true);
111 			if (ret)
112 				goto exit;
113 		}
114 
115 		mmio_setbits_32(reg, RTFF_CLK_DIS);
116 		mmio_setbits_32(reg, RTFF_SAVE);
117 		mmio_clrbits_32(reg, RTFF_SAVE);
118 		mmio_clrbits_32(reg, RTFF_CLK_DIS);
119 		mmio_setbits_32(reg, RTFF_SAVE_FLAG);
120 
121 		mmio_setbits_32(reg, PWR_ISO);
122 		mmio_setbits_32(reg, PWR_CLK_DIS);
123 		mmio_clrbits_32(reg, PWR_RST_B);
124 
125 		mmio_clrbits_32(reg, PWR_ON);
126 		ret = mtcmos_wait_for_state(reg, PWR_ACK, false);
127 		if (ret)
128 			goto exit;
129 
130 		mmio_clrbits_32(reg, PWR_ON_2ND);
131 		ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, false);
132 		if (ret)
133 			goto exit;
134 	} else if (state == STA_POWER_ON) {
135 		mmio_setbits_32(reg, PWR_ON);
136 		ret = mtcmos_wait_for_state(reg, PWR_ACK, true);
137 		if (ret)
138 			goto exit;
139 
140 		udelay(50);
141 
142 		mmio_setbits_32(reg, PWR_ON_2ND);
143 		ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, true);
144 		if (ret)
145 			goto exit;
146 
147 		mmio_clrbits_32(reg, PWR_CLK_DIS);
148 		mmio_clrbits_32(reg, PWR_ISO);
149 		udelay(10);
150 		mmio_setbits_32(reg, PWR_RST_B);
151 
152 		if ((mmio_read_32(reg) & RTFF_SAVE_FLAG) == RTFF_SAVE_FLAG) {
153 			mmio_setbits_32(reg, RTFF_CLK_DIS);
154 			mmio_clrbits_32(reg, RTFF_NRESTORE);
155 			mmio_setbits_32(reg, RTFF_NRESTORE);
156 			mmio_clrbits_32(reg, RTFF_CLK_DIS);
157 		}
158 
159 		if (reg == UFS0_PWR_CON) {
160 			mmio_clrbits_32(UFS0_PWR_CON, UFS0_SRAM_PDN);
161 			ret = mtcmos_wait_for_state(UFS0_PWR_CON,
162 						    UFS0_SRAM_PDN_ACK,
163 						    false);
164 			if (ret)
165 				goto exit;
166 		}
167 
168 		spm_mtcmos_ctrl_bus_prot(RELEASE_BUS_PROTECT, mask);
169 	}
170 
171 exit:
172 	spin_unlock(&mtcmos_ctrl_lock);
173 	return ret;
174 }
175 
176 int spm_mtcmos_ctrl_ufs0(enum mtcmos_state state)
177 {
178 	return spm_mtcmos_ctrl(state, UFS0_PWR_CON, UFS0_PROT_STEP1_MASK);
179 }
180 
181 int spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state)
182 {
183 	return spm_mtcmos_ctrl(state, UFS0_PHY_PWR_CON,
184 			       UFS0_PHY_PROT_STEP1_MASK);
185 }
186