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, ¤t_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