1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
5 #include <soc/addressmap.h>
7 #include <soc/srclken_rc.h>
9 #define RCTAG "[SRCLKEN_RC]"
10 #define rc_info(fmt, arg ...) printk(BIOS_INFO, RCTAG "%s,%d: " fmt, \
11 __func__, __LINE__, ## arg)
15 /* RC settle time setting */
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,
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
,
38 /* RC central setting */
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 */
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 */
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
,
79 DXCO_SETTLE_BLK_DIS
= 0,
80 DXCO_SETTLE_BLK_EN
= 1,
83 #define SUB_CTRL_CON(_dcxo_prd, _xo_prd, _bypass_cmd, _dcxo_settle_blk_en) { \
84 .dcxo_prd = _dcxo_prd, \
86 .cnt_step = CENTROL_CNT_STEP, \
88 .req_ack_imd_en = 0x1, \
89 .xo_soc_link_en = 0x0, \
90 .sw_bblpm = SW_BBLPM_LOW, \
91 .sw_fpm = SW_FPM_HIGH, \
93 .bypass_cmd = _bypass_cmd, \
94 .dcxo_settle_blk_en = _dcxo_settle_blk_en, \
97 static struct mtk_rc_regs
*rc_regs
= (struct mtk_rc_regs
*)RC_BASE
;
98 static struct mtk_rc_status_regs
*rc_sta_regs
= (struct mtk_rc_status_regs
*)RC_STATUS_BASE
;
100 static 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
),
117 static void pmic_read(u32 addr
, u32
*rdata
)
119 static struct pmif
*pmif_arb
;
122 pmif_arb
= get_pmif_controller(PMIF_SPI
, 0);
124 pmif_arb
->read(pmif_arb
, 0, addr
, rdata
);
127 static void rc_dump_reg_info(void)
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
));
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
]));
149 /* RC initial flow and relative setting */
150 static void __rc_ctrl_mode_switch(enum chn_id id
, enum rc_ctrl_m 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
);
168 SET32_BITFIELDS(&rc_regs
->rc_mxx_srclken_cfg
[id
], SW_SRCLKEN_RC
, 1);
171 SET32_BITFIELDS(&rc_regs
->rc_mxx_srclken_cfg
[id
], SW_SRCLKEN_RC
, 0);
174 die("Can't support rc_mode %d\n", mode
);
177 rc_info("M%02d: %#x\n", id
, read32(&rc_regs
->rc_mxx_srclken_cfg
[id
]));
181 /* RC subsys FPM control */
182 static void __rc_ctrl_fpm_switch(enum chn_id id
, unsigned int mode
)
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
]));
189 static void __rc_ctrl_bblpm_switch(enum chn_id id
, unsigned int mode
)
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
]));
196 static void rc_init_subsys_hw_mode(void)
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
);
206 static void rc_init_subsys_lpm(void)
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
);
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
);
220 static void rc_ctrl_mode_switch_init(enum chn_id id
)
222 __rc_ctrl_mode_switch(id
, INIT_MODE
);
225 static enum rc_support
srclken_rc_chk_init_cfg(void)
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
;
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);
237 return SRCLKEN_RC_ENABLE
;
240 int srclken_rc_init(void)
242 /* New co-clock architecture srclkenrc implement here */
246 /* Check platform config to proceed init flow */
247 if (srclken_rc_chk_init_cfg() != SRCLKEN_RC_ENABLE
)
251 SET32_BITFIELDS(&rc_regs
->srclken_rc_cfg
, SW_RESET
, 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));
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));
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
);
274 /* Set PMIC addr for SPI CMD */
275 write32(&rc_regs
->rc_pmic_rcen_addr
, PMIC_PMRC_CON0
);
277 write32(&rc_regs
->rc_pmic_rcen_set_clr_addr
,
278 (PMIC_PMRC_CON0_CLR
<< 16) | PMIC_PMRC_CON0_SET
);
280 write32(&rc_regs
->rc_cmd_arb_cfg
, 0);
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
));
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
));
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));
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
));
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
));
321 /* Trigger srclken_rc enable */
322 SET32_BITFIELDS(&rc_regs
->rc_central_cfg1
,
323 SRCLKEN_RC_EN
, RC_CENTRAL_ENABLE
);
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));
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));
343 write32(&rc_regs
->srclken_rc_cfg
, _BF_VALUE(MUX_FCLK_FR
, 1));
348 /* Set req_filter m00~m12 FPM to LPM */
349 rc_init_subsys_lpm();
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;
357 /* Fix RC_MXX_REQ_STA_0 register shift */
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;
364 while ((read32(&rc_sta_regs
->rc_mxx_req_sta_0
[chn_n
+ shift_chn_n
]) & 0xa)
365 != chk_sta
&& retry
-- > 0)
368 pmic_read(PMIC_PMRC_CON0
, &temp
);
369 rc_info("polling M%02d failed.(R:%#x)(C:%#x)(PMRC:%#x)\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
);
377 /* Set req_filter m00~m12 */
378 rc_init_subsys_hw_mode();
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));