blob: f6790c689834e4f85ae1509272f97fb1c60ec78d [file] [log] [blame]
Yuchen Huangec39cb32020-09-23 20:41:19 +08001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#include <delay.h>
5#include <soc/addressmap.h>
6#include <soc/pmif.h>
7#include <soc/srclken_rc.h>
8
9#define RCTAG "[SRCLKEN_RC]"
10#define rc_info(fmt, arg ...) printk(BIOS_INFO, RCTAG "%s,%d: " fmt, \
11 __func__, __LINE__, ## arg)
12
13#define SRCLKEN_DBG 1
14
15/* RC settle time setting */
16enum {
17 FULL_SET_HW_MODE = 0, /* dcxo mode use pmrc_en */
18 VCORE_SETTLE_TIME = 1, /* ~= 30us */
19 ULPOSC_SETTLE_TIME = 4, /* ~= 150us */
20 XO_SETTLE_TIME = 0x1, /* 2 ^ (step_sz + 5) * 0x33 * 30.77ns ~= 400us */
21 DCXO_SETTLE_TIME = 0x1, /* 2 ^ (step_sz + 5) * 0x87 * 30.77ns ~= 1063us */
22 CENTROL_CNT_STEP = 0x3, /* fix in 3, central align with Mxx channel */
23 DCXO_STABLE_TIME = 0x70,
24 XO_STABLE_TIME = 0x70,
25 KEEP_RC_SPI_ACTIVE_VAL = 1,
26 SRCLKEN_RC_EN_SEL_VAL = 0,
27};
28
29enum {
30 INIT_SUBSYS_FPM_TO_LPM = 1 << CHN_RF | 1 << CHN_DEEPIDLE | 1 << CHN_MD
31 | 1 << CHN_GPS | 1 << CHN_BT | 1 << CHN_WIFI
32 | 1 << CHN_MCU | 1 << CHN_COANT | 1 << CHN_NFC
33 | 1 << CHN_UFS | 1 << CHN_SCP | 1 << CHN_RESERVE,
34 INIT_SUBSYS_FPM_TO_BBLPM = 1 << CHN_DEEPIDLE,
35 INIT_SUBSYS_TO_HW = 1 << CHN_SUSPEND | 1 << CHN_DEEPIDLE | 1 << CHN_MCU,
36};
37
38/* RC central setting */
39enum {
40 RC_CENTRAL_ENABLE = 1,
41 RC_CENTRAL_DISABLE = 0,
42 SPI_TRIG_MODE = SRCLKENAO_MODE, /* use srlckenao to set vcore */
43 IS_SPI_DONE_RELEASE = 0, /* release vcore when spi request done */
44 IS_SPI2PMIC_SET_CLR = 0, /* register direct write */
45 SRCLKENO_0_CTRL_M = MERGE_OR_MODE, /* merge with spm */
46 VREQ_CTRL_M = BYPASS_MODE, /* merge with vreq */
47 ULPOSC_CTRL_M_VAL = BYPASS_MODE, /* merge with ulposc */
48 PWRAP_CTRL_M = MERGE_OR_MODE, /* merge with pwrap_scp */
49 SPI_CLK_SRC = RC_32K, /* pmic spec under 200us */
50};
51
52/* Other setting */
53enum {
54 DCXO_FPM_CTRL_MODE = MERGE_OR_MODE | ASYNC_MODE, /* merge with spm */
55 PWRAP_TMOUT_VAL = 0xA, /* 31us * 0xa ~= 310us */
56 FPM_MSK_B = FULL_SET_HW_MODE,
57 MD0_SRCLKENO_0_MASK_B = 0, /* md0 control by pmrc */
58};
59
60enum {
61 SUB_BBLPM_SET = 1 << CHN_COANT | 1 << CHN_DEEPIDLE,
62 SUB_FPM_SET = 1 << CHN_SUSPEND | 1 << CHN_RF | 1 << CHN_MD
63 | 1 << CHN_GPS | 1 << CHN_BT | 1 << CHN_WIFI
64 | 1 << CHN_MCU | 1 << CHN_NFC | 1 << CHN_UFS
65 | 1 << CHN_SCP | 1 << CHN_RESERVE,
66};
67
68enum {
69 SW_FPM_LOW = 0,
70 SW_FPM_HIGH = 1,
71};
72
73enum {
74 SW_BBLPM_LOW = 0,
75 SW_BBLPM_HIGH = 1,
76};
77
78enum {
79 DXCO_SETTLE_BLK_DIS = 0,
80 DXCO_SETTLE_BLK_EN = 1,
81};
82
83#define SUB_CTRL_CON(_dcxo_prd, _xo_prd, _bypass_cmd, _dcxo_settle_blk_en) { \
84 .dcxo_prd = _dcxo_prd, \
85 .xo_prd = _xo_prd, \
86 .cnt_step = CENTROL_CNT_STEP, \
87 .track_en = 0x0, \
88 .req_ack_imd_en = 0x1, \
89 .xo_soc_link_en = 0x0, \
90 .sw_bblpm = SW_BBLPM_LOW, \
91 .sw_fpm = SW_FPM_HIGH, \
92 .sw_rc = SW_MODE, \
93 .bypass_cmd = _bypass_cmd, \
94 .dcxo_settle_blk_en = _dcxo_settle_blk_en, \
95 }
96
97static struct mtk_rc_regs *rc_regs = (struct mtk_rc_regs *)RC_BASE;
98static struct mtk_rc_status_regs *rc_sta_regs = (struct mtk_rc_status_regs *)RC_STATUS_BASE;
99
100static struct subsys_rc_con rc_ctrl[MAX_CHN_NUM] = {
101 [CHN_SUSPEND] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
102 [CHN_RF] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
103 [CHN_DEEPIDLE] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME,
104 0x0, DXCO_SETTLE_BLK_EN),
105 [CHN_MD] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
106 [CHN_GPS] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
107 [CHN_BT] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
108 [CHN_WIFI] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
109 [CHN_MCU] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
110 [CHN_COANT] = SUB_CTRL_CON(0x0, 0x0, 0x1, DXCO_SETTLE_BLK_DIS),
111 [CHN_NFC] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
112 [CHN_UFS] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN),
113 [CHN_SCP] = SUB_CTRL_CON(0x0, 0x0, 0x1, DXCO_SETTLE_BLK_DIS),
114 [CHN_RESERVE] = SUB_CTRL_CON(0x0, 0x0, 0x1, DXCO_SETTLE_BLK_DIS),
115};
116
117static void pmic_read(u32 addr, u32 *rdata)
118{
119 static struct pmif *pmif_arb;
120
121 if (pmif_arb == NULL)
122 pmif_arb = get_pmif_controller(PMIF_SPI, 0);
123
124 pmif_arb->read(pmif_arb, 0, addr, rdata);
125}
126
127static void rc_dump_reg_info(void)
128{
129 unsigned int chn_n;
130
131 if (SRCLKEN_DBG) {
132 rc_info("SRCLKEN_RC_CFG:%#x\n", read32(&rc_regs->srclken_rc_cfg));
133 rc_info("RC_CENTRAL_CFG1:%#x\n", read32(&rc_regs->rc_central_cfg1));
134 rc_info("RC_CENTRAL_CFG2:%#x\n", read32(&rc_regs->rc_central_cfg2));
135 rc_info("RC_CENTRAL_CFG3:%#x\n", read32(&rc_regs->rc_central_cfg3));
136 rc_info("RC_CENTRAL_CFG4:%#x\n", read32(&rc_regs->rc_central_cfg4));
137 rc_info("RC_DCXO_FPM_CFG:%#x\n", read32(&rc_regs->rc_dcxo_fpm_cfg));
138 rc_info("SUBSYS_INTF_CFG:%#x\n", read32(&rc_regs->rc_subsys_intf_cfg));
139 rc_info("RC_SPI_STA_0:%#x\n", read32(&rc_sta_regs->rc_spi_sta_0));
140 rc_info("RC_PI_PO_STA:%#x\n", read32(&rc_sta_regs->rc_pi_po_sta_0));
141
142 for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) {
143 rc_info("M%02d: %#x\n", chn_n,
144 read32(&rc_regs->rc_mxx_srclken_cfg[chn_n]));
145 }
146 }
147}
148
149/* RC initial flow and relative setting */
150static void __rc_ctrl_mode_switch(enum chn_id id, enum rc_ctrl_m mode)
151{
152 switch (mode) {
153 case INIT_MODE:
154 SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id],
155 DCXO_SETTLE_BLK_EN, rc_ctrl[id].dcxo_settle_blk_en,
156 BYPASS_CMD_EN, rc_ctrl[id].bypass_cmd,
157 SW_SRCLKEN_RC, rc_ctrl[id].sw_rc,
158 SW_SRCLKEN_FPM, rc_ctrl[id].sw_fpm,
159 SW_SRCLKEN_BBLPM, rc_ctrl[id].sw_bblpm,
160 XO_SOC_LINK_EN, rc_ctrl[id].xo_soc_link_en,
161 REQ_ACK_LOW_IMD_EN, rc_ctrl[id].req_ack_imd_en,
162 SRCLKEN_TRACK_M_EN, rc_ctrl[id].track_en,
163 CNT_PRD_STEP, rc_ctrl[id].cnt_step,
164 XO_STABLE_PRD, rc_ctrl[id].xo_prd,
165 DCXO_STABLE_PRD, rc_ctrl[id].dcxo_prd);
166 break;
167 case SW_MODE:
168 SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_RC, 1);
169 break;
170 case HW_MODE:
171 SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_RC, 0);
172 break;
173 default:
174 die("Can't support rc_mode %d\n", mode);
175 }
176
177 rc_info("M%02d: %#x\n", id, read32(&rc_regs->rc_mxx_srclken_cfg[id]));
178}
179
180
181/* RC subsys FPM control */
182static void __rc_ctrl_fpm_switch(enum chn_id id, unsigned int mode)
183{
184 SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_FPM, !!mode);
185 rc_ctrl[id].sw_fpm = mode;
186 rc_info("M%02d FPM SWITCH: %#x\n", id, read32(&rc_regs->rc_mxx_srclken_cfg[id]));
187}
188
189static void __rc_ctrl_bblpm_switch(enum chn_id id, unsigned int mode)
190{
191 SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_BBLPM, !!mode);
192 rc_ctrl[id].sw_bblpm = mode;
193 rc_info("M%02d BBLPM SWITCH: %#x\n", id, read32(&rc_regs->rc_mxx_srclken_cfg[id]));
194}
195
196static void rc_init_subsys_hw_mode(void)
197{
198 unsigned int chn_n;
199
200 for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) {
201 if (INIT_SUBSYS_TO_HW & (1 << chn_n))
202 __rc_ctrl_mode_switch(chn_n, HW_MODE);
203 }
204}
205
206static void rc_init_subsys_lpm(void)
207{
208 unsigned int chn_n;
209
210 for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) {
211 if (INIT_SUBSYS_FPM_TO_LPM & (1 << chn_n))
212 __rc_ctrl_fpm_switch(chn_n, SW_FPM_LOW);
213 }
214 for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) {
215 if (INIT_SUBSYS_FPM_TO_BBLPM & (1 << chn_n))
216 __rc_ctrl_bblpm_switch(chn_n, SW_BBLPM_HIGH);
217 }
218}
219
220static void rc_ctrl_mode_switch_init(enum chn_id id)
221{
222 __rc_ctrl_mode_switch(id, INIT_MODE);
223}
224
225static enum rc_support srclken_rc_chk_init_cfg(void)
226{
227 pmwrap_interface_init();
228 if (!CONFIG(SRCLKEN_RC_SUPPORT)) {
229 rc_info("Bring-UP : skip srclken_rc init\n");
230 return SRCLKEN_RC_DISABLE;
231 }
232 if (SRCLKEN_DBG) {
233 /* Enable debug trace */
234 write32(&rc_sta_regs->rc_debug_trace, 1);
235 SET32_BITFIELDS(&rc_regs->rc_debug_cfg, TRACE_MODE_EN, 1);
236 }
237 return SRCLKEN_RC_ENABLE;
238}
239
240int srclken_rc_init(void)
241{
242 /* New co-clock architecture srclkenrc implement here */
243 unsigned int chn_n;
244 int ret = 0;
245
246 /* Check platform config to proceed init flow */
247 if (srclken_rc_chk_init_cfg() != SRCLKEN_RC_ENABLE)
248 return ret;
249
250 /* Set SW RESET 1 */
251 SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, SW_RESET, 1);
252
253 /* Wait 100us */
254 udelay(100);
255
256 /* Set SW CG 1 */
257 write32(&rc_regs->srclken_rc_cfg,
258 _BF_VALUE(SW_RESET, 1) | _BF_VALUE(CG_32K_EN, 1) |
259 _BF_VALUE(CG_FCLK_EN, 1) | _BF_VALUE(CG_FCLK_FR_EN, 1));
260
261 /* Wait 100us */
262 udelay(100);
263
264 /* Set Clock Mux */
265 write32(&rc_regs->srclken_rc_cfg,
266 _BF_VALUE(SW_RESET, 1) | _BF_VALUE(CG_32K_EN, 1) |
267 _BF_VALUE(CG_FCLK_EN, 1) | _BF_VALUE(CG_FCLK_FR_EN, 1) |
268 _BF_VALUE(MUX_FCLK_FR, 1));
269
270 /* Set req_filter m00~m12 as default SW_FPM */
271 for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++)
272 rc_ctrl_mode_switch_init(chn_n);
273
274 /* Set PMIC addr for SPI CMD */
275 write32(&rc_regs->rc_pmic_rcen_addr, PMIC_PMRC_CON0);
276
277 write32(&rc_regs->rc_pmic_rcen_set_clr_addr,
278 (PMIC_PMRC_CON0_CLR << 16) | PMIC_PMRC_CON0_SET);
279
280 write32(&rc_regs->rc_cmd_arb_cfg, 0);
281
282 /* CFG1 setting for spi cmd config */
283 write32(&rc_regs->rc_central_cfg1,
284 _BF_VALUE(DCXO_SETTLE_T, DCXO_SETTLE_TIME) |
285 _BF_VALUE(NON_DCXO_SETTLE_T, XO_SETTLE_TIME) |
286 _BF_VALUE(ULPOSC_SETTLE_T, ULPOSC_SETTLE_TIME) |
287 _BF_VALUE(VCORE_SETTLE_T, VCORE_SETTLE_TIME) |
288 _BF_VALUE(SRCLKEN_RC_EN_SEL, SRCLKEN_RC_EN_SEL_VAL) |
289 _BF_VALUE(RC_SPI_ACTIVE, KEEP_RC_SPI_ACTIVE_VAL) |
290 _BF_VALUE(RCEN_ISSUE_M, IS_SPI2PMIC_SET_CLR) |
291 _BF_VALUE(SRCLKEN_RC_EN, RC_CENTRAL_DISABLE));
292
293 /* CFG2 setting for signal mode of each control mux */
294 write32(&rc_regs->rc_central_cfg2,
295 _BF_VALUE(PWRAP_SLP_MUX_SEL, SPI_CLK_SRC) |
296 _BF_VALUE(PWRAP_SLP_CTRL_M, PWRAP_CTRL_M) |
297 _BF_VALUE(ULPOSC_CTRL_M, ULPOSC_CTRL_M_VAL) |
298 _BF_VALUE(SRCVOLTEN_VREQ_M, IS_SPI_DONE_RELEASE) |
299 _BF_VALUE(SRCVOLTEN_VREQ_SEL, SPI_TRIG_MODE) |
300 _BF_VALUE(VREQ_CTRL, VREQ_CTRL_M) |
301 _BF_VALUE(SRCVOLTEN_CTRL, SRCLKENO_0_CTRL_M));
302
303 write32(&rc_regs->rc_central_cfg3,
304 _BF_VALUE(TO_LPM_SETTLE_T, 0x4) |
305 _BF_VALUE(TO_BBLPM_SETTLE_EN, 1) |
306 _BF_VALUE(BLK_COANT_DXCO_MD_TARGET, 1) |
307 _BF_VALUE(BLK_SCP_DXCO_MD_TARGET, 1) |
308 _BF_VALUE(TO_LPM_SETTLE_EN, 1));
309
310 /* Set srclkeno_0/conn_bt as factor to allow dcxo change to FPM */
311 write32(&rc_regs->rc_dcxo_fpm_cfg,
312 _BF_VALUE(SUB_SRCLKEN_FPM_MSK_B, FPM_MSK_B) |
313 _BF_VALUE(SRCVOLTEN_FPM_MSK_B, MD0_SRCLKENO_0_MASK_B) |
314 _BF_VALUE(DCXO_FPM_CTRL_M, DCXO_FPM_CTRL_MODE));
315
316 /* Set bblpm/fpm channel */
317 write32(&rc_regs->rc_subsys_intf_cfg,
318 _BF_VALUE(SRCLKEN_BBLPM_MASK_B, SUB_BBLPM_SET) |
319 _BF_VALUE(SRCLKEN_FPM_MASK_B, SUB_FPM_SET));
320
321 /* Trigger srclken_rc enable */
322 SET32_BITFIELDS(&rc_regs->rc_central_cfg1,
323 SRCLKEN_RC_EN, RC_CENTRAL_ENABLE);
324
325 write32(&rc_regs->rc_central_cfg4,
326 _BF_VALUE(SLEEP_VLD_MODE, 0x1) |
327 _BF_VALUE(PWRAP_VLD_FORCE, 0x1) |
328 _BF_VALUE(KEEP_RC_SPI_ACTIVE, 0x800));
329
330
331 /* Wait 100us */
332 udelay(100);
333
334 /* Set SW RESET 0 */
335 write32(&rc_regs->srclken_rc_cfg,
336 _BF_VALUE(CG_32K_EN, 1) | _BF_VALUE(CG_FCLK_EN, 1) |
337 _BF_VALUE(CG_FCLK_FR_EN, 1) | _BF_VALUE(MUX_FCLK_FR, 1));
338
339 /* Wait 100us */
340 udelay(100);
341
342 /* Set SW CG 0 */
343 write32(&rc_regs->srclken_rc_cfg, _BF_VALUE(MUX_FCLK_FR, 1));
344
345 /* Wait 500us */
346 udelay(500);
347
348 /* Set req_filter m00~m12 FPM to LPM */
349 rc_init_subsys_lpm();
350
351 /* Polling ACK of Initial Subsys Input */
352 for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) {
353 unsigned int chk_sta, shift_chn_n = 0;
354 int retry;
355 u32 temp;
356
357 /* Fix RC_MXX_REQ_STA_0 register shift */
358 if (chn_n > 0)
359 shift_chn_n = 1;
360
361 chk_sta = (rc_ctrl[chn_n].sw_fpm & SW_SRCLKEN_FPM_MSK) << 1 |
362 (rc_ctrl[chn_n].sw_bblpm & SW_SRCLKEN_BBLPM_MSK) << 3;
363 retry = 200;
364 while ((read32(&rc_sta_regs->rc_mxx_req_sta_0[chn_n + shift_chn_n]) & 0xa)
365 != chk_sta && retry-- > 0)
366 udelay(10);
367 if (retry < 0) {
368 pmic_read(PMIC_PMRC_CON0, &temp);
369 rc_info("polling M%02d failed.(R:%#x)(C:%#x)(PMRC:%#x)\n",
370 chn_n,
371 read32(&rc_sta_regs->rc_mxx_req_sta_0[chn_n + shift_chn_n]),
372 read32(&rc_regs->rc_mxx_srclken_cfg[chn_n]), temp);
373 ret = -1;
374 }
375 }
376
377 /* Set req_filter m00~m12 */
378 rc_init_subsys_hw_mode();
379
380 /* Release force pmic req signal */
381 write32(&rc_regs->rc_central_cfg4,
382 _BF_VALUE(SLEEP_VLD_MODE, 0x1) |
383 _BF_VALUE(KEEP_RC_SPI_ACTIVE, 0x800));
384
385 rc_dump_reg_info();
386
387 return ret;
388}