1 /* 2 * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdlib.h> 8 9 #include <common/debug.h> 10 11 #include <ddrphy_phyinit.h> 12 13 /* 14 * Reads PhyInit inputs structures and sets relevant message block 15 * parameters. 16 * 17 * This function sets Message Block parameters based on user_input_basic and 18 * user_input_advanced. user changes in these files takes precedence 19 * over this function call. 20 * 21 * MessageBlock fields set : 22 * - dramtype 23 * - pstate 24 * - dramfreq 25 * - pllbypassen 26 * - dfifreqratio 27 * - phyodtimpedance 28 * - phydrvimpedance 29 * - bpznresval 30 * - enableddqscha (LPDDR4) 31 * - cspresentcha (LPDDR4) 32 * - enableddqsChb (LPDDR4) 33 * - cspresentchb (LPDDR4) 34 * - enableddqs (DDR3/DDR4) 35 * - phycfg (DDR3/DDR4) 36 * - x16present (DDR4) 37 * 38 * \return 0 on success. 39 */ 40 int ddrphy_phyinit_calcmb(struct stm32mp_ddr_config *config, struct pmu_smb_ddr_1d *mb_ddr_1d) 41 { 42 uint32_t nad0 = config->uib.numactivedbytedfi0; 43 uint32_t nad1 = 0; 44 uint16_t mr4 __maybe_unused; 45 uint16_t disableddbyte __maybe_unused; 46 uint32_t dbyte __maybe_unused; 47 int ret; 48 49 #if STM32MP_LPDDR4_TYPE 50 nad1 = config->uib.numactivedbytedfi1; 51 #endif /* STM32MP_LPDDR4_TYPE */ 52 53 /* A few checks to make sure valid programming */ 54 if ((nad0 == 0U) || (config->uib.numdbyte == 0U)) { 55 ERROR("%s %d\n", __func__, __LINE__); 56 VERBOSE("%s numactivedbytedfi0, numactivedbytedfi0, NumByte out of range.\n", 57 __func__); 58 return -1; 59 } 60 61 if ((nad0 + nad1) > config->uib.numdbyte) { 62 ERROR("%s %d\n", __func__, __LINE__); 63 VERBOSE("%s numactivedbytedfi0+numactivedbytedfi1 is larger than numdbyteDfi0\n", 64 __func__); 65 return -1; 66 } 67 68 if ((config->uib.dfi1exists == 0U) && (nad1 != 0U)) { 69 ERROR("%s %d\n", __func__, __LINE__); 70 VERBOSE("%s dfi1exists==0 but numdbyteDfi0 != 0\n", __func__); 71 return -1; 72 } 73 74 #if STM32MP_DDR4_TYPE 75 /* OR all mr4 masked values, to help check in next loop */ 76 mr4 = mb_ddr_1d->mr4 & 0x1C0U; 77 78 /* 1D message block defaults */ 79 if (mr4 != 0x0U) { 80 ERROR("mr4 != 0x0\n"); 81 VERBOSE("%s Setting DRAM CAL mode is not supported by the PHY.\n", __func__); 82 VERBOSE("Memory controller may set CAL mode after PHY has entered mission\n"); 83 VERBOSE("mode. Please check value programmed in mb_ddr_1d[*].mr4\n"); 84 VERBOSE("and unset A8:6\n"); 85 return -1; 86 } 87 #endif /* STM32MP_DDR4_TYPE */ 88 89 #if STM32MP_DDR3_TYPE 90 if (config->uib.dimmtype == DDR_DIMMTYPE_NODIMM) { 91 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DRAMTYPE, 0x1U); 92 if (ret != 0) { 93 return ret; 94 } 95 } 96 #elif STM32MP_DDR4_TYPE 97 if (config->uib.dimmtype == DDR_DIMMTYPE_NODIMM) { 98 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DRAMTYPE, 0x2U); 99 if (ret != 0) { 100 return ret; 101 } 102 } 103 #else /* STM32MP_LPDDR4_TYPE */ 104 /* Nothing to do */ 105 #endif /* STM32MP_DDR3_TYPE */ 106 107 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PSTATE, 0U); 108 if (ret != 0) { 109 return ret; 110 } 111 112 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DRAMFREQ, config->uib.frequency * 2U); 113 if (ret != 0) { 114 return ret; 115 } 116 117 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PLLBYPASSEN, config->uib.pllbypass); 118 if (ret != 0) { 119 return ret; 120 } 121 122 if (config->uib.dfifreqratio == 1U) { 123 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DFIFREQRATIO, 0x2U); 124 if (ret != 0) { 125 return ret; 126 } 127 } 128 129 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYODTIMPEDANCE, 0U); 130 if (ret != 0) { 131 return ret; 132 } 133 134 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYDRVIMPEDANCE, 0U); 135 if (ret != 0) { 136 return ret; 137 } 138 139 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_BPZNRESVAL, 0U); 140 if (ret != 0) { 141 return ret; 142 } 143 144 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE 145 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_ENABLEDDQS, nad0 * 8U); 146 if (ret != 0) { 147 return ret; 148 } 149 150 disableddbyte = 0x0U; 151 152 for (dbyte = 0U; (dbyte < config->uib.numdbyte) && (dbyte < 8U); dbyte++) { 153 if (ddrphy_phyinit_isdbytedisabled(config, mb_ddr_1d, dbyte) != 0) { 154 disableddbyte |= 0x1U << dbyte; 155 } 156 } 157 158 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_DISABLEDDBYTE, disableddbyte); 159 if (ret != 0) { 160 return ret; 161 } 162 163 #if STM32MP_DDR3_TYPE 164 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYCFG, config->uia.is2ttiming); 165 if (ret != 0) { 166 return ret; 167 } 168 #else /* STM32MP_DDR4_TYPE */ 169 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_PHYCFG, 170 ((mb_ddr_1d->mr3 & 0x8U) != 0U) ? 171 0U : config->uia.is2ttiming); 172 if (ret != 0) { 173 return ret; 174 } 175 176 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_X16PRESENT, 177 (config->uib.dramdatawidth == 0x10U) ? 178 mb_ddr_1d->cspresent : 0x0U); 179 if (ret != 0) { 180 return ret; 181 } 182 #endif /* STM32MP_DDR3_TYPE */ 183 #else /* STM32MP_LPDDR4_TYPE */ 184 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_ENABLEDDQSCHA, nad0 * 8U); 185 if (ret != 0) { 186 return ret; 187 } 188 189 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_CSPRESENTCHA, 190 (config->uib.numrank_dfi0 == 2U) ? 191 0x3U : config->uib.numrank_dfi0); 192 if (ret != 0) { 193 return ret; 194 } 195 196 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_ENABLEDDQSCHB, nad1 * 8U); 197 if (ret != 0) { 198 return ret; 199 } 200 201 ret = ddrphy_phyinit_softsetmb(mb_ddr_1d, MB_FIELD_CSPRESENTCHB, 202 (config->uib.numrank_dfi1 == 2U) ? 203 0x3U : config->uib.numrank_dfi1); 204 if (ret != 0) { 205 return ret; 206 } 207 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */ 208 209 return 0; 210 } 211