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