1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2025 NXP
4 */
5
6 #include "lpddr4_timing.h"
7
8 #include <init.h>
9 #include <spl.h>
10 #include <asm/arch/clock.h>
11 #include <asm/arch/ddr.h>
12 #include <asm/arch/mu.h>
13 #include <asm/arch/sys_proto.h>
14 #include <asm/arch/trdc.h>
15 #include <asm/mach-imx/boot_mode.h>
16 #include <asm/mach-imx/ele_api.h>
17 #include <asm/global_data.h>
18 #include <asm/sections.h>
19 #include <dm/device.h>
20 #include <dm/device-internal.h>
21 #include <dm/uclass.h>
22 #include <dm/uclass-internal.h>
23 #include <linux/delay.h>
24 #include <power/pca9450.h>
25 #include <power/pmic.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 #define SRC_DDRC_SW_CTRL (0x44461020)
30 #define SRC_DDRPHY_SINGLE_RESET_SW_CTRL (0x44461424)
31
32 static struct _drams {
33 u8 mr8;
34 struct dram_timing_info *pdram_timing;
35 char *name;
36 } frdm_drams[2] = {
37 {0x10, &dram_timing_1GB, "1GB DRAM" },
38 {0x18, &dram_timing_2GB, "2GB DRAM" },
39 };
40
spl_board_boot_device(enum boot_device boot_dev_spl)41 int spl_board_boot_device(enum boot_device boot_dev_spl)
42 {
43 return BOOT_DEVICE_BOOTROM;
44 }
45
spl_board_init(void)46 void spl_board_init(void)
47 {
48 int ret;
49
50 ret = ele_start_rng();
51 if (ret)
52 printf("Fail to start RNG: %d\n", ret);
53
54 puts("Normal Boot\n");
55 }
56
spl_dram_init(void)57 void spl_dram_init(void)
58 {
59 int i;
60 int ret;
61
62 for (i = 0; i < ARRAY_SIZE(frdm_drams); i++) {
63 struct dram_timing_info *ptiming = frdm_drams[i].pdram_timing;
64
65 printf("DDR: %uMTS\n", ptiming->fsp_msg[0].drate);
66 ret = ddr_init(ptiming);
67 if (ret == 0) {
68 if (lpddr4_mr_read(1, 8) == frdm_drams[i].mr8) {
69 printf("found DRAM %s matched\n", frdm_drams[i].name);
70 break;
71 }
72
73 /* Power down and Power up DDR Mixer */
74
75 /* Clear PwrOkIn via DDRMIX register */
76 setbits_32(SRC_DDRPHY_SINGLE_RESET_SW_CTRL, BIT(0));
77 /* Power off the DDRMIX */
78 setbits_32(SRC_DDRC_SW_CTRL, BIT(31));
79
80 udelay(50);
81
82 /* Power up the DDRMIX */
83 clrbits_32(SRC_DDRC_SW_CTRL, BIT(31));
84 setbits_32(SRC_DDRC_SW_CTRL, BIT(0));
85 udelay(10);
86 clrbits_32(SRC_DDRC_SW_CTRL, BIT(0));
87 udelay(10);
88 }
89 }
90 }
91
power_init_board(void)92 int power_init_board(void)
93 {
94 struct udevice *dev;
95 int ret;
96 unsigned int val = 0, buck_val;
97
98 ret = pmic_get("pmic@25", &dev);
99 if (ret == -ENODEV) {
100 puts("No pca9450@25\n");
101 return 0;
102 }
103 if (ret != 0)
104 return ret;
105
106 /* BUCKxOUT_DVS0/1 control BUCK123 output */
107 pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29);
108
109 /* Enable DVS control through PMIC_STBY_REQ */
110 pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59);
111
112 ret = pmic_reg_read(dev, PCA9450_PWR_CTRL);
113 if (ret < 0)
114 return ret;
115
116 val = ret;
117
118 if (is_voltage_mode(VOLT_LOW_DRIVE)) {
119 buck_val = 0x0c; /* 0.8V for Low drive mode */
120 printf("PMIC: Low Drive Voltage Mode\n");
121 } else if (is_voltage_mode(VOLT_NOMINAL_DRIVE)) {
122 buck_val = 0x10; /* 0.85V for Nominal drive mode */
123 printf("PMIC: Nominal Voltage Mode\n");
124 } else {
125 buck_val = 0x14; /* 0.9V for Over drive mode */
126 printf("PMIC: Over Drive Voltage Mode\n");
127 }
128
129 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) {
130 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, buck_val);
131 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, buck_val);
132 } else {
133 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, buck_val + 0x4);
134 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, buck_val + 0x4);
135 }
136
137 /* Set standby voltage to 0.65V */
138 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB)
139 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x0);
140 else
141 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x4);
142
143 /* I2C_LT_EN*/
144 pmic_reg_write(dev, 0xa, 0x3);
145 return 0;
146 }
147
board_init_f(ulong dummy)148 void board_init_f(ulong dummy)
149 {
150 int ret;
151
152 /* Clear the BSS. */
153 memset(__bss_start, 0, __bss_end - __bss_start);
154
155 timer_init();
156
157 arch_cpu_init();
158
159 board_early_init_f();
160
161 spl_early_init();
162
163 preloader_console_init();
164
165 ret = imx9_probe_mu();
166 if (ret) {
167 printf("Fail to init Sentinel API\n");
168 } else {
169 debug("SOC: 0x%x\n", gd->arch.soc_rev);
170 debug("LC: 0x%x\n", gd->arch.lifecycle);
171 }
172
173 clock_init_late();
174
175 power_init_board();
176
177 if (!is_voltage_mode(VOLT_LOW_DRIVE))
178 set_arm_clk(get_cpu_speed_grade_hz());
179
180 /* Init power of mix */
181 soc_power_init();
182
183 /* Setup TRDC for DDR access */
184 trdc_init();
185
186 /* DDR initialization */
187 spl_dram_init();
188
189 /* Put M33 into CPUWAIT for following kick */
190 ret = m33_prepare();
191 if (!ret)
192 printf("M33 prepare ok\n");
193
194 board_init_r(NULL, 0);
195 }
196