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