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 */
ddrphy_phyinit_mapdrvstren(uint32_t drvstren_ohm,enum drvtype targetcsr)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