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
mtcmos_wait_for_state(uint32_t reg,uint32_t mask,bool is_set)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
spm_mtcmos_ctrl_bus_prot(const struct bus_protect * bp_table,uint32_t bp_steps)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
spm_mtcmos_ctrl(enum mtcmos_state state,uintptr_t reg,bool has_sram,int * rtff_save_flag,const struct bus_protect * bp_table,uint32_t bp_steps)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
spm_mtcmos_ctrl_ufs0(enum mtcmos_state state)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
spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state)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