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 #include <string.h> 9 10 #include <common/debug.h> 11 12 #include <ddrphy_phyinit.h> 13 14 /* 15 * Maps impedance values to register settings 16 * 17 * Reads the pull-up/pull-down driver impedance from drvstren_ohm input 18 * and encodes that value for the CSR field specified in targetcsr input, 19 * based on DDR protocol. 20 * 21 * @param[in] drvstren_ohm drive strenght / ODT impedance in Ohms 22 * 23 * @param[in] targetcsr Target CSR for the impedance value. on of following 24 * enum drvtype: 25 * - DRVSTRENFSDQP 26 * - DRVSTRENFSDQN 27 * - ODTSTRENP 28 * - ODTSTRENN 29 * - ADRVSTRENP 30 * - ADRVSTRENN 31 * 32 * \return >=0 value on success, else negative. 33 */ 34 int ddrphy_phyinit_mapdrvstren(uint32_t drvstren_ohm, enum drvtype targetcsr) 35 { 36 int stren_setting = -1; 37 38 if ((targetcsr == DRVSTRENFSDQP) || (targetcsr == DRVSTRENFSDQN)) { 39 if (drvstren_ohm == 0U) { 40 stren_setting = 0x00; /* High-impedance */ 41 } else if (drvstren_ohm < 29U) { 42 stren_setting = 0x3f; 43 } else if (drvstren_ohm < 31U) { 44 stren_setting = 0x3e; 45 } else if (drvstren_ohm < 33U) { 46 stren_setting = 0x3b; 47 } else if (drvstren_ohm < 35U) { 48 stren_setting = 0x3a; 49 } else if (drvstren_ohm < 38U) { 50 stren_setting = 0x39; 51 } else if (drvstren_ohm < 41U) { 52 stren_setting = 0x38; 53 } else if (drvstren_ohm < 45U) { 54 stren_setting = 0x1b; 55 } else if (drvstren_ohm < 50U) { 56 stren_setting = 0x1a; 57 } else if (drvstren_ohm < 56U) { 58 stren_setting = 0x19; 59 } else if (drvstren_ohm < 64U) { 60 stren_setting = 0x18; 61 } else if (drvstren_ohm < 74U) { 62 stren_setting = 0x0b; 63 } else if (drvstren_ohm < 88U) { 64 stren_setting = 0x0a; 65 } else if (drvstren_ohm < 108U) { 66 stren_setting = 0x09; 67 } else if (drvstren_ohm < 140U) { 68 stren_setting = 0x08; 69 } else if (drvstren_ohm < 200U) { 70 stren_setting = 0x03; 71 } else if (drvstren_ohm < 360U) { 72 stren_setting = 0x02; 73 } else if (drvstren_ohm < 481U) { 74 stren_setting = 0x01; 75 } else { 76 stren_setting = 0x00; /* High-impedance */ 77 } 78 } else if (targetcsr == ODTSTRENP) { 79 #if STM32MP_DDR3_TYPE 80 /* 81 * DDR3 - P and N has the same impedance and non-zero. 82 * user input is half the individual pull-up and pull-down impedances values 83 * because of parallel between them. 84 */ 85 if (drvstren_ohm == 0U) { 86 stren_setting = 0x00; /* High-impedance */ 87 } else if (drvstren_ohm < 15U) { 88 stren_setting = 0x3f; 89 } else if (drvstren_ohm < 16U) { 90 stren_setting = 0x3e; 91 } else if (drvstren_ohm < 17U) { 92 stren_setting = 0x3b; 93 } else if (drvstren_ohm < 18U) { 94 stren_setting = 0x3a; 95 } else if (drvstren_ohm < 20U) { 96 stren_setting = 0x39; 97 } else if (drvstren_ohm < 21U) { 98 stren_setting = 0x38; 99 } else if (drvstren_ohm < 23U) { 100 stren_setting = 0x1b; 101 } else if (drvstren_ohm < 26U) { 102 stren_setting = 0x1a; 103 } else if (drvstren_ohm < 29U) { 104 stren_setting = 0x19; 105 } else if (drvstren_ohm < 33U) { 106 stren_setting = 0x18; 107 } else if (drvstren_ohm < 38U) { 108 stren_setting = 0x0b; 109 } else if (drvstren_ohm < 45U) { 110 stren_setting = 0x0a; 111 } else if (drvstren_ohm < 55U) { 112 stren_setting = 0x09; 113 } else if (drvstren_ohm < 71U) { 114 stren_setting = 0x08; 115 } else if (drvstren_ohm < 101U) { 116 stren_setting = 0x03; 117 } else if (drvstren_ohm < 181U) { 118 stren_setting = 0x02; 119 } else if (drvstren_ohm < 241U) { 120 stren_setting = 0x01; 121 } else { 122 stren_setting = 0x00; /* High-impedance */ 123 } 124 #elif STM32MP_DDR4_TYPE 125 /* DDR4 - P is non-zero */ 126 if (drvstren_ohm == 0U) { 127 stren_setting = 0x00; /* High-impedance */ 128 } else if (drvstren_ohm < 29U) { 129 stren_setting = 0x3f; 130 } else if (drvstren_ohm < 31U) { 131 stren_setting = 0x3e; 132 } else if (drvstren_ohm < 33U) { 133 stren_setting = 0x3b; 134 } else if (drvstren_ohm < 35U) { 135 stren_setting = 0x3a; 136 } else if (drvstren_ohm < 38U) { 137 stren_setting = 0x39; 138 } else if (drvstren_ohm < 41U) { 139 stren_setting = 0x38; 140 } else if (drvstren_ohm < 45U) { 141 stren_setting = 0x1b; 142 } else if (drvstren_ohm < 50U) { 143 stren_setting = 0x1a; 144 } else if (drvstren_ohm < 56U) { 145 stren_setting = 0x19; 146 } else if (drvstren_ohm < 64U) { 147 stren_setting = 0x18; 148 } else if (drvstren_ohm < 74U) { 149 stren_setting = 0x0b; 150 } else if (drvstren_ohm < 88U) { 151 stren_setting = 0x0a; 152 } else if (drvstren_ohm < 108U) { 153 stren_setting = 0x09; 154 } else if (drvstren_ohm < 140U) { 155 stren_setting = 0x08; 156 } else if (drvstren_ohm < 200U) { 157 stren_setting = 0x03; 158 } else if (drvstren_ohm < 360U) { 159 stren_setting = 0x02; 160 } else if (drvstren_ohm < 481U) { 161 stren_setting = 0x01; 162 } else { 163 stren_setting = 0x00; /* High-impedance */ 164 } 165 #else /* STM32MP_LPDDR4_TYPE */ 166 /* LPDDR4 - P is high-Z */ 167 stren_setting = 0x00; /* High-impedance */ 168 #endif /* STM32MP_DDR3_TYPE */ 169 } else if (targetcsr == ODTSTRENN) { 170 #if STM32MP_DDR3_TYPE 171 /* 172 * DDR3 - P and N has the same impedance and non-zero. 173 * Times 2 of user input because of parallel pull-up and pull-down termination. 174 */ 175 if (drvstren_ohm == 0U) { 176 stren_setting = 0x00; /* High-impedance */ 177 } else if (drvstren_ohm < 15U) { 178 stren_setting = 0x3f; 179 } else if (drvstren_ohm < 16U) { 180 stren_setting = 0x3e; 181 } else if (drvstren_ohm < 17U) { 182 stren_setting = 0x3b; 183 } else if (drvstren_ohm < 18U) { 184 stren_setting = 0x3a; 185 } else if (drvstren_ohm < 20U) { 186 stren_setting = 0x39; 187 } else if (drvstren_ohm < 21U) { 188 stren_setting = 0x38; 189 } else if (drvstren_ohm < 23U) { 190 stren_setting = 0x1b; 191 } else if (drvstren_ohm < 26U) { 192 stren_setting = 0x1a; 193 } else if (drvstren_ohm < 29U) { 194 stren_setting = 0x19; 195 } else if (drvstren_ohm < 33U) { 196 stren_setting = 0x18; 197 } else if (drvstren_ohm < 38U) { 198 stren_setting = 0x0b; 199 } else if (drvstren_ohm < 45U) { 200 stren_setting = 0x0a; 201 } else if (drvstren_ohm < 55U) { 202 stren_setting = 0x09; 203 } else if (drvstren_ohm < 71U) { 204 stren_setting = 0x08; 205 } else if (drvstren_ohm < 101U) { 206 stren_setting = 0x03; 207 } else if (drvstren_ohm < 181U) { 208 stren_setting = 0x02; 209 } else if (drvstren_ohm < 241U) { 210 stren_setting = 0x01; 211 } else { 212 stren_setting = 0x00; /* High-impedance */ 213 } 214 #elif STM32MP_DDR4_TYPE 215 /* DDR4 - N is high-Z */ 216 stren_setting = 0x00; /* High-impedance */ 217 #else /* STM32MP_LPDDR4_TYPE */ 218 /* LPDDR4 - N is non-zero */ 219 if (drvstren_ohm == 0U) { 220 stren_setting = 0x00; /* High-impedance */ 221 } else if (drvstren_ohm < 29U) { 222 stren_setting = 0x3f; 223 } else if (drvstren_ohm < 31U) { 224 stren_setting = 0x3e; 225 } else if (drvstren_ohm < 33U) { 226 stren_setting = 0x3b; 227 } else if (drvstren_ohm < 35U) { 228 stren_setting = 0x3a; 229 } else if (drvstren_ohm < 38U) { 230 stren_setting = 0x39; 231 } else if (drvstren_ohm < 41U) { 232 stren_setting = 0x38; 233 } else if (drvstren_ohm < 45U) { 234 stren_setting = 0x1b; 235 } else if (drvstren_ohm < 50U) { 236 stren_setting = 0x1a; 237 } else if (drvstren_ohm < 56U) { 238 stren_setting = 0x19; 239 } else if (drvstren_ohm < 64U) { 240 stren_setting = 0x18; 241 } else if (drvstren_ohm < 74U) { 242 stren_setting = 0x0b; 243 } else if (drvstren_ohm < 88U) { 244 stren_setting = 0x0a; 245 } else if (drvstren_ohm < 108U) { 246 stren_setting = 0x09; 247 } else if (drvstren_ohm < 140U) { 248 stren_setting = 0x08; 249 } else if (drvstren_ohm < 200U) { 250 stren_setting = 0x03; 251 } else if (drvstren_ohm < 360U) { 252 stren_setting = 0x02; 253 } else if (drvstren_ohm < 481U) { 254 stren_setting = 0x01; 255 } else { 256 stren_setting = 0x00; /* High-impedance */ 257 } 258 #endif /* STM32MP_DDR3_TYPE */ 259 } else { 260 /* if ((targetcsr == ADRVSTRENP) || (targetcsr == ADRVSTRENN)) */ 261 if (drvstren_ohm == 120U) { 262 stren_setting = 0x00; 263 } else if (drvstren_ohm == 60U) { 264 stren_setting = 0x01; 265 } else if (drvstren_ohm == 40U) { 266 stren_setting = 0x03; 267 } else if (drvstren_ohm == 30U) { 268 stren_setting = 0x07; 269 } else if (drvstren_ohm == 24U) { 270 stren_setting = 0x0F; 271 } else if (drvstren_ohm == 20U) { 272 stren_setting = 0x1F; 273 } else { 274 ERROR("%s %d\n", __func__, __LINE__); 275 VERBOSE("%s userinputadvanced.atximpedance %u Ohms value is not valid.\n", 276 __func__, drvstren_ohm); 277 VERBOSE("Valid values are: 20, 24, 30, 40, 60 and 120 Ohms.\n"); 278 } 279 } 280 281 return stren_setting; 282 } 283