1*e2d6e5e2SPascal Paillet /* 2*e2d6e5e2SPascal Paillet * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved 3*e2d6e5e2SPascal Paillet * 4*e2d6e5e2SPascal Paillet * SPDX-License-Identifier: BSD-3-Clause 5*e2d6e5e2SPascal Paillet */ 6*e2d6e5e2SPascal Paillet 7*e2d6e5e2SPascal Paillet #include <assert.h> 8*e2d6e5e2SPascal Paillet #include <errno.h> 9*e2d6e5e2SPascal Paillet #include <stdint.h> 10*e2d6e5e2SPascal Paillet 11*e2d6e5e2SPascal Paillet #include <common/fdt_wrappers.h> 12*e2d6e5e2SPascal Paillet #include <drivers/delay_timer.h> 13*e2d6e5e2SPascal Paillet #include <drivers/st/regulator.h> 14*e2d6e5e2SPascal Paillet #include <drivers/st/stm32mp_ddr.h> 15*e2d6e5e2SPascal Paillet 16*e2d6e5e2SPascal Paillet #include <libfdt.h> 17*e2d6e5e2SPascal Paillet #include <platform_def.h> 18*e2d6e5e2SPascal Paillet 19*e2d6e5e2SPascal Paillet #if STM32MP_DDR3_TYPE 20*e2d6e5e2SPascal Paillet struct ddr3_supply { 21*e2d6e5e2SPascal Paillet struct rdev *vdd; 22*e2d6e5e2SPascal Paillet struct rdev *vref; 23*e2d6e5e2SPascal Paillet struct rdev *vtt; 24*e2d6e5e2SPascal Paillet }; 25*e2d6e5e2SPascal Paillet 26*e2d6e5e2SPascal Paillet static void ddr3_supply_read(void *fdt, int node, struct ddr3_supply *supply) 27*e2d6e5e2SPascal Paillet { 28*e2d6e5e2SPascal Paillet supply->vdd = regulator_get_by_supply_name(fdt, node, "vdd"); 29*e2d6e5e2SPascal Paillet supply->vref = regulator_get_by_supply_name(fdt, node, "vref"); 30*e2d6e5e2SPascal Paillet supply->vtt = regulator_get_by_supply_name(fdt, node, "vtt"); 31*e2d6e5e2SPascal Paillet } 32*e2d6e5e2SPascal Paillet 33*e2d6e5e2SPascal Paillet static int ddr_power_init(void *fdt, int node) 34*e2d6e5e2SPascal Paillet { 35*e2d6e5e2SPascal Paillet int status; 36*e2d6e5e2SPascal Paillet struct ddr3_supply supply; 37*e2d6e5e2SPascal Paillet 38*e2d6e5e2SPascal Paillet ddr3_supply_read(fdt, node, &supply); 39*e2d6e5e2SPascal Paillet if ((supply.vdd == NULL) || (supply.vref == NULL) || (supply.vtt == NULL)) { 40*e2d6e5e2SPascal Paillet return -ENOENT; 41*e2d6e5e2SPascal Paillet } 42*e2d6e5e2SPascal Paillet 43*e2d6e5e2SPascal Paillet /* 44*e2d6e5e2SPascal Paillet * DDR3 power on sequence is: 45*e2d6e5e2SPascal Paillet * enable VREF_DDR, VTT_DDR, VPP_DDR 46*e2d6e5e2SPascal Paillet */ 47*e2d6e5e2SPascal Paillet status = regulator_set_min_voltage(supply.vdd); 48*e2d6e5e2SPascal Paillet if (status != 0) { 49*e2d6e5e2SPascal Paillet return status; 50*e2d6e5e2SPascal Paillet } 51*e2d6e5e2SPascal Paillet 52*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vdd); 53*e2d6e5e2SPascal Paillet if (status != 0) { 54*e2d6e5e2SPascal Paillet return status; 55*e2d6e5e2SPascal Paillet } 56*e2d6e5e2SPascal Paillet 57*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vref); 58*e2d6e5e2SPascal Paillet if (status != 0) { 59*e2d6e5e2SPascal Paillet return status; 60*e2d6e5e2SPascal Paillet } 61*e2d6e5e2SPascal Paillet 62*e2d6e5e2SPascal Paillet return regulator_enable(supply.vtt); 63*e2d6e5e2SPascal Paillet } 64*e2d6e5e2SPascal Paillet #endif /* STM32MP_DDR3_TYPE */ 65*e2d6e5e2SPascal Paillet 66*e2d6e5e2SPascal Paillet #if STM32MP_DDR4_TYPE 67*e2d6e5e2SPascal Paillet struct ddr4_supply { 68*e2d6e5e2SPascal Paillet struct rdev *vdd; 69*e2d6e5e2SPascal Paillet struct rdev *vref; 70*e2d6e5e2SPascal Paillet struct rdev *vtt; 71*e2d6e5e2SPascal Paillet struct rdev *vpp; 72*e2d6e5e2SPascal Paillet }; 73*e2d6e5e2SPascal Paillet 74*e2d6e5e2SPascal Paillet static void ddr4_supply_read(void *fdt, int node, struct ddr4_supply *supply) 75*e2d6e5e2SPascal Paillet { 76*e2d6e5e2SPascal Paillet supply->vpp = regulator_get_by_supply_name(fdt, node, "vpp"); 77*e2d6e5e2SPascal Paillet supply->vdd = regulator_get_by_supply_name(fdt, node, "vdd"); 78*e2d6e5e2SPascal Paillet supply->vref = regulator_get_by_supply_name(fdt, node, "vref"); 79*e2d6e5e2SPascal Paillet supply->vtt = regulator_get_by_supply_name(fdt, node, "vtt"); 80*e2d6e5e2SPascal Paillet } 81*e2d6e5e2SPascal Paillet 82*e2d6e5e2SPascal Paillet static int ddr_power_init(void *fdt, int node) 83*e2d6e5e2SPascal Paillet { 84*e2d6e5e2SPascal Paillet int status; 85*e2d6e5e2SPascal Paillet struct ddr4_supply supply; 86*e2d6e5e2SPascal Paillet 87*e2d6e5e2SPascal Paillet ddr4_supply_read(fdt, node, &supply); 88*e2d6e5e2SPascal Paillet if ((supply.vpp == NULL) || (supply.vdd == NULL) || (supply.vref == NULL) || 89*e2d6e5e2SPascal Paillet (supply.vtt == NULL)) { 90*e2d6e5e2SPascal Paillet return -ENOENT; 91*e2d6e5e2SPascal Paillet } 92*e2d6e5e2SPascal Paillet 93*e2d6e5e2SPascal Paillet /* 94*e2d6e5e2SPascal Paillet * DDR4 power on sequence is: 95*e2d6e5e2SPascal Paillet * enable VPP_DDR 96*e2d6e5e2SPascal Paillet * enable VREF_DDR, VTT_DDR, VPP_DDR 97*e2d6e5e2SPascal Paillet */ 98*e2d6e5e2SPascal Paillet status = regulator_set_min_voltage(supply.vpp); 99*e2d6e5e2SPascal Paillet if (status != 0) { 100*e2d6e5e2SPascal Paillet return status; 101*e2d6e5e2SPascal Paillet } 102*e2d6e5e2SPascal Paillet 103*e2d6e5e2SPascal Paillet status = regulator_set_min_voltage(supply.vdd); 104*e2d6e5e2SPascal Paillet if (status != 0) { 105*e2d6e5e2SPascal Paillet return status; 106*e2d6e5e2SPascal Paillet } 107*e2d6e5e2SPascal Paillet 108*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vpp); 109*e2d6e5e2SPascal Paillet if (status != 0) { 110*e2d6e5e2SPascal Paillet return status; 111*e2d6e5e2SPascal Paillet } 112*e2d6e5e2SPascal Paillet 113*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vdd); 114*e2d6e5e2SPascal Paillet if (status != 0) { 115*e2d6e5e2SPascal Paillet return status; 116*e2d6e5e2SPascal Paillet } 117*e2d6e5e2SPascal Paillet 118*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vref); 119*e2d6e5e2SPascal Paillet if (status != 0) { 120*e2d6e5e2SPascal Paillet return status; 121*e2d6e5e2SPascal Paillet } 122*e2d6e5e2SPascal Paillet 123*e2d6e5e2SPascal Paillet return regulator_enable(supply.vtt); 124*e2d6e5e2SPascal Paillet } 125*e2d6e5e2SPascal Paillet #endif /* STM32MP_DDR4_TYPE */ 126*e2d6e5e2SPascal Paillet 127*e2d6e5e2SPascal Paillet #if STM32MP_LPDDR4_TYPE 128*e2d6e5e2SPascal Paillet struct lpddr4_supply { 129*e2d6e5e2SPascal Paillet struct rdev *vdd1; 130*e2d6e5e2SPascal Paillet struct rdev *vdd2; 131*e2d6e5e2SPascal Paillet struct rdev *vddq; 132*e2d6e5e2SPascal Paillet }; 133*e2d6e5e2SPascal Paillet 134*e2d6e5e2SPascal Paillet static void lpddr4_supply_read(void *fdt, int node, struct lpddr4_supply *supply) 135*e2d6e5e2SPascal Paillet { 136*e2d6e5e2SPascal Paillet supply->vdd1 = regulator_get_by_supply_name(fdt, node, "vdd1"); 137*e2d6e5e2SPascal Paillet supply->vdd2 = regulator_get_by_supply_name(fdt, node, "vdd2"); 138*e2d6e5e2SPascal Paillet supply->vddq = regulator_get_by_supply_name(fdt, node, "vddq"); 139*e2d6e5e2SPascal Paillet } 140*e2d6e5e2SPascal Paillet 141*e2d6e5e2SPascal Paillet static int ddr_power_init(void *fdt, int node) 142*e2d6e5e2SPascal Paillet { 143*e2d6e5e2SPascal Paillet int status; 144*e2d6e5e2SPascal Paillet struct lpddr4_supply supply; 145*e2d6e5e2SPascal Paillet 146*e2d6e5e2SPascal Paillet lpddr4_supply_read(fdt, node, &supply); 147*e2d6e5e2SPascal Paillet if ((supply.vdd1 == NULL) || (supply.vdd2 == NULL) || (supply.vddq == NULL)) { 148*e2d6e5e2SPascal Paillet return -ENOENT; 149*e2d6e5e2SPascal Paillet } 150*e2d6e5e2SPascal Paillet 151*e2d6e5e2SPascal Paillet /* 152*e2d6e5e2SPascal Paillet * LPDDR4 power on sequence is: 153*e2d6e5e2SPascal Paillet * enable VDD1_DDR 154*e2d6e5e2SPascal Paillet * enable VDD2_DDR 155*e2d6e5e2SPascal Paillet * enable VDDQ_DDR 156*e2d6e5e2SPascal Paillet */ 157*e2d6e5e2SPascal Paillet status = regulator_set_min_voltage(supply.vdd1); 158*e2d6e5e2SPascal Paillet if (status != 0) { 159*e2d6e5e2SPascal Paillet return status; 160*e2d6e5e2SPascal Paillet } 161*e2d6e5e2SPascal Paillet 162*e2d6e5e2SPascal Paillet status = regulator_set_min_voltage(supply.vdd2); 163*e2d6e5e2SPascal Paillet if (status != 0) { 164*e2d6e5e2SPascal Paillet return status; 165*e2d6e5e2SPascal Paillet } 166*e2d6e5e2SPascal Paillet 167*e2d6e5e2SPascal Paillet status = regulator_set_min_voltage(supply.vddq); 168*e2d6e5e2SPascal Paillet if (status != 0) { 169*e2d6e5e2SPascal Paillet return status; 170*e2d6e5e2SPascal Paillet } 171*e2d6e5e2SPascal Paillet 172*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vdd1); 173*e2d6e5e2SPascal Paillet if (status != 0) { 174*e2d6e5e2SPascal Paillet return status; 175*e2d6e5e2SPascal Paillet } 176*e2d6e5e2SPascal Paillet 177*e2d6e5e2SPascal Paillet status = regulator_enable(supply.vdd2); 178*e2d6e5e2SPascal Paillet if (status != 0) { 179*e2d6e5e2SPascal Paillet return status; 180*e2d6e5e2SPascal Paillet } 181*e2d6e5e2SPascal Paillet 182*e2d6e5e2SPascal Paillet return regulator_enable(supply.vddq); 183*e2d6e5e2SPascal Paillet } 184*e2d6e5e2SPascal Paillet #endif /* STM32MP_LPDDR4_TYPE */ 185*e2d6e5e2SPascal Paillet 186*e2d6e5e2SPascal Paillet int stm32mp_board_ddr_power_init(enum ddr_type ddr_type) 187*e2d6e5e2SPascal Paillet { 188*e2d6e5e2SPascal Paillet void *fdt = NULL; 189*e2d6e5e2SPascal Paillet int node; 190*e2d6e5e2SPascal Paillet 191*e2d6e5e2SPascal Paillet VERBOSE("DDR power init, ddr_type = %u\n", ddr_type); 192*e2d6e5e2SPascal Paillet 193*e2d6e5e2SPascal Paillet #if STM32MP_DDR3_TYPE 194*e2d6e5e2SPascal Paillet assert(ddr_type == STM32MP_DDR3); 195*e2d6e5e2SPascal Paillet #elif STM32MP_DDR4_TYPE 196*e2d6e5e2SPascal Paillet assert(ddr_type == STM32MP_DDR4); 197*e2d6e5e2SPascal Paillet #elif STM32MP_LPDDR4_TYPE 198*e2d6e5e2SPascal Paillet assert(ddr_type == STM32MP_LPDDR4); 199*e2d6e5e2SPascal Paillet #else 200*e2d6e5e2SPascal Paillet ERROR("DDR type (%u) not supported\n", ddr_type); 201*e2d6e5e2SPascal Paillet panic(); 202*e2d6e5e2SPascal Paillet #endif 203*e2d6e5e2SPascal Paillet 204*e2d6e5e2SPascal Paillet if (fdt_get_address(&fdt) == 0) { 205*e2d6e5e2SPascal Paillet return -FDT_ERR_NOTFOUND; 206*e2d6e5e2SPascal Paillet } 207*e2d6e5e2SPascal Paillet 208*e2d6e5e2SPascal Paillet node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 209*e2d6e5e2SPascal Paillet if (node < 0) { 210*e2d6e5e2SPascal Paillet ERROR("%s: Cannot read DDR node in DT\n", __func__); 211*e2d6e5e2SPascal Paillet return -EINVAL; 212*e2d6e5e2SPascal Paillet } 213*e2d6e5e2SPascal Paillet 214*e2d6e5e2SPascal Paillet return ddr_power_init(fdt, node); 215*e2d6e5e2SPascal Paillet } 216