xref: /aosp_15_r20/external/coreboot/src/soc/mediatek/mt8192/srclken_rc.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* 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 */
16 enum {
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 
29 enum {
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 */
39 enum {
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 */
53 enum {
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 
60 enum {
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 
68 enum {
69 	SW_FPM_LOW = 0,
70 	SW_FPM_HIGH = 1,
71 };
72 
73 enum {
74 	SW_BBLPM_LOW = 0,
75 	SW_BBLPM_HIGH = 1,
76 };
77 
78 enum {
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 
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;
99 
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),
115 };
116 
pmic_read(u32 addr,u32 * rdata)117 static void pmic_read(u32 addr, u32 *rdata)
118 {
119 	static struct pmif *pmif_arb;
120 
121 	if (!pmif_arb)
122 		pmif_arb = get_pmif_controller(PMIF_SPI, 0);
123 
124 	pmif_arb->read(pmif_arb, 0, addr, rdata);
125 }
126 
rc_dump_reg_info(void)127 static 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 */
__rc_ctrl_mode_switch(enum chn_id id,enum rc_ctrl_m mode)150 static 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 */
__rc_ctrl_fpm_switch(enum chn_id id,unsigned int mode)182 static 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 
__rc_ctrl_bblpm_switch(enum chn_id id,unsigned int mode)189 static 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 
rc_init_subsys_hw_mode(void)196 static 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 
rc_init_subsys_lpm(void)206 static 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 
rc_ctrl_mode_switch_init(enum chn_id id)220 static void rc_ctrl_mode_switch_init(enum chn_id id)
221 {
222 	__rc_ctrl_mode_switch(id, INIT_MODE);
223 }
224 
srclken_rc_chk_init_cfg(void)225 static 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 
srclken_rc_init(void)240 int 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 }
389