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