1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3 * Copyright (C) 2023 PHYTEC Messtechnik GmbH
4 * Author: Christoph Stoidner <c.stoidner@phytec.de>
5 * Copyright (C) 2024 Mathieu Othacehe <m.othacehe@gmail.com>
6 * Copyright (C) 2024 PHYTEC Messtechnik GmbH
7 */
8
9 #include <asm/arch/clock.h>
10 #include <asm/arch/ddr.h>
11 #include <asm/arch/mu.h>
12 #include <asm/arch/sys_proto.h>
13 #include <asm/arch/trdc.h>
14 #include <asm/mach-imx/boot_mode.h>
15 #include <asm/mach-imx/ele_api.h>
16 #include <asm/sections.h>
17 #include <init.h>
18 #include <power/pmic.h>
19 #include <power/pca9450.h>
20 #include <spl.h>
21
22 #include "../common/imx93_som_detection.h"
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 #define EEPROM_ADDR 0x50
27
28 /*
29 * Prototypes of automatically generated ram config file
30 */
31 void set_dram_timings_2gb_lpddr4x(void);
32 void set_dram_timings_1gb_lpddr4x_900mhz(void);
33
spl_board_boot_device(enum boot_device boot_dev_spl)34 int spl_board_boot_device(enum boot_device boot_dev_spl)
35 {
36 return BOOT_DEVICE_BOOTROM;
37 }
38
spl_board_init(void)39 void spl_board_init(void)
40 {
41 int ret;
42
43 ret = ele_start_rng();
44 if (ret)
45 printf("Fail to start RNG: %d\n", ret);
46
47 puts("Normal Boot\n");
48 }
49
spl_dram_init(void)50 void spl_dram_init(void)
51 {
52 int ret;
53 enum phytec_imx93_ddr_eeprom_code ddr_opt = PHYTEC_IMX93_DDR_INVALID;
54
55 /* NOTE: In SPL lpi2c3 is mapped to bus 0 */
56 ret = phytec_eeprom_data_setup(NULL, 0, EEPROM_ADDR);
57 if (ret && !IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_FIX))
58 goto out;
59
60 ret = phytec_imx93_detect(NULL);
61 if (!ret)
62 phytec_print_som_info(NULL);
63
64 if (IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_FIX)) {
65 if (IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_LPDDR4X_1GB))
66 ddr_opt = PHYTEC_IMX93_LPDDR4X_1GB;
67 else if (IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_LPDDR4X_2GB))
68 ddr_opt = PHYTEC_IMX93_LPDDR4X_2GB;
69 } else {
70 ddr_opt = phytec_imx93_get_opt(NULL, PHYTEC_IMX93_OPT_DDR);
71 }
72
73 switch (ddr_opt) {
74 case PHYTEC_IMX93_LPDDR4X_1GB:
75 if (is_voltage_mode(VOLT_LOW_DRIVE))
76 set_dram_timings_1gb_lpddr4x_900mhz();
77 break;
78 case PHYTEC_IMX93_LPDDR4X_2GB:
79 set_dram_timings_2gb_lpddr4x();
80 break;
81 default:
82 goto out;
83 }
84 ddr_init(&dram_timing);
85 return;
86 out:
87 puts("Could not detect correct RAM type and size. Fall back to default.\n");
88 if (is_voltage_mode(VOLT_LOW_DRIVE))
89 set_dram_timings_1gb_lpddr4x_900mhz();
90 ddr_init(&dram_timing);
91 }
92
power_init_board(void)93 int power_init_board(void)
94 {
95 struct udevice *dev;
96 int ret;
97 unsigned int val = 0;
98
99 ret = pmic_get("pmic@25", &dev);
100 if (ret == -ENODEV) {
101 puts("No pca9450@25\n");
102 return 0;
103 }
104
105 if (ret != 0)
106 return ret;
107
108 /* BUCKxOUT_DVS0/1 control BUCK123 output */
109 pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29);
110
111 /* enable DVS control through PMIC_STBY_REQ */
112 pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59);
113
114 ret = pmic_reg_read(dev, PCA9450_PWR_CTRL);
115 if (ret < 0)
116 return ret;
117 val = ret;
118
119 if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)) {
120 /* 0.8v for Low drive mode */
121 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) {
122 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x0c);
123 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x0c);
124 } else {
125 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x10);
126 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x10);
127 }
128 } else {
129 /* 0.9v for Over drive mode */
130 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) {
131 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x14);
132 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x14);
133 } else {
134 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x18);
135 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x18);
136 }
137 }
138
139 /* set standby voltage to 0.65v */
140 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB)
141 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x0);
142 else
143 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x4);
144
145 /* I2C_LT_EN*/
146 pmic_reg_write(dev, 0xa, 0x3);
147
148 return 0;
149 }
150
board_init_f(ulong dummy)151 void board_init_f(ulong dummy)
152 {
153 int ret;
154
155 /* Clear the BSS. */
156 memset(__bss_start, 0, __bss_end - __bss_start);
157
158 timer_init();
159
160 arch_cpu_init();
161
162 spl_early_init();
163
164 preloader_console_init();
165
166 ret = imx9_probe_mu();
167 if (ret) {
168 printf("Fail to init ELE API\n");
169 } else {
170 debug("SOC: 0x%x\n", gd->arch.soc_rev);
171 debug("LC: 0x%x\n", gd->arch.lifecycle);
172 }
173
174 clock_init_late();
175
176 power_init_board();
177
178 if (!IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE))
179 set_arm_core_max_clk();
180
181 /* Init power of mix */
182 soc_power_init();
183
184 /* Setup TRDC for DDR access */
185 trdc_init();
186
187 /* DDR initialization */
188 spl_dram_init();
189
190 /* Put M33 into CPUWAIT for following kick */
191 ret = m33_prepare();
192 if (!ret)
193 printf("M33 prepare ok\n");
194
195 board_init_r(NULL, 0);
196 }
197