1 /*
2  * Copyright 2022-2023 NXP
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/init.h>
7 #include "fsl_power.h"
8 #include <zephyr/pm/policy.h>
9 #include "board.h"
10 
11 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
12 #include "flash_clock_setup.h"
13 #endif
14 
15 /* OTP fuse index. */
16 #define FRO_192MHZ_SC_TRIM 0x2C
17 #define FRO_192MHZ_RD_TRIM 0x2B
18 #define FRO_96MHZ_SC_TRIM  0x2E
19 #define FRO_96MHZ_RD_TRIM  0x2D
20 
21 #define OTP_FUSE_READ_API ((void (*)(uint32_t addr, uint32_t *data))0x1300805D)
22 
23 #define PMIC_MODE_BOOT			0U
24 #define PMIC_MODE_DEEP_SLEEP		1U
25 #define PMIC_MODE_FRO192M_900MV		2U
26 #define PMIC_MODE_FRO96M_800MV		3U
27 
28 #define PMIC_SETTLING_TIME		2000U	/* in micro-seconds */
29 
30 static uint32_t sc_trim_192, rd_trim_192, sc_trim_96, rd_trim_96;
31 
32 #if CONFIG_REGULATOR
33 #include <zephyr/drivers/regulator.h>
34 
35 #define NODE_PCA9420	DT_NODELABEL(pca9420)
36 #define NODE_SW1	DT_NODELABEL(pca9420_sw1)
37 #define NODE_SW2	DT_NODELABEL(pca9420_sw2)
38 #define NODE_LDO1	DT_NODELABEL(pca9420_ldo1)
39 #define NODE_LDO2	DT_NODELABEL(pca9420_ldo2)
40 static const struct device *pca9420 = DEVICE_DT_GET(NODE_PCA9420);
41 static const struct device *sw1 = DEVICE_DT_GET(NODE_SW1);
42 static const struct device *sw2 = DEVICE_DT_GET(NODE_SW2);
43 static const struct device *ldo1 = DEVICE_DT_GET(NODE_LDO1);
44 static const struct device *ldo2 = DEVICE_DT_GET(NODE_LDO2);
45 
46 static int current_power_profile;
47 
48 #define MEGA (1000000U)
49 
50 /* Core frequency levels number. */
51 #define POWER_FREQ_LEVELS_NUM (5U)
52 
53 /* Invalid voltage level. */
54 #define POWER_INVALID_VOLT_LEVEL (0xFFFFFFFFU)
55 
56 static const uint32_t power_freq_level[POWER_FREQ_LEVELS_NUM] = {
57 	275U * MEGA,
58 	230U * MEGA,
59 	192U * MEGA,
60 	100U * MEGA,
61 	60U * MEGA
62 };
63 
64 /* System clock frequency. */
65 extern uint32_t SystemCoreClock;
66 
67 static const int32_t sw1_volt[] = {1100000, 1000000, 900000, 800000, 700000};
68 
board_calc_volt_level(void)69 static int32_t board_calc_volt_level(void)
70 {
71 	uint32_t i;
72 	uint32_t volt;
73 
74 	for (i = 0U; i < POWER_FREQ_LEVELS_NUM; i++) {
75 		if (SystemCoreClock > power_freq_level[i]) {
76 			break;
77 		}
78 	}
79 
80 	/* Frequency exceed max supported */
81 	if (i == 0U) {
82 		volt = POWER_INVALID_VOLT_LEVEL;
83 	} else {
84 		volt = sw1_volt[i - 1U];
85 	}
86 
87 	return volt;
88 }
89 
board_config_pmic(void)90 static int board_config_pmic(void)
91 {
92 	uint32_t volt;
93 	int ret = 0;
94 
95 	volt = board_calc_volt_level();
96 
97 	ret = regulator_set_voltage(sw1, volt, volt);
98 	if (ret != 0) {
99 		return ret;
100 	}
101 
102 	ret = regulator_set_voltage(sw2, 1800000, 1800000);
103 	if (ret != 0) {
104 		return ret;
105 	}
106 
107 	ret = regulator_set_voltage(ldo1, 1800000, 1800000);
108 	if (ret != 0) {
109 		return ret;
110 	}
111 
112 	ret = regulator_set_voltage(ldo2, 3300000, 3300000);
113 	if (ret != 0) {
114 		return ret;
115 	}
116 
117 	/* We can enter deep low power modes */
118 	pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
119 
120 	return ret;
121 }
122 
board_pmic_change_mode(uint8_t pmic_mode)123 static int board_pmic_change_mode(uint8_t pmic_mode)
124 {
125 	int ret;
126 
127 	if (pmic_mode >= 4) {
128 		return -ERANGE;
129 	}
130 
131 	ret = regulator_parent_dvs_state_set(pca9420, pmic_mode);
132 	if (ret != -EPERM) {
133 		return ret;
134 	}
135 
136 	POWER_SetPmicMode(pmic_mode, kCfg_Run);
137 	k_busy_wait(PMIC_SETTLING_TIME);
138 
139 	return 0;
140 }
141 
142 /* Changes power-related config to preset profiles, like clocks and VDDCORE voltage */
power_manager_set_profile(uint32_t power_profile)143 __ramfunc int32_t power_manager_set_profile(uint32_t power_profile)
144 {
145 	bool voltage_changed = false;
146 	int32_t current_uv, future_uv;
147 	int ret;
148 
149 	if (power_profile == current_power_profile) {
150 		return 0;
151 	}
152 
153 	/* Confirm valid power_profile, and read the new VDDCORE voltage */
154 	switch (power_profile) {
155 	case POWER_PROFILE_AFTER_BOOT:
156 		future_uv = DT_PROP(NODE_SW1, nxp_mode0_microvolt);
157 		break;
158 
159 	case POWER_PROFILE_FRO192M_900MV:
160 		future_uv = DT_PROP(NODE_SW1, nxp_mode2_microvolt);
161 		break;
162 
163 	case POWER_PROFILE_FRO96M_800MV:
164 		future_uv = DT_PROP(NODE_SW1, nxp_mode3_microvolt);
165 		break;
166 
167 	default:
168 		return -EINVAL;
169 	}
170 
171 	if (current_power_profile == POWER_PROFILE_AFTER_BOOT) {
172 		/* One-Time optimization after boot */
173 
174 		POWER_DisableLVD();
175 
176 		CLOCK_AttachClk(kFRO_DIV1_to_MAIN_CLK);
177 		/* Set SYSCPUAHBCLKDIV divider to value 1 */
178 		CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U);
179 
180 		/* Other clock optimizations */
181 	#ifdef CONFIG_FLASH_MCUX_FLEXSPI_XIP
182 		flexspi_setup_clock(FLEXSPI0, 0U, 1U);	/* main_clk div by 1 */
183 	#endif
184 		/* Disable the PFDs of SYSPLL */
185 		CLKCTL0->SYSPLL0PFD |=	CLKCTL0_SYSPLL0PFD_PFD0_CLKGATE_MASK |
186 					CLKCTL0_SYSPLL0PFD_PFD1_CLKGATE_MASK |
187 					CLKCTL0_SYSPLL0PFD_PFD2_CLKGATE_MASK;
188 
189 		POWER_EnablePD(kPDRUNCFG_PD_SYSPLL_LDO);
190 		POWER_EnablePD(kPDRUNCFG_PD_SYSPLL_ANA);
191 		POWER_EnablePD(kPDRUNCFG_PD_AUDPLL_LDO);
192 		POWER_EnablePD(kPDRUNCFG_PD_AUDPLL_ANA);
193 		POWER_EnablePD(kPDRUNCFG_PD_SYSXTAL);
194 
195 		/* Configure MCU that PMIC supplies will be powered in all
196 		 * PMIC modes
197 		 */
198 		PMC->PMICCFG = 0xFF;
199 
200 	}
201 
202 	/* Get current and future PMIC voltages to determine DVFS sequence */
203 	ret = regulator_get_voltage(sw1, &current_uv);
204 	if (ret) {
205 		return ret;
206 	}
207 
208 	if (power_profile == POWER_PROFILE_FRO192M_900MV) {
209 		/* check if voltage or frequency change is first */
210 		if (future_uv > current_uv) {
211 			/* Increase voltage first before frequencies */
212 			ret = board_pmic_change_mode(PMIC_MODE_FRO192M_900MV);
213 			if (ret) {
214 				return ret;
215 			}
216 
217 			voltage_changed = true;
218 		}
219 
220 		/* Trim FRO to 192MHz */
221 		CLKCTL0->FRO_SCTRIM = sc_trim_192;
222 		CLKCTL0->FRO_RDTRIM = rd_trim_192;
223 		/* Reset the EXP_COUNT. */
224 		CLKCTL0->FRO_CONTROL &= ~CLKCTL0_FRO_CONTROL_EXP_COUNT_MASK;
225 
226 		CLOCK_AttachClk(kFRO_DIV1_to_MAIN_CLK);
227 		/* Set SYSCPUAHBCLKDIV divider to value 1 */
228 		CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U);
229 
230 		if (voltage_changed == false) {
231 			ret = board_pmic_change_mode(PMIC_MODE_FRO192M_900MV);
232 			if (ret) {
233 				return ret;
234 			}
235 		}
236 
237 	} else if (power_profile == POWER_PROFILE_FRO96M_800MV) {
238 		/* This PMIC mode is the lowest voltage used for DVFS,
239 		 * Reduce frequency first, and then reduce voltage
240 		 */
241 
242 		/* Trim the FRO to 96MHz */
243 		CLKCTL0->FRO_SCTRIM = sc_trim_96;
244 		CLKCTL0->FRO_RDTRIM = rd_trim_96;
245 		/* Reset the EXP_COUNT. */
246 		CLKCTL0->FRO_CONTROL &= ~CLKCTL0_FRO_CONTROL_EXP_COUNT_MASK;
247 
248 		CLOCK_AttachClk(kFRO_DIV1_to_MAIN_CLK);
249 		/* Set SYSCPUAHBCLKDIV divider to value 1 */
250 		CLOCK_SetClkDiv(kCLOCK_DivSysCpuAhbClk, 1U);
251 
252 		ret = board_pmic_change_mode(PMIC_MODE_FRO96M_800MV);
253 		if (ret) {
254 			return ret;
255 		}
256 	}
257 
258 	current_power_profile = power_profile;
259 
260 	return 0;
261 }
262 
263 #endif /* CONFIG_REGULATOR */
264 
mimxrt595_evk_init(void)265 static int mimxrt595_evk_init(void)
266 {
267 	/* Set the correct voltage range according to the board. */
268 	power_pad_vrange_t vrange = {
269 		.Vdde0Range = kPadVol_171_198,
270 		.Vdde1Range = kPadVol_171_198,
271 		.Vdde2Range = kPadVol_171_198,
272 		.Vdde3Range = kPadVol_300_360,
273 		.Vdde4Range = kPadVol_171_198
274 	};
275 
276 	POWER_SetPadVolRange(&vrange);
277 
278 	/* Do not enter deep low power modes until the PMIC modes have been initialized */
279 	pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES);
280 
281 #ifdef CONFIG_I2S
282 #ifdef CONFIG_I2S_TEST_SEPARATE_DEVICES
283 	/* Set shared signal set 0 SCK, WS from Transmit I2S - Flexcomm3 */
284 	SYSCTL1->SHAREDCTRLSET[0] = SYSCTL1_SHAREDCTRLSET_SHAREDSCKSEL(3) |
285 				SYSCTL1_SHAREDCTRLSET_SHAREDWSSEL(3);
286 	/* Select Data in from Transmit I2S - Flexcomm 3 */
287 	SYSCTL1->SHAREDCTRLSET[0] |= SYSCTL1_SHAREDCTRLSET_SHAREDDATASEL(3);
288 	/* Enable Transmit I2S - Flexcomm 3 for Shared Data Out */
289 	SYSCTL1->SHAREDCTRLSET[0] |= SYSCTL1_SHAREDCTRLSET_FC3DATAOUTEN(1);
290 #else
291 	/* Set shared signal set 0: SCK, WS from Flexcomm1 */
292 	SYSCTL1->SHAREDCTRLSET[0] = SYSCTL1_SHAREDCTRLSET_SHAREDSCKSEL(1) |
293 				SYSCTL1_SHAREDCTRLSET_SHAREDWSSEL(1);
294 #endif
295 	/* Set Receive I2S - Flexcomm 1 SCK, WS from shared signal set 0 */
296 	SYSCTL1->FCCTRLSEL[1] = SYSCTL1_FCCTRLSEL_SCKINSEL(1) |
297 				SYSCTL1_FCCTRLSEL_WSINSEL(1);
298 	/* Set Transmit I2S - Flexcomm 3 SCK, WS from shared signal set 0 */
299 	SYSCTL1->FCCTRLSEL[3] = SYSCTL1_FCCTRLSEL_SCKINSEL(1) |
300 				SYSCTL1_FCCTRLSEL_WSINSEL(1);
301 #ifdef CONFIG_I2S_TEST_SEPARATE_DEVICES
302 	/* Select Receive I2S - Flexcomm 1 Data in from shared signal set 0 */
303 	SYSCTL1->FCCTRLSEL[1] |= SYSCTL1_FCCTRLSEL_DATAINSEL(1);
304 	/* Select Transmit I2S - Flexcomm 3 Data out to shared signal set 0 */
305 	SYSCTL1->FCCTRLSEL[3] |= SYSCTL1_FCCTRLSEL_DATAOUTSEL(1);
306 #endif /* CONFIG_I2S_TEST_SEPARATE_DEVICES */
307 #endif /* CONFIG_I2S */
308 
309 
310 #ifdef CONFIG_REBOOT
311 	/*
312 	 * The sys_reboot API calls NVIC_SystemReset. On the RT595, the warm
313 	 * reset will not complete correctly unless the ROM toggles the
314 	 * flash reset pin. We can control this behavior using the OTP shadow
315 	 * register for OPT word BOOT_CFG1
316 	 *
317 	 * Set FLEXSPI_RESET_PIN_ENABLE=1, FLEXSPI_RESET_PIN= PIO4_5
318 	 */
319 	 OCOTP0->OTP_SHADOW[97] = 0x164000;
320 #endif /* CONFIG_REBOOT */
321 
322 	/* Read 192M FRO clock Trim settings from fuses.
323 	 * NOTE: Reading OTP fuses requires a VDDCORE voltage of at least 1.0V
324 	 */
325 	OTP_FUSE_READ_API(FRO_192MHZ_SC_TRIM, &sc_trim_192);
326 	OTP_FUSE_READ_API(FRO_192MHZ_RD_TRIM, &rd_trim_192);
327 
328 	/* Read 96M FRO clock Trim settings from fuses. */
329 	OTP_FUSE_READ_API(FRO_96MHZ_SC_TRIM, &sc_trim_96);
330 	OTP_FUSE_READ_API(FRO_96MHZ_RD_TRIM, &rd_trim_96);
331 
332 	/* Check if the 96MHz fuses have been programmed.
333 	 * Production devices have 96M trim values programmed in OTP fuses.
334 	 * However, older EVKs may have pre-production silicon.
335 	 */
336 	if ((rd_trim_96 == 0) && (sc_trim_96 == 0)) {
337 		/* If not programmed then use software to calculate the trim values */
338 		CLOCK_FroTuneToFreq(96000000u);
339 		rd_trim_96 = CLKCTL0->FRO_RDTRIM;
340 		sc_trim_96 = sc_trim_192;
341 	}
342 
343 	return 0;
344 }
345 
346 
347 #ifdef CONFIG_LV_Z_VBD_CUSTOM_SECTION
348 extern char __flexspi2_start[];
349 extern char __flexspi2_end[];
350 
init_psram_framebufs(void)351 static int init_psram_framebufs(void)
352 {
353 	/*
354 	 * Framebuffers will be stored in PSRAM, within FlexSPI2 linker
355 	 * section. Zero out BSS section.
356 	 */
357 	memset(__flexspi2_start, 0, __flexspi2_end - __flexspi2_start);
358 	return 0;
359 }
360 
361 #endif /* CONFIG_LV_Z_VBD_CUSTOM_SECTION */
362 
363 #if CONFIG_REGULATOR
364 /* PMIC setup is dependent on the regulator API */
365 SYS_INIT(board_config_pmic, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY);
366 #endif
367 
368 #ifdef CONFIG_LV_Z_VBD_CUSTOM_SECTION
369 /* Framebuffers should be setup after PSRAM is initialized but before
370  * Graphics framework init
371  */
372 SYS_INIT(init_psram_framebufs, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY);
373 #endif
374 
375 SYS_INIT(mimxrt595_evk_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY);
376