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 */ 7 8#include <asm/arch/clock.h> 9#include <asm/arch/ddr.h> 10#include <asm/arch/mu.h> 11#include <asm/arch/sys_proto.h> 12#include <asm/arch/trdc.h> 13#include <asm/mach-imx/boot_mode.h> 14#include <asm/mach-imx/ele_api.h> 15#include <asm/sections.h> 16#include <hang.h> 17#include <init.h> 18#include <log.h> 19#include <power/pmic.h> 20#include <power/pca9450.h> 21#include <spl.h> 22 23DECLARE_GLOBAL_DATA_PTR; 24 25/* 26 * Will be part of drivers/power/regulator/pca9450.c 27 * when pca9451a support is added. 28 */ 29#define PCA9450_REG_PWRCTRL_TOFF_DEB BIT(5) 30 31int spl_board_boot_device(enum boot_device boot_dev_spl) 32{ 33 return BOOT_DEVICE_BOOTROM; 34} 35 36void spl_board_init(void) 37{ 38 int ret; 39 40 ret = ele_start_rng(); 41 if (ret) 42 printf("Fail to start RNG: %d\n", ret); 43 44 puts("Normal Boot\n"); 45} 46 47void spl_dram_init(void) 48{ 49 ddr_init(&dram_timing); 50} 51 52int power_init_board(void) 53{ 54 struct udevice *dev; 55 int ret; 56 unsigned int val = 0; 57 58 ret = pmic_get("pmic@25", &dev); 59 if (ret == -ENODEV) { 60 puts("No pca9450@25\n"); 61 return 0; 62 } 63 64 if (ret != 0) 65 return ret; 66 67 /* BUCKxOUT_DVS0/1 control BUCK123 output */ 68 pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29); 69 70 /* enable DVS control through PMIC_STBY_REQ */ 71 pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59); 72 73 ret = pmic_reg_read(dev, PCA9450_PWR_CTRL); 74 if (ret < 0) 75 return ret; 76 val = ret; 77 78 if (IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)) { 79 /* 0.8v for Low drive mode */ 80 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) { 81 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x0c); 82 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x0c); 83 } else { 84 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x10); 85 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x10); 86 } 87 } else { 88 /* 0.9v for Over drive mode */ 89 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) { 90 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x14); 91 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x14); 92 } else { 93 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, 0x18); 94 pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, 0x18); 95 } 96 } 97 98 /* set standby voltage to 0.65v */ 99 if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) 100 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x0); 101 else 102 pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x4); 103 104 /* I2C_LT_EN*/ 105 pmic_reg_write(dev, 0xa, 0x3); 106 107 return 0; 108} 109 110void board_init_f(ulong dummy) 111{ 112 int ret; 113 114 /* Clear the BSS. */ 115 memset(__bss_start, 0, __bss_end - __bss_start); 116 117 timer_init(); 118 119 arch_cpu_init(); 120 121 spl_early_init(); 122 123 preloader_console_init(); 124 125 ret = imx9_probe_mu(); 126 if (ret) { 127 printf("Fail to init ELE API\n"); 128 } else { 129 debug("SOC: 0x%x\n", gd->arch.soc_rev); 130 debug("LC: 0x%x\n", gd->arch.lifecycle); 131 } 132 133 clock_init(); 134 135 power_init_board(); 136 137 if (!IS_ENABLED(CONFIG_IMX9_LOW_DRIVE_MODE)) 138 set_arm_core_max_clk(); 139 140 /* Init power of mix */ 141 soc_power_init(); 142 143 /* Setup TRDC for DDR access */ 144 trdc_init(); 145 146 /* DDR initialization */ 147 spl_dram_init(); 148 149 /* Put M33 into CPUWAIT for following kick */ 150 ret = m33_prepare(); 151 if (!ret) 152 printf("M33 prepare ok\n"); 153 154 board_init_r(NULL, 0); 155} 156