blob: 5fd9cb5c5936fa6a1411837845bec16e70da7a9e [file] [log] [blame]
Pankaj Guptac518de42020-12-09 14:02:39 +05301/*
Pankit Gargdadba6e2021-07-13 13:40:06 +05302 * Copyright 2021-2022 NXP
Pankaj Guptac518de42020-12-09 14:02:39 +05303 * SPDX-License-Identifier: BSD-3-Clause
4 *
5 */
6
7#include <errno.h>
8#include <stdint.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include <common/debug.h>
14#include "csr.h"
15#include <ddr.h>
16#include "ddr4fw.h"
17#include <drivers/delay_timer.h>
18#ifdef NXP_WARM_BOOT
19#include <fspi_api.h>
20#endif
21#include "input.h"
22#include <lib/mmio.h>
23#include <lib/utils.h>
24#include <lib/xlat_tables/xlat_tables_v2.h>
25#ifdef DDR_PHY_DEBUG
26#include "messages.h"
27#endif
28#ifdef NXP_WARM_BOOT
29#include "phy.h"
30#endif
31#include "pie.h"
32
33#define TIMEOUTDEFAULT 500
34#define MAP_PHY_ADDR(pstate, n, instance, offset, c) \
35 ((((pstate * n) + instance + c) << 12) + offset)
36
37static uint32_t map_phy_addr_space(uint32_t addr)
38{
39 /* 23 bit addressing */
40 uint32_t pstate = (addr & U(0x700000)) >> 20U; /* bit 22:20 */
41 uint32_t block_type = (addr & U(0x0f0000)) >> 16U; /* bit 19:16 */
42 uint32_t instance = (addr & U(0x00f000)) >> 12U; /* bit 15:12 */
43 uint32_t offset = (addr & U(0x000fff)); /* bit 11:0 */
44
45 switch (block_type) {
46 case 0x0: /* 0x0 : ANIB */
47 return MAP_PHY_ADDR(pstate, 12, instance, offset, 0);
48 case 0x1: /* 0x1 : DBYTE */
49 return MAP_PHY_ADDR(pstate, 10, instance, offset, 0x30);
50 case 0x2: /* 0x2 : MASTER */
51 return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x58);
52 case 0x4: /* 0x4 : ACSM */
53 return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x5c);
54 case 0x5: /* 0x5 : μCTL Memory */
55 return MAP_PHY_ADDR(pstate, 0, instance, offset, 0x60);
56 case 0x7: /* 0x7 : PPGC */
57 return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x68);
58 case 0x9: /* 0x9 : INITENG */
59 return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x69);
60 case 0xc: /* 0xC : DRTUB */
61 return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6d);
62 case 0xd: /* 0xD : APB Only */
63 return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6e);
64 default:
65 printf("ERR: Invalid block_type = 0x%x\n", block_type);
66 return 0;
67 }
68}
69
70static inline uint16_t *phy_io_addr(void *phy, uint32_t addr)
71{
72 return phy + (map_phy_addr_space(addr) << 2);
73}
74
75static inline void phy_io_write16(uint16_t *phy, uint32_t addr, uint16_t data)
76{
77 mmio_write_16((uintptr_t)phy_io_addr(phy, addr), data);
78#ifdef DEBUG_PHY_IO
79 printf("0x%06x,0x%x\n", addr, data);
80#endif
81}
82
83static inline uint16_t phy_io_read16(uint16_t *phy, uint32_t addr)
84{
85 uint16_t reg = mmio_read_16((uintptr_t) phy_io_addr(phy, addr));
86
87#ifdef DEBUG_PHY_IO
88 printf("R: 0x%06x,0x%x\n", addr, reg);
89#endif
90
91 return reg;
92}
93
94#ifdef NXP_APPLY_MAX_CDD
95
96#define CDD_VAL_READ_ADDR (0x054012)
97#define CDD_DATA_LEN (60)
98
99static void read_phy_reg(uint16_t *phy, uint32_t addr,
100 uint16_t *buf, uint32_t len)
101{
102 uint32_t i = 0U;
103
104 for (i = 0U; i < len/2; i++) {
105 buf[i] = phy_io_read16(phy, (addr + i));
106 }
107}
108
109static uint32_t findrank(uint32_t cs_in_use)
110{
111 uint32_t val = 0U;
112
113 switch (cs_in_use) {
114 case U(0xf):
115 val = 4U;
116 break;
117 case U(0x3):
118 val = 2U;
119 break;
120 case U(0x1):
121 val = 1U;
122 break;
123 default:
124 printf("Error - Invalid cs_in_use value\n");
125 }
126 return val;
127}
128
129static uint8_t findmax(uint8_t *buf, uint32_t len)
130{
131 uint8_t max = 0U;
132 uint32_t i = 0U;
133
134 for (i = 0U; i < len; i++) {
135 if (buf[i] > max) {
136 max = buf[i];
137 }
138 }
139
140 return max;
141}
142
143static void get_cdd_val(uint16_t **phy_ptr, uint32_t rank, uint32_t freq,
144 uint32_t *tcfg0, uint32_t *tcfg4)
145{
146 uint8_t cdd[CDD_DATA_LEN+4] = {0U};
147 uint32_t i, val = 0U;
148 uint16_t *phy;
149 uint8_t buf[16] = {U(0x0)};
150 uint8_t trr = 0U, tww = 0U, trw = 0U, twr = 0U;
151 uint8_t rrmax = 0U, wwmax = 0U, rwmax = 0U, wrmax = 0U;
152 uint8_t tmp = U(0x0);
153 uint8_t *c = NULL;
154
155 for (i = 0U; i < NUM_OF_DDRC; i++) {
156
157 phy = phy_ptr[i];
158 if (phy == NULL) {
159 continue;
160 }
161
162 phy_io_write16(phy, t_apbonly |
163 csr_micro_cont_mux_sel_addr, U(0x0));
164
165 read_phy_reg(phy, CDD_VAL_READ_ADDR,
166 (uint16_t *)&cdd, CDD_DATA_LEN);
167
168 phy_io_write16(phy, t_apbonly |
169 csr_micro_cont_mux_sel_addr, U(0x1));
170
171 /* CDD values and address
172 *
173 * 0x054012 0x24 cdd[0] CDD[X][X]
174 * 0x054012 0x25 cdd[1] RR[3][2]
175 * 0x054013 0x26 cdd[2] RR[3][1]
176 * 0x054013 0x27 cdd[3] RR[3][0]
177 * 0x054014 0x28 cdd[4] RR[2][3]
178 * 0x054014 0x29 cdd[5] RR[2][1]
179 * 0x054015 0x2a cdd[6] RR[2][0]
180 * 0x054015 0x2b cdd[7] RR[1][3]
181 * 0x054016 0x2c cdd[8] RR[1][2]
182 * 0x054016 0x2d cdd[9] RR[1][0]
183 * 0x054017 0x2e cdd[10] RR[0][3]
184 * 0x054017 0x2f cdd[11] RR[0][2]
185 * 0x054018 0x30 cdd[12] RR[0][1]
186
187 * 0x054018 0x31 cdd[13] WW[3][2]
188 * 0x054019 0x32 cdd[14] WW[3][1]
189 * 0x054019 0x33 cdd[15] WW[3][0]
190 * 0x05401a 0x34 cdd[16] WW[2][3]
191 * 0x05401a 0x35 cdd[17] WW[2][1]
192 * 0x05401b 0x36 cdd[18] WW[2][0]
193 * 0x05401b 0x37 cdd[19] WW[1][3]
194 * 0x05401c 0x38 cdd[20] WW[1][2]
195 * 0x05401c 0x39 cdd[21] WW[1][0]
196 * 0x05401d 0x3a cdd[22] WW[0][3]
197 * 0x05401d 0x3b cdd[23] WW[0][2]
198 * 0x05401e 0x3c cdd[24] WW[0][1]
199
200 * 0x05401e 0x3d cdd[25] RW[3][3]
201 * 0x05401f 0x3e cdd[26] RW[3][2]
202 * 0x05401f 0x3f cdd[27] RW[3][1]
203 * 0x054020 0x40 cdd[28] RW[3][0]
204 * 0x054020 0x41 cdd[29] RW[2][3]
205 * 0x054021 0x42 cdd[30] RW[2][2]
206 * 0x054021 0x43 cdd[31] RW[2][1]
207 * 0x054022 0x44 cdd[32] RW[2][0]
208 * 0x054022 0x45 cdd[33] RW[1][3]
209 * 0x054023 0x46 cdd[34] RW[1][2]
210 * 0x054023 0x47 cdd[35] RW[1][1]
211 * 0x054024 0x48 cdd[36] RW[1][0]
212 * 0x054024 0x49 cdd[37] RW[0][3]
213 * 0x054025 0x4a cdd[38] RW[0][2]
214 * 0x054025 0x4b cdd[39] RW[0][1]
215 * 0x054026 0x4c cdd[40] RW[0][0]
216
217 * 0x054026 0x4d cdd[41] WR[3][3]
218 * 0x054027 0x4e cdd[42] WR[3][2]
219 * 0x054027 0x4f cdd[43] WR[3][1]
220 * 0x054028 0x50 cdd[44] WR[3][0]
221 * 0x054028 0x51 cdd[45] WR[2][3]
222 * 0x054029 0x52 cdd[46] WR[2][2]
223 * 0x054029 0x53 cdd[47] WR[2][1]
224 * 0x05402a 0x54 cdd[48] WR[2][0]
225 * 0x05402a 0x55 cdd[49] WR[1][3]
226 * 0x05402b 0x56 cdd[50] WR[1][2]
227 * 0x05402b 0x57 cdd[51] WR[1][1]
228 * 0x05402c 0x58 cdd[52] WR[1][0]
229 * 0x05402c 0x59 cdd[53] WR[0][3]
230 * 0x05402d 0x5a cdd[54] WR[0][2]
231 * 0x05402d 0x5b cdd[55] WR[0][1]
232 * 0x05402e 0x5c cdd[56] WR[0][0]
233 * 0x05402e 0x5d cdd[57] CDD[Y][Y]
234 */
235
236 switch (rank) {
237 case 1U:
238 tmp = rwmax;
239 rwmax = cdd[40];
240 if (tmp > rwmax) {
241 rwmax = tmp;
242 }
243
Pankaj Guptac518de42020-12-09 14:02:39 +0530244 break;
245
246 case 2U:
247 buf[0] = cdd[12];
248 buf[1] = cdd[9];
249 tmp = rrmax;
250 rrmax = findmax(buf, 2U);
251 if (tmp > rrmax) {
252 rrmax = tmp;
253 }
254
255 buf[0] = cdd[24];
256 buf[1] = cdd[21];
257 tmp = wwmax;
258 wwmax = findmax(buf, 2U);
259 if (tmp > wwmax) {
260 wwmax = tmp;
261 }
262
263 buf[0] = cdd[40];
264 buf[1] = cdd[39];
265 buf[2] = cdd[36];
266 buf[3] = cdd[35];
267 tmp = rwmax;
268 rwmax = findmax(buf, 4U);
269 if (tmp > rwmax) {
270 rwmax = tmp;
271 }
272
Maninder Singh2174f322022-02-20 20:51:43 -0700273 wrmax = wwmax;
Pankaj Guptac518de42020-12-09 14:02:39 +0530274
275 break;
276
277 case 4U:
278 tmp = rrmax;
279 c = &cdd[1];
280 rrmax = findmax(c, 12U);
281 if (tmp > rrmax) {
282 rrmax = tmp;
283 }
284
285 tmp = wwmax;
286 c = &cdd[13];
287 wwmax = findmax(c, 12U);
288 if (tmp > wwmax) {
289 wwmax = tmp;
290 }
291
292 tmp = rwmax;
293 c = &cdd[25];
294 rwmax = findmax(c, 16U);
295 if (tmp > rwmax) {
296 rwmax = tmp;
297 }
298
Maninder Singh2174f322022-02-20 20:51:43 -0700299 wrmax = wwmax;
Pankaj Guptac518de42020-12-09 14:02:39 +0530300
301 break;
302
303 }
304 }
305
306 rrmax += 3U;
307 wwmax += 4U;
308
309 if (wwmax > 7U) {
310 wwmax = 7U;
311 }
312
313 if (rrmax > 7U) {
314 rrmax = 7U;
315 }
316
317 if (wrmax > U(0xf)) {
318 wrmax = 0U;
319 }
320
321 if (rwmax > U(0x7)) {
322 rwmax = U(0x7);
323 }
324
325 val = *tcfg0;
326 tww = (val >> 24U) & U(0x3);
327 trr = (val >> 26U) & U(0x3);
328 twr = (val >> 28U) & U(0x3);
329 trw = (val >> 30U) & U(0x3);
330
331 val = *tcfg4;
332 tww = tww | (((val >> 8U) & U(0x1)) << 2U);
333 trr = trr | (((val >> 10U) & U(0x1)) << 2U);
334 twr = twr | (((val >> 12U) & U(0x1)) << 2U);
335 trw = trw | (((val >> 14U) & U(0x3)) << 2U);
336
337 if (trr > rrmax) {
338 rrmax = trr;
339 }
340
341 if (tww > wwmax) {
342 wwmax = tww;
343 }
344
345 if (trw > rwmax) {
346 rwmax = trw;
347 }
348
349 if (twr > wrmax) {
350 wrmax = twr;
351 }
352
353 debug("CDD rrmax %x wwmax %x rwmax %x wrmax %x\n",
354 rrmax, wwmax, rwmax, wrmax);
355
356 val = ((wwmax & U(0x3)) << 24U)
357 | ((rrmax & U(0x3)) << 26U)
358 | ((wrmax & U(0x3)) << 28U)
359 | ((rwmax & U(0x3)) << 30U);
360
361 *tcfg0 = (*tcfg0 & U(0x00FFFFFF)) | (val);
362
363 val = (((wwmax >> 2U) & U(0x1)) << 8U)
364 | (((rrmax >> 2U) & U(0x1)) << 10U)
365 | (((wrmax >> 2U) & U(0x1)) << 12U)
366 | (((rwmax >> 2U) & U(0x3)) << 14U);
367
368 *tcfg4 = (*tcfg4 & U(0xffff00ff)) | val;
369}
370#endif
371
372#ifdef NXP_WARM_BOOT
373int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store,
Maninder Singh8666b3c2022-01-31 02:16:10 -0700374 uint32_t num_of_phy, int train2d
375#ifdef NXP_APPLY_MAX_CDD
376 , struct ddr_ctrl_reg_values *ddrctrl_regs
377#endif
378 )
379
Pankaj Guptac518de42020-12-09 14:02:39 +0530380{
381 uint16_t *phy = NULL, value = 0x0;
382 uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U;
383 int i = 0, j = 0, ret = -EINVAL;
384
385 ret = xspi_sector_erase(address_to_store, PHY_ERASE_SIZE);
386 if (ret != 0) {
387 return -EINVAL;
388 }
389
390 for (j = 0; j < num_of_phy; j++) {
391 /* Save training values of all PHYs */
392 phy = phy_ptr[j];
393 size = sizeof(training_1D_values);
394 num_of_regs = ARRAY_SIZE(training_1D_values);
395
396 /* Enable access to the internal CSRs */
397 phy_io_write16(phy, t_apbonly |
398 csr_micro_cont_mux_sel_addr, 0x0);
399 /* Enable clocks in case they were disabled. */
400 phy_io_write16(phy, t_drtub |
401 csr_ucclk_hclk_enables_addr, 0x3);
402 if (train2d != 0) {
403 /* Address to store training values is
404 * to be appended for next PHY
405 */
406 phy_store = address_to_store + (j *
407 (sizeof(training_1D_values) +
408 sizeof(training_2D_values)));
409 } else {
410 phy_store = address_to_store + (j *
411 (sizeof(training_1D_values)));
412 }
413 debug("Saving 1D Training reg val at: %d\n", phy_store);
414 for (i = 0; i < num_of_regs; i++) {
415 value = phy_io_read16(phy, training_1D_values[i].addr);
416#ifdef DEBUG_WARM_RESET
417 debug("%d. Reg: %x, value: %x PHY: %p\n", i,
418 training_1D_values[i].addr, value,
419 phy_io_addr(phy,
420 training_1D_values[i].addr));
421#endif
422 training_1D_values[i].data = value;
423 }
424 /* Storing 1D training values on flash */
425 ret = xspi_write(phy_store, (void *)training_1D_values, size);
426 if (train2d != 0) {
427 phy_store = phy_store+size;
428 size = sizeof(training_2D_values);
429 num_of_regs = ARRAY_SIZE(training_2D_values);
430 debug("Saving 2D Training reg val at:%d\n", phy_store);
431 for (i = 0; i < num_of_regs; i++) {
432 value = phy_io_read16(phy,
433 training_2D_values[i].addr);
434 training_2D_values[i].data = value;
435#ifdef DEBUG_WARM_RESET
436 debug("%d.2D addr:0x%x,val:0x%x,PHY:0x%p\n",
437 i, training_2D_values[i].addr,
438 value, phy_io_addr(phy,
439 training_2D_values[i].addr));
440#endif
441 }
442 /* Storing 2D training values on flash */
443 ret = xspi_write(phy_store, training_2D_values,
444 size);
445 }
Maninder Singh8666b3c2022-01-31 02:16:10 -0700446
447#ifdef NXP_APPLY_MAX_CDD
448 /* Save DDR control register Timing CFG 0 and 4 */
449 phy_store += size;
450 size = sizeof(ddrctrl_regs);
451 if (ret != 0) {
452 ret = xspi_write(phy_store, ddrctrl_regs, size);
453 }
454#endif
Pankaj Guptac518de42020-12-09 14:02:39 +0530455 /* Disable clocks in case they were disabled. */
456 phy_io_write16(phy, t_drtub |
457 csr_ucclk_hclk_enables_addr, 0x0);
458 /* Disable access to the internal CSRs */
459 phy_io_write16(phy, t_apbonly |
460 csr_micro_cont_mux_sel_addr, 0x1);
461 }
462 if (ret != 0) {
463 return -EINVAL;
464 }
465
466 return 0;
467}
468
469int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore,
Maninder Singh8666b3c2022-01-31 02:16:10 -0700470 uint32_t num_of_phy, int train2d
471#ifdef NXP_APPLY_MAX_CDD
472 , struct ddr_ctrl_reg_values *ddrctrl_regs
473#endif
474 )
Pankaj Guptac518de42020-12-09 14:02:39 +0530475{
476 uint16_t *phy = NULL;
477 uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U;
478 int i = 0, j = 0, ret = -EINVAL;
479
480 debug("Restoring Training register values\n");
481 for (j = 0; j < num_of_phy; j++) {
482 phy = phy_ptr[j];
483 size = sizeof(training_1D_values);
484 num_of_regs = ARRAY_SIZE(training_1D_values);
485 if (train2d != 0) {
486 /* The address to restore training values is
487 * to be appended for next PHY
488 */
489 phy_store = address_to_restore + (j *
490 (sizeof(training_1D_values) +
491 sizeof(training_2D_values)));
492 } else {
493 phy_store = address_to_restore + (j *
494 (sizeof(training_1D_values)));
495 }
496 /* Enable access to the internal CSRs */
497 phy_io_write16(phy, t_apbonly |
498 csr_micro_cont_mux_sel_addr, 0x0);
499 /* Enable clocks in case they were disabled. */
500 phy_io_write16(phy, t_drtub |
501 csr_ucclk_hclk_enables_addr, 0x3);
502
503 /* Reading 1D training values from flash*/
504 ret = xspi_read(phy_store, (uint32_t *)training_1D_values,
505 size);
506 debug("Restoring 1D Training reg val at:%08x\n", phy_store);
507 for (i = 0; i < num_of_regs; i++) {
508 phy_io_write16(phy, training_1D_values[i].addr,
509 training_1D_values[i].data);
510#ifdef DEBUG_WARM_RESET
511 debug("%d. Reg: %x, value: %x PHY: %p\n", i,
512 training_1D_values[i].addr,
513 training_1D_values[i].data,
514 phy_io_addr(phy,
515 training_1D_values[i].addr));
516#endif
517 }
518 if (train2d != 0) {
519 phy_store = phy_store + size;
520 size = sizeof(training_2D_values);
521 num_of_regs = ARRAY_SIZE(training_2D_values);
522 /* Reading 2D training values from flash */
523 ret = xspi_read(phy_store,
524 (uint32_t *)training_2D_values, size);
525 debug("Restoring 2D Training reg val at:%08x\n",
526 phy_store);
527 for (i = 0; i < num_of_regs; i++) {
528 phy_io_write16(phy, training_2D_values[i].addr,
529 training_2D_values[i].data);
530#ifdef DEBUG_WARM_RESET
531 debug("%d. Reg: %x, value: %x PHY: %p\n", i,
532 training_2D_values[i].addr,
533 training_2D_values[i].data,
534 phy_io_addr(phy,
535 training_1D_values[i].addr));
536#endif
537 }
538 }
Maninder Singh8666b3c2022-01-31 02:16:10 -0700539#ifdef NXP_APPLY_MAX_CDD
540 phy_store = phy_store + size;
541 size = sizeof(ddrctrl_regs);
542 ret = xspi_read(phy_store, (uint32_t *)ddrctrl_regs, size);
543#endif
Pankaj Guptac518de42020-12-09 14:02:39 +0530544 /* Disable clocks in case they were disabled. */
545 phy_io_write16(phy, t_drtub |
546 csr_ucclk_hclk_enables_addr, 0x0);
547 /* Disable access to the internal CSRs */
548 phy_io_write16(phy, t_apbonly |
549 csr_micro_cont_mux_sel_addr, 0x1);
550 }
551 if (ret != 0) {
552 return -EINVAL;
553 }
554 return 0;
555}
556#endif
557
558static void load_pieimage(uint16_t *phy,
559 enum dimm_types dimm_type)
560{
561 int i;
562 int size;
563 const struct pie *image = NULL;
564
565 switch (dimm_type) {
566 case UDIMM:
567 case SODIMM:
568 case NODIMM:
569 image = pie_udimm;
570 size = ARRAY_SIZE(pie_udimm);
571 break;
572 case RDIMM:
573 image = pie_rdimm;
574 size = ARRAY_SIZE(pie_rdimm);
575 break;
576 case LRDIMM:
577 image = pie_lrdimm;
578 size = ARRAY_SIZE(pie_lrdimm);
579 break;
580 default:
581 printf("Unsupported DIMM type\n");
582 break;
583 }
584
585 if (image != NULL) {
586 for (i = 0; i < size; i++)
587 phy_io_write16(phy, image[i].addr, image[i].data);
588 }
589}
590
591static void prog_acsm_playback(uint16_t *phy,
592 const struct input *input, const void *msg)
593{
594 int vec;
595 const struct ddr4r1d *msg_blk;
596 uint16_t acsmplayback[2][3];
597 uint32_t f0rc0a;
598 uint32_t f0rc3x;
599 uint32_t f0rc5x;
600
601 if (input->basic.dimm_type != RDIMM) {
602 return;
603 }
604
605 msg_blk = msg;
606 f0rc0a = (msg_blk->f0rc0a_d0 & U(0xf)) | U(0xa0);
607 f0rc3x = (msg_blk->f0rc3x_d0 & U(0xff)) | U(0x300);
608 f0rc5x = (input->adv.phy_gen2_umctl_f0rc5x & U(0xff)) | U(0x500);
609
610 acsmplayback[0][0] = U(0x3ff) & f0rc0a;
611 acsmplayback[1][0] = (U(0x1c00) & f0rc0a) >> 10U;
612 acsmplayback[0][1] = U(0x3ff) & f0rc3x;
613 acsmplayback[1][1] = (U(0x1c00) & f0rc3x) >> 10U;
614 acsmplayback[0][2] = U(0x3ff) & f0rc5x;
615 acsmplayback[1][2] = (U(0x1c00) & f0rc5x) >> 10U;
616 for (vec = 0; vec < 3; vec++) {
617 phy_io_write16(phy, t_acsm | (csr_acsm_playback0x0_addr +
618 (vec << 1)), acsmplayback[0][vec]);
619 phy_io_write16(phy, t_acsm | (csr_acsm_playback1x0_addr +
620 (vec << 1)), acsmplayback[1][vec]);
621 }
622}
623
624static void prog_acsm_ctr(uint16_t *phy,
625 const struct input *input)
626{
627 if (input->basic.dimm_type != RDIMM) {
628 return;
629 }
630
631 phy_io_write16(phy, t_acsm | csr_acsm_ctrl13_addr,
632 0xf << csr_acsm_cke_enb_lsb);
633
634 phy_io_write16(phy, t_acsm | csr_acsm_ctrl0_addr,
635 csr_acsm_par_mode_mask | csr_acsm_2t_mode_mask);
636}
637
638static void prog_cal_rate_run(uint16_t *phy,
639 const struct input *input)
640{
641 int cal_rate;
642 int cal_interval;
643 int cal_once;
644 uint32_t addr;
645
646 cal_interval = input->adv.cal_interval;
647 cal_once = input->adv.cal_once;
648 cal_rate = 0x1 << csr_cal_run_lsb |
649 cal_once << csr_cal_once_lsb |
650 cal_interval << csr_cal_interval_lsb;
651 addr = t_master | csr_cal_rate_addr;
652 phy_io_write16(phy, addr, cal_rate);
653}
654
655static void prog_seq0bdly0(uint16_t *phy,
656 const struct input *input)
657{
658 int ps_count[4];
659 int frq;
660 uint32_t addr;
661 int lower_freq_opt = 0;
662
663 __unused const soc_info_t *soc_info;
664
665 frq = input->basic.frequency >> 1;
666 ps_count[0] = frq >> 3; /* 0.5 * frq / 4*/
667 if (input->basic.frequency < 400) {
668 lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 7 : 3;
669 } else if (input->basic.frequency < 533) {
670 lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 14 : 11;
671 }
672
673 /* 1.0 * frq / 4 - lower_freq */
674 ps_count[1] = (frq >> 2) - lower_freq_opt;
675 ps_count[2] = (frq << 1) + (frq >> 1); /* 10.0 * frq / 4 */
676
677#ifdef DDR_PLL_FIX
678 soc_info = get_soc_info();
Jiafei Panb27ac802021-07-20 17:14:32 +0800679 if (soc_info->svr_reg.bf.maj_ver == 1) {
Pankaj Guptac518de42020-12-09 14:02:39 +0530680 ps_count[0] = 0x520; /* seq0bdly0 */
681 ps_count[1] = 0xa41; /* seq0bdly1 */
682 ps_count[2] = 0x668a; /* seq0bdly2 */
683 }
684#endif
685 if (frq > 266) {
686 ps_count[3] = 44;
687 } else if (frq > 200) {
688 ps_count[3] = 33;
689 } else {
690 ps_count[3] = 16;
691 }
692
693 addr = t_master | csr_seq0bdly0_addr;
694 phy_io_write16(phy, addr, ps_count[0]);
695
696 debug("seq0bdly0 = 0x%x\n", phy_io_read16(phy, addr));
697
698 addr = t_master | csr_seq0bdly1_addr;
699 phy_io_write16(phy, addr, ps_count[1]);
700
701 debug("seq0bdly1 = 0x%x\n", phy_io_read16(phy, addr));
702
703 addr = t_master | csr_seq0bdly2_addr;
704 phy_io_write16(phy, addr, ps_count[2]);
705
706 debug("seq0bdly2 = 0x%x\n", phy_io_read16(phy, addr));
707
708 addr = t_master | csr_seq0bdly3_addr;
709 phy_io_write16(phy, addr, ps_count[3]);
710
711 debug("seq0bdly3 = 0x%x\n", phy_io_read16(phy, addr));
712}
713
714/* Only RDIMM requires msg_blk */
715static void i_load_pie(uint16_t **phy_ptr,
716 const struct input *input,
717 const void *msg)
718{
719 int i;
720 uint16_t *phy;
721
722 for (i = 0; i < NUM_OF_DDRC; i++) {
723 phy = phy_ptr[i];
724 if (phy == NULL) {
725 continue;
726 }
727
728 phy_io_write16(phy,
729 t_apbonly | csr_micro_cont_mux_sel_addr,
730 0U);
731
732 load_pieimage(phy, input->basic.dimm_type);
733
734 prog_seq0bdly0(phy, input);
735 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag0_addr,
736 U(0x0000));
737 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag1_addr,
738 U(0x0173));
739 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag2_addr,
740 U(0x0060));
741 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag3_addr,
742 U(0x6110));
743 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag4_addr,
744 U(0x2152));
745 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag5_addr,
746 U(0xdfbd));
747 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag6_addr,
748 input->basic.dimm_type == RDIMM &&
749 input->adv.phy_gen2_umctl_opt == 1U ?
750 U(0x6000) : U(0xffff));
751 phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag7_addr,
752 U(0x6152));
753 prog_acsm_playback(phy, input, msg); /* rdimm */
754 prog_acsm_ctr(phy, input); /* rdimm */
755
756 phy_io_write16(phy, t_master | csr_cal_zap_addr, U(0x1));
757 prog_cal_rate_run(phy, input);
758
759 phy_io_write16(phy, t_drtub | csr_ucclk_hclk_enables_addr,
760 input->basic.dimm_type == RDIMM ? U(0x2) : 0U);
761
762 phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 1U);
763 }
764}
765
766static void phy_gen2_init_input(struct input *input)
767{
768 int i;
769
770 input->adv.dram_byte_swap = 0;
771 input->adv.ext_cal_res_val = 0;
772 input->adv.tx_slew_rise_dq = 0xf;
773 input->adv.tx_slew_fall_dq = 0xf;
774 input->adv.tx_slew_rise_ac = 0xf;
775 input->adv.tx_slew_fall_ac = 0xf;
776 input->adv.mem_alert_en = 0;
777 input->adv.mem_alert_puimp = 5;
778 input->adv.mem_alert_vref_level = 0x29;
779 input->adv.mem_alert_sync_bypass = 0;
780 input->adv.cal_interval = 0x9;
781 input->adv.cal_once = 0;
782 input->adv.dis_dyn_adr_tri = 0;
783 input->adv.is2ttiming = 0;
784 input->adv.d4rx_preamble_length = 0;
785 input->adv.d4tx_preamble_length = 0;
786
787 for (i = 0; i < 7; i++) {
788 debug("mr[%d] = 0x%x\n", i, input->mr[i]);
789 }
790
791 debug("input->cs_d0 = 0x%x\n", input->cs_d0);
792 debug("input->cs_d1 = 0x%x\n", input->cs_d1);
793 debug("input->mirror = 0x%x\n", input->mirror);
794 debug("PHY ODT impedance = %d ohm\n", input->adv.odtimpedance);
795 debug("PHY DQ driver impedance = %d ohm\n", input->adv.tx_impedance);
796 debug("PHY Addr driver impedance = %d ohm\n", input->adv.atx_impedance);
797
798 for (i = 0; i < 4; i++) {
799 debug("odt[%d] = 0x%x\n", i, input->odt[i]);
800 }
801
802 if (input->basic.dimm_type == RDIMM) {
803 for (i = 0; i < 16; i++) {
804 debug("input->rcw[%d] = 0x%x\n", i, input->rcw[i]);
805 }
806 debug("input->rcw3x = 0x%x\n", input->rcw3x);
807 }
808}
809
810/*
811 * All protocols share the same base structure of message block.
812 * RDIMM and LRDIMM have more entries defined than UDIMM.
813 * Create message blocks for 1D and 2D training.
814 * Update len with message block size.
815 */
816static int phy_gen2_msg_init(void *msg_1d,
817 void *msg_2d,
818 const struct input *input)
819{
820 struct ddr4u1d *msg_blk = msg_1d;
821 struct ddr4u2d *msg_blk_2d = msg_2d;
822 struct ddr4r1d *msg_blk_r;
823 struct ddr4lr1d *msg_blk_lr;
824
825 switch (input->basic.dimm_type) {
826 case UDIMM:
827 case SODIMM:
828 case NODIMM:
829 msg_blk->dram_type = U(0x2);
830 break;
831 case RDIMM:
832 msg_blk->dram_type = U(0x4);
833 break;
834 case LRDIMM:
835 msg_blk->dram_type = U(0x5);
836 break;
837 default:
838 ERROR("Unsupported DIMM type\n");
839 return -EINVAL;
840 }
841 msg_blk->pstate = 0U;
842
843 /*Enable quickRd2D, a substage of read deskew, to 1D training.*/
844 msg_blk->reserved00 = U(0x20);
845
846 /*Enable High-Effort WrDQ1D.*/
847 msg_blk->reserved00 |= U(0x40);
848
849 /* Enable 1D extra effort training.*/
850 msg_blk->reserved1c[3] = U(0x3);
851
852 if (input->basic.dimm_type == LRDIMM) {
853 msg_blk->sequence_ctrl = U(0x3f1f);
854 } else {
855 msg_blk->sequence_ctrl = U(0x031f);
856 }
857 msg_blk->phy_config_override = 0U;
858#ifdef DDR_PHY_DEBUG
859 msg_blk->hdt_ctrl = U(0x5);
860#else
861 msg_blk->hdt_ctrl = U(0xc9);
862#endif
863 msg_blk->msg_misc = U(0x0);
864 msg_blk->dfimrlmargin = U(0x1);
865 msg_blk->phy_vref = input->vref ? input->vref : U(0x61);
866 msg_blk->cs_present = input->cs_d0 | input->cs_d1;
867 msg_blk->cs_present_d0 = input->cs_d0;
868 msg_blk->cs_present_d1 = input->cs_d1;
869 if (input->mirror != 0) {
870 msg_blk->addr_mirror = U(0x0a); /* odd CS are mirrored */
871 }
872 msg_blk->share2dvref_result = 1U;
873
874 msg_blk->acsm_odt_ctrl0 = input->odt[0];
875 msg_blk->acsm_odt_ctrl1 = input->odt[1];
876 msg_blk->acsm_odt_ctrl2 = input->odt[2];
877 msg_blk->acsm_odt_ctrl3 = input->odt[3];
878 msg_blk->enabled_dqs = (input->basic.num_active_dbyte_dfi0 +
879 input->basic.num_active_dbyte_dfi1) * 8;
880 msg_blk->x16present = input->basic.dram_data_width == 0x10 ?
881 msg_blk->cs_present : 0;
882 msg_blk->d4misc = U(0x1);
883 msg_blk->cs_setup_gddec = U(0x1);
884 msg_blk->rtt_nom_wr_park0 = 0U;
885 msg_blk->rtt_nom_wr_park1 = 0U;
886 msg_blk->rtt_nom_wr_park2 = 0U;
887 msg_blk->rtt_nom_wr_park3 = 0U;
888 msg_blk->rtt_nom_wr_park4 = 0U;
889 msg_blk->rtt_nom_wr_park5 = 0U;
890 msg_blk->rtt_nom_wr_park6 = 0U;
891 msg_blk->rtt_nom_wr_park7 = 0U;
892 msg_blk->mr0 = input->mr[0];
893 msg_blk->mr1 = input->mr[1];
894 msg_blk->mr2 = input->mr[2];
895 msg_blk->mr3 = input->mr[3];
896 msg_blk->mr4 = input->mr[4];
897 msg_blk->mr5 = input->mr[5];
898 msg_blk->mr6 = input->mr[6];
899 if ((msg_blk->mr4 & U(0x1c0)) != 0U) {
900 ERROR("Setting DRAM CAL mode is not supported\n");
901 }
902
903 msg_blk->alt_cas_l = 0U;
904 msg_blk->alt_wcas_l = 0U;
905
906 msg_blk->dramfreq = input->basic.frequency * 2U;
907 msg_blk->pll_bypass_en = input->basic.pll_bypass;
908 msg_blk->dfi_freq_ratio = input->basic.dfi_freq_ratio == 0U ? 1U :
909 input->basic.dfi_freq_ratio == 1U ? 2U :
910 4U;
911 msg_blk->bpznres_val = input->adv.ext_cal_res_val;
912 msg_blk->disabled_dbyte = 0U;
913
914 debug("msg_blk->dram_type = 0x%x\n", msg_blk->dram_type);
915 debug("msg_blk->sequence_ctrl = 0x%x\n", msg_blk->sequence_ctrl);
916 debug("msg_blk->phy_cfg = 0x%x\n", msg_blk->phy_cfg);
917 debug("msg_blk->x16present = 0x%x\n", msg_blk->x16present);
918 debug("msg_blk->dramfreq = 0x%x\n", msg_blk->dramfreq);
919 debug("msg_blk->pll_bypass_en = 0x%x\n", msg_blk->pll_bypass_en);
920 debug("msg_blk->dfi_freq_ratio = 0x%x\n", msg_blk->dfi_freq_ratio);
921 debug("msg_blk->phy_odt_impedance = 0x%x\n",
922 msg_blk->phy_odt_impedance);
923 debug("msg_blk->phy_drv_impedance = 0x%x\n",
924 msg_blk->phy_drv_impedance);
925 debug("msg_blk->bpznres_val = 0x%x\n", msg_blk->bpznres_val);
926 debug("msg_blk->enabled_dqs = 0x%x\n", msg_blk->enabled_dqs);
927 debug("msg_blk->acsm_odt_ctrl0 = 0x%x\n", msg_blk->acsm_odt_ctrl0);
928 debug("msg_blk->acsm_odt_ctrl1 = 0x%x\n", msg_blk->acsm_odt_ctrl1);
929 debug("msg_blk->acsm_odt_ctrl2 = 0x%x\n", msg_blk->acsm_odt_ctrl2);
930 debug("msg_blk->acsm_odt_ctrl3 = 0x%x\n", msg_blk->acsm_odt_ctrl3);
931
932 /* RDIMM only */
933 if (input->basic.dimm_type == RDIMM ||
934 input->basic.dimm_type == LRDIMM) {
935 msg_blk_r = (struct ddr4r1d *)msg_blk;
936 if (msg_blk_r->cs_present_d0 != 0U) {
937 msg_blk_r->f0rc00_d0 = input->rcw[0];
938 msg_blk_r->f0rc01_d0 = input->rcw[1];
939 msg_blk_r->f0rc02_d0 = input->rcw[2];
940 msg_blk_r->f0rc03_d0 = input->rcw[3];
941 msg_blk_r->f0rc04_d0 = input->rcw[4];
942 msg_blk_r->f0rc05_d0 = input->rcw[5];
943 msg_blk_r->f0rc06_d0 = input->rcw[6];
944 msg_blk_r->f0rc07_d0 = input->rcw[7];
945 msg_blk_r->f0rc08_d0 = input->rcw[8];
946 msg_blk_r->f0rc09_d0 = input->rcw[9];
947 msg_blk_r->f0rc0a_d0 = input->rcw[10];
948 msg_blk_r->f0rc0b_d0 = input->rcw[11];
949 msg_blk_r->f0rc0c_d0 = input->rcw[12];
950 msg_blk_r->f0rc0d_d0 = input->rcw[13];
951 msg_blk_r->f0rc0e_d0 = input->rcw[14];
952 msg_blk_r->f0rc0f_d0 = input->rcw[15];
953 msg_blk_r->f0rc3x_d0 = input->rcw3x;
954 }
955 if (msg_blk_r->cs_present_d1 != 0) {
956 msg_blk_r->f0rc00_d1 = input->rcw[0];
957 msg_blk_r->f0rc01_d1 = input->rcw[1];
958 msg_blk_r->f0rc02_d1 = input->rcw[2];
959 msg_blk_r->f0rc03_d1 = input->rcw[3];
960 msg_blk_r->f0rc04_d1 = input->rcw[4];
961 msg_blk_r->f0rc05_d1 = input->rcw[5];
962 msg_blk_r->f0rc06_d1 = input->rcw[6];
963 msg_blk_r->f0rc07_d1 = input->rcw[7];
964 msg_blk_r->f0rc08_d1 = input->rcw[8];
965 msg_blk_r->f0rc09_d1 = input->rcw[9];
966 msg_blk_r->f0rc0a_d1 = input->rcw[10];
967 msg_blk_r->f0rc0b_d1 = input->rcw[11];
968 msg_blk_r->f0rc0c_d1 = input->rcw[12];
969 msg_blk_r->f0rc0d_d1 = input->rcw[13];
970 msg_blk_r->f0rc0e_d1 = input->rcw[14];
971 msg_blk_r->f0rc0f_d1 = input->rcw[15];
972 msg_blk_r->f0rc3x_d1 = input->rcw3x;
973 }
974 if (input->basic.dimm_type == LRDIMM) {
975 msg_blk_lr = (struct ddr4lr1d *)msg_blk;
976 msg_blk_lr->bc0a_d0 = msg_blk_lr->f0rc0a_d0;
977 msg_blk_lr->bc0a_d1 = msg_blk_lr->f0rc0a_d1;
978 msg_blk_lr->f0bc6x_d0 = msg_blk_lr->f0rc3x_d0;
979 msg_blk_lr->f0bc6x_d1 = msg_blk_lr->f0rc3x_d1;
980 }
981 }
982
983 /* below is different for 1D and 2D message block */
984 if (input->basic.train2d != 0) {
985 memcpy(msg_blk_2d, msg_blk, sizeof(struct ddr4u1d));
986 /*High-Effort WrDQ1D is applicable to 2D traning also*/
987 msg_blk_2d->reserved00 |= U(0x40);
988 msg_blk_2d->sequence_ctrl = U(0x0061);
989 msg_blk_2d->rx2d_train_opt = 0U;
990 msg_blk_2d->tx2d_train_opt = 0U;
991 msg_blk_2d->share2dvref_result = 1U;
992 msg_blk_2d->delay_weight2d = U(0x20);
993 msg_blk_2d->voltage_weight2d = U(0x80);
994 debug("rx2d_train_opt %d, tx2d_train_opt %d\n",
995 msg_blk_2d->rx2d_train_opt,
996 msg_blk_2d->tx2d_train_opt);
997 }
998
999 msg_blk->phy_cfg = (((msg_blk->mr3 & U(0x8)) != 0U) ||
1000 ((msg_blk_2d->mr3 & 0x8) != 0U)) ? 0U
1001 : input->adv.is2ttiming;
1002
1003 return 0;
1004}
1005
1006static void prog_tx_pre_drv_mode(uint16_t *phy,
1007 const struct input *input)
1008{
1009 int lane, byte, b_addr, c_addr, p_addr;
1010 int tx_slew_rate, tx_pre_p, tx_pre_n;
1011 int tx_pre_drv_mode = 0x2;
1012 uint32_t addr;
1013
1014 /* Program TxPreDrvMode with 0x2 */
1015 /* FIXME: TxPreDrvMode depends on DramType? */
1016 tx_pre_p = input->adv.tx_slew_rise_dq;
1017 tx_pre_n = input->adv.tx_slew_fall_dq;
1018 tx_slew_rate = tx_pre_drv_mode << csr_tx_pre_drv_mode_lsb |
1019 tx_pre_p << csr_tx_pre_p_lsb |
1020 tx_pre_n << csr_tx_pre_n_lsb;
1021 p_addr = 0;
1022 for (byte = 0; byte < input->basic.num_dbyte; byte++) {
1023 c_addr = byte << 12;
1024 for (lane = 0; lane <= 1; lane++) {
1025 b_addr = lane << 8;
1026 addr = p_addr | t_dbyte | c_addr | b_addr |
1027 csr_tx_slew_rate_addr;
1028 phy_io_write16(phy, addr, tx_slew_rate);
1029 }
1030 }
1031}
1032
1033static void prog_atx_pre_drv_mode(uint16_t *phy,
1034 const struct input *input)
1035{
1036 int anib, c_addr;
1037 int atx_slew_rate, atx_pre_p, atx_pre_n, atx_pre_drv_mode,
1038 ck_anib_inst[2];
1039 uint32_t addr;
1040
1041 atx_pre_n = input->adv.tx_slew_fall_ac;
1042 atx_pre_p = input->adv.tx_slew_rise_ac;
1043
1044 if (input->basic.num_anib == 8) {
1045 ck_anib_inst[0] = 1;
1046 ck_anib_inst[1] = 1;
1047 } else if (input->basic.num_anib == 10 || input->basic.num_anib == 12 ||
1048 input->basic.num_anib == 13) {
1049 ck_anib_inst[0] = 4;
1050 ck_anib_inst[1] = 5;
1051 } else {
1052 ERROR("Invalid number of aNIBs: %d\n", input->basic.num_anib);
1053 return;
1054 }
1055
1056 for (anib = 0; anib < input->basic.num_anib; anib++) {
1057 c_addr = anib << 12;
1058 if (anib == ck_anib_inst[0] || anib == ck_anib_inst[1]) {
1059 atx_pre_drv_mode = 0;
1060 } else {
1061 atx_pre_drv_mode = 3;
1062 }
1063 atx_slew_rate = atx_pre_drv_mode << csr_atx_pre_drv_mode_lsb |
1064 atx_pre_n << csr_atx_pre_n_lsb |
1065 atx_pre_p << csr_atx_pre_p_lsb;
1066 addr = t_anib | c_addr | csr_atx_slew_rate_addr;
1067 phy_io_write16(phy, addr, atx_slew_rate);
1068 }
1069}
1070
1071static void prog_enable_cs_multicast(uint16_t *phy,
1072 const struct input *input)
1073{
1074 uint32_t addr = t_master | csr_enable_cs_multicast_addr;
1075
1076 if (input->basic.dimm_type != RDIMM &&
1077 input->basic.dimm_type != LRDIMM) {
1078 return;
1079 }
1080
1081 phy_io_write16(phy, addr, input->adv.cast_cs_to_cid);
1082}
1083
1084static void prog_dfi_rd_data_cs_dest_map(uint16_t *phy,
1085 unsigned int ip_rev,
1086 const struct input *input,
1087 const struct ddr4lr1d *msg)
1088{
1089 const struct ddr4lr1d *msg_blk;
1090 uint16_t dfi_xxdestm0 = 0U;
1091 uint16_t dfi_xxdestm1 = 0U;
1092 uint16_t dfi_xxdestm2 = 0U;
1093 uint16_t dfi_xxdestm3 = 0U;
1094 uint16_t dfi_rd_data_cs_dest_map;
1095 uint16_t dfi_wr_data_cs_dest_map;
1096 __unused const soc_info_t *soc_info;
1097
1098#ifdef ERRATA_DDR_A011396
1099 /* Only apply to DDRC 5.05.00 */
Jiafei Panb27ac802021-07-20 17:14:32 +08001100 soc_info = get_soc_info();
1101 if ((soc_info->svr_reg.bf.maj_ver == 1U) && (ip_rev == U(0x50500))) {
Pankaj Guptac518de42020-12-09 14:02:39 +05301102 phy_io_write16(phy,
1103 t_master | csr_dfi_rd_data_cs_dest_map_addr,
1104 0U);
1105 return;
1106 }
1107#endif
1108
1109 msg_blk = msg;
1110
1111 switch (input->basic.dimm_type) {
1112 case UDIMM:
1113 case SODIMM:
1114 case NODIMM:
1115 if ((msg_blk->msg_misc & U(0x40)) != 0U) {
1116 dfi_rd_data_cs_dest_map = U(0xa0);
1117 dfi_wr_data_cs_dest_map = U(0xa0);
1118
1119 phy_io_write16(phy,
1120 t_master | csr_dfi_rd_data_cs_dest_map_addr,
1121 dfi_rd_data_cs_dest_map);
1122 phy_io_write16(phy,
1123 t_master | csr_dfi_wr_data_cs_dest_map_addr,
1124 dfi_wr_data_cs_dest_map);
1125 }
1126 break;
1127 case LRDIMM:
1128 if (msg->cs_present_d1 != 0U) {
1129 dfi_xxdestm2 = 1U;
1130 dfi_xxdestm3 = 1U;
1131 }
1132
1133 dfi_rd_data_cs_dest_map =
1134 dfi_xxdestm0 << csr_dfi_rd_destm0_lsb |
1135 dfi_xxdestm1 << csr_dfi_rd_destm1_lsb |
1136 dfi_xxdestm2 << csr_dfi_rd_destm2_lsb |
1137 dfi_xxdestm3 << csr_dfi_rd_destm3_lsb;
1138 dfi_wr_data_cs_dest_map =
1139 dfi_xxdestm0 << csr_dfi_wr_destm0_lsb |
1140 dfi_xxdestm1 << csr_dfi_wr_destm1_lsb |
1141 dfi_xxdestm2 << csr_dfi_wr_destm2_lsb |
1142 dfi_xxdestm3 << csr_dfi_wr_destm3_lsb;
1143 phy_io_write16(phy, t_master | csr_dfi_rd_data_cs_dest_map_addr,
1144 dfi_rd_data_cs_dest_map);
1145 phy_io_write16(phy, t_master | csr_dfi_wr_data_cs_dest_map_addr,
1146 dfi_wr_data_cs_dest_map);
1147
1148 break;
1149 default:
1150 break;
1151 }
1152}
1153
1154static void prog_pll_ctrl(uint16_t *phy,
1155 const struct input *input)
1156{
1157 uint32_t addr;
1158 int pll_ctrl1 = 0x21; /* 000100001b */
1159 int pll_ctrl4 = 0x17f; /* 101111111b */
1160 int pll_test_mode = 0x24; /* 00100100b */
1161
1162 addr = t_master | csr_pll_ctrl1_addr;
1163 phy_io_write16(phy, addr, pll_ctrl1);
1164
1165 debug("pll_ctrl1 = 0x%x\n", phy_io_read16(phy, addr));
1166
1167 addr = t_master | csr_pll_test_mode_addr;
1168 phy_io_write16(phy, addr, pll_test_mode);
1169
1170 debug("pll_test_mode = 0x%x\n", phy_io_read16(phy, addr));
1171
1172 addr = t_master | csr_pll_ctrl4_addr;
1173 phy_io_write16(phy, addr, pll_ctrl4);
1174
1175 debug("pll_ctrl4 = 0x%x\n", phy_io_read16(phy, addr));
1176}
1177
1178static void prog_pll_ctrl2(uint16_t *phy,
1179 const struct input *input)
1180{
1181 int pll_ctrl2;
1182 uint32_t addr = t_master | csr_pll_ctrl2_addr;
1183
1184 if (input->basic.frequency / 2 < 235) {
1185 pll_ctrl2 = 0x7;
1186 } else if (input->basic.frequency / 2 < 313) {
1187 pll_ctrl2 = 0x6;
1188 } else if (input->basic.frequency / 2 < 469) {
1189 pll_ctrl2 = 0xb;
1190 } else if (input->basic.frequency / 2 < 625) {
1191 pll_ctrl2 = 0xa;
1192 } else if (input->basic.frequency / 2 < 938) {
1193 pll_ctrl2 = 0x19;
1194 } else if (input->basic.frequency / 2 < 1067) {
1195 pll_ctrl2 = 0x18;
1196 } else {
1197 pll_ctrl2 = 0x19;
1198 }
1199
1200 phy_io_write16(phy, addr, pll_ctrl2);
1201
1202 debug("pll_ctrl2 = 0x%x\n", phy_io_read16(phy, addr));
1203}
1204
1205static void prog_dll_lck_param(uint16_t *phy, const struct input *input)
1206{
1207 uint32_t addr = t_master | csr_dll_lockparam_addr;
1208
1209 phy_io_write16(phy, addr, U(0x212));
1210 debug("dll_lck_param = 0x%x\n", phy_io_read16(phy, addr));
1211}
1212
1213static void prog_dll_gain_ctl(uint16_t *phy, const struct input *input)
1214{
1215 uint32_t addr = t_master | csr_dll_gain_ctl_addr;
1216
1217 phy_io_write16(phy, addr, U(0x61));
1218 debug("dll_gain_ctl = 0x%x\n", phy_io_read16(phy, addr));
1219}
1220
1221static void prog_pll_pwr_dn(uint16_t *phy,
1222 const struct input *input)
1223{
1224 uint32_t addr;
1225
1226 addr = t_master | csr_pll_pwr_dn_addr;
1227 phy_io_write16(phy, addr, 0U);
1228
1229 debug("pll_pwrdn = 0x%x\n", phy_io_read16(phy, addr));
1230}
1231
1232static void prog_ard_ptr_init_val(uint16_t *phy,
1233 const struct input *input)
1234{
1235 int ard_ptr_init_val;
1236 uint32_t addr = t_master | csr_ard_ptr_init_val_addr;
1237
1238 if (input->basic.frequency >= 933) {
1239 ard_ptr_init_val = 0x2;
1240 } else {
1241 ard_ptr_init_val = 0x1;
1242 }
1243
1244 phy_io_write16(phy, addr, ard_ptr_init_val);
1245}
1246
1247static void prog_dqs_preamble_control(uint16_t *phy,
1248 const struct input *input)
1249{
1250 int data;
1251 uint32_t addr = t_master | csr_dqs_preamble_control_addr;
1252 const int wdqsextension = 0;
1253 const int lp4sttc_pre_bridge_rx_en = 0;
1254 const int lp4postamble_ext = 0;
1255 const int lp4tgl_two_tck_tx_dqs_pre = 0;
1256 const int position_dfe_init = 2;
1257 const int dll_rx_preamble_mode = 1;
1258 int two_tck_tx_dqs_pre = input->adv.d4tx_preamble_length;
1259 int two_tck_rx_dqs_pre = input->adv.d4rx_preamble_length;
1260
1261 data = wdqsextension << csr_wdqsextension_lsb |
1262 lp4sttc_pre_bridge_rx_en << csr_lp4sttc_pre_bridge_rx_en_lsb |
1263 lp4postamble_ext << csr_lp4postamble_ext_lsb |
1264 lp4tgl_two_tck_tx_dqs_pre << csr_lp4tgl_two_tck_tx_dqs_pre_lsb |
1265 position_dfe_init << csr_position_dfe_init_lsb |
1266 two_tck_tx_dqs_pre << csr_two_tck_tx_dqs_pre_lsb |
1267 two_tck_rx_dqs_pre << csr_two_tck_rx_dqs_pre_lsb;
1268 phy_io_write16(phy, addr, data);
1269
1270 data = dll_rx_preamble_mode << csr_dll_rx_preamble_mode_lsb;
1271 addr = t_master | csr_dbyte_dll_mode_cntrl_addr;
1272 phy_io_write16(phy, addr, data);
1273}
1274
1275static void prog_proc_odt_time_ctl(uint16_t *phy,
1276 const struct input *input)
1277{
1278 int proc_odt_time_ctl;
1279 uint32_t addr = t_master | csr_proc_odt_time_ctl_addr;
1280
1281 if (input->adv.wdqsext != 0) {
1282 proc_odt_time_ctl = 0x3;
1283 } else if (input->basic.frequency <= 933) {
1284 proc_odt_time_ctl = 0xa;
1285 } else if (input->basic.frequency <= 1200) {
1286 if (input->adv.d4rx_preamble_length == 1) {
1287 proc_odt_time_ctl = 0x2;
1288 } else {
1289 proc_odt_time_ctl = 0x6;
1290 }
1291 } else {
1292 if (input->adv.d4rx_preamble_length == 1) {
1293 proc_odt_time_ctl = 0x3;
1294 } else {
1295 proc_odt_time_ctl = 0x7;
1296 }
1297 }
1298 phy_io_write16(phy, addr, proc_odt_time_ctl);
1299}
1300
1301static const struct impedance_mapping map[] = {
1302 { 29, 0x3f },
1303 { 31, 0x3e },
1304 { 33, 0x3b },
1305 { 36, 0x3a },
1306 { 39, 0x39 },
1307 { 42, 0x38 },
1308 { 46, 0x1b },
1309 { 51, 0x1a },
1310 { 57, 0x19 },
1311 { 64, 0x18 },
1312 { 74, 0x0b },
1313 { 88, 0x0a },
1314 { 108, 0x09 },
1315 { 140, 0x08 },
1316 { 200, 0x03 },
1317 { 360, 0x02 },
1318 { 481, 0x01 },
1319 {}
1320};
1321
1322static int map_impedance(int strength)
1323{
1324 const struct impedance_mapping *tbl = map;
1325 int val = 0;
1326
1327 if (strength == 0) {
1328 return 0;
1329 }
1330
1331 while (tbl->ohm != 0U) {
1332 if (strength < tbl->ohm) {
1333 val = tbl->code;
1334 break;
1335 }
1336 tbl++;
1337 }
1338
1339 return val;
1340}
1341
1342static int map_odtstren_p(int strength, int hard_macro_ver)
1343{
1344 int val = -1;
1345
1346 if (hard_macro_ver == 4) {
1347 if (strength == 0) {
1348 val = 0;
1349 } else if (strength == 120) {
1350 val = 0x8;
1351 } else if (strength == 60) {
1352 val = 0x18;
1353 } else if (strength == 40) {
1354 val = 0x38;
1355 } else {
1356 printf("error: unsupported ODTStrenP %d\n", strength);
1357 }
1358 } else {
1359 val = map_impedance(strength);
1360 }
1361
1362 return val;
1363}
1364
1365static void prog_tx_odt_drv_stren(uint16_t *phy,
1366 const struct input *input)
1367{
1368 int lane, byte, b_addr, c_addr;
1369 int tx_odt_drv_stren;
1370 int odtstren_p, odtstren_n;
1371 uint32_t addr;
1372
1373 odtstren_p = map_odtstren_p(input->adv.odtimpedance,
1374 input->basic.hard_macro_ver);
1375 if (odtstren_p < 0) {
1376 return;
1377 }
1378
1379 odtstren_n = 0; /* always high-z */
1380 tx_odt_drv_stren = odtstren_n << csr_odtstren_n_lsb | odtstren_p;
1381 for (byte = 0; byte < input->basic.num_dbyte; byte++) {
1382 c_addr = byte << 12;
1383 for (lane = 0; lane <= 1; lane++) {
1384 b_addr = lane << 8;
1385 addr = t_dbyte | c_addr | b_addr |
1386 csr_tx_odt_drv_stren_addr;
1387 phy_io_write16(phy, addr, tx_odt_drv_stren);
1388 }
1389 }
1390}
1391
1392static int map_drvstren_fsdq_p(int strength, int hard_macro_ver)
1393{
1394 int val = -1;
1395
1396 if (hard_macro_ver == 4) {
1397 if (strength == 0) {
1398 val = 0x07;
1399 } else if (strength == 120) {
1400 val = 0x0F;
1401 } else if (strength == 60) {
1402 val = 0x1F;
1403 } else if (strength == 40) {
1404 val = 0x3F;
1405 } else {
1406 printf("error: unsupported drv_stren_fSDq_p %d\n",
1407 strength);
1408 }
1409 } else {
1410 val = map_impedance(strength);
1411 }
1412
1413 return val;
1414}
1415
1416static int map_drvstren_fsdq_n(int strength, int hard_macro_ver)
1417{
1418 int val = -1;
1419
1420 if (hard_macro_ver == 4) {
1421 if (strength == 0) {
1422 val = 0x00;
1423 } else if (strength == 120) {
1424 val = 0x08;
1425 } else if (strength == 60) {
1426 val = 0x18;
1427 } else if (strength == 40) {
1428 val = 0x38;
1429 } else {
1430 printf("error: unsupported drvStrenFSDqN %d\n",
1431 strength);
1432 }
1433 } else {
1434 val = map_impedance(strength);
1435 }
1436
1437 return val;
1438}
1439
1440static void prog_tx_impedance_ctrl1(uint16_t *phy,
1441 const struct input *input)
1442{
1443 int lane, byte, b_addr, c_addr;
1444 int tx_impedance_ctrl1;
1445 int drv_stren_fsdq_p, drv_stren_fsdq_n;
1446 uint32_t addr;
1447
1448 drv_stren_fsdq_p = map_drvstren_fsdq_p(input->adv.tx_impedance,
1449 input->basic.hard_macro_ver);
1450 drv_stren_fsdq_n = map_drvstren_fsdq_n(input->adv.tx_impedance,
1451 input->basic.hard_macro_ver);
1452 tx_impedance_ctrl1 = drv_stren_fsdq_n << csr_drv_stren_fsdq_n_lsb |
1453 drv_stren_fsdq_p << csr_drv_stren_fsdq_p_lsb;
1454
1455 for (byte = 0; byte < input->basic.num_dbyte; byte++) {
1456 c_addr = byte << 12;
1457 for (lane = 0; lane <= 1; lane++) {
1458 b_addr = lane << 8;
1459 addr = t_dbyte | c_addr | b_addr |
1460 csr_tx_impedance_ctrl1_addr;
1461 phy_io_write16(phy, addr, tx_impedance_ctrl1);
1462 }
1463 }
1464}
1465
1466static int map_adrv_stren_p(int strength, int hard_macro_ver)
1467{
1468 int val = -1;
1469
1470 if (hard_macro_ver == 4) {
1471 if (strength == 120) {
1472 val = 0x1c;
1473 } else if (strength == 60) {
1474 val = 0x1d;
1475 } else if (strength == 40) {
1476 val = 0x1f;
1477 } else {
1478 printf("error: unsupported aDrv_stren_p %d\n",
1479 strength);
1480 }
1481 } else {
1482 if (strength == 120) {
1483 val = 0x00;
1484 } else if (strength == 60) {
1485 val = 0x01;
1486 } else if (strength == 40) {
1487 val = 0x03;
1488 } else if (strength == 30) {
1489 val = 0x07;
1490 } else if (strength == 24) {
1491 val = 0x0f;
1492 } else if (strength == 20) {
1493 val = 0x1f;
1494 } else {
1495 printf("error: unsupported aDrv_stren_p %d\n",
1496 strength);
1497 }
1498 }
1499
1500 return val;
1501}
1502
1503static int map_adrv_stren_n(int strength, int hard_macro_ver)
1504{
1505 int val = -1;
1506
1507 if (hard_macro_ver == 4) {
1508 if (strength == 120) {
1509 val = 0x00;
1510 } else if (strength == 60) {
1511 val = 0x01;
1512 } else if (strength == 40) {
1513 val = 0x03;
1514 } else {
1515 printf("Error: unsupported ADrvStrenP %d\n", strength);
1516 }
1517 } else {
1518 if (strength == 120) {
1519 val = 0x00;
1520 } else if (strength == 60) {
1521 val = 0x01;
1522 } else if (strength == 40) {
1523 val = 0x03;
1524 } else if (strength == 30) {
1525 val = 0x07;
1526 } else if (strength == 24) {
1527 val = 0x0f;
1528 } else if (strength == 20) {
1529 val = 0x1f;
1530 } else {
1531 printf("Error: unsupported ADrvStrenP %d\n", strength);
1532 }
1533 }
1534
1535 return val;
1536}
1537
1538static void prog_atx_impedance(uint16_t *phy,
1539 const struct input *input)
1540{
1541 int anib, c_addr;
1542 int atx_impedance;
1543 int adrv_stren_p;
1544 int adrv_stren_n;
1545 uint32_t addr;
1546
1547 if (input->basic.hard_macro_ver == 4 &&
1548 input->adv.atx_impedance == 20) {
1549 printf("Error:ATxImpedance has to be 40 for HardMacroVer 4\n");
1550 return;
1551 }
1552
1553 adrv_stren_p = map_adrv_stren_p(input->adv.atx_impedance,
1554 input->basic.hard_macro_ver);
1555 adrv_stren_n = map_adrv_stren_n(input->adv.atx_impedance,
1556 input->basic.hard_macro_ver);
1557 atx_impedance = adrv_stren_n << csr_adrv_stren_n_lsb |
1558 adrv_stren_p << csr_adrv_stren_p_lsb;
1559 for (anib = 0; anib < input->basic.num_anib; anib++) {
1560 c_addr = anib << 12;
1561 addr = t_anib | c_addr | csr_atx_impedance_addr;
1562 phy_io_write16(phy, addr, atx_impedance);
1563 }
1564}
1565
1566static void prog_dfi_mode(uint16_t *phy,
1567 const struct input *input)
1568{
1569 int dfi_mode;
1570 uint32_t addr;
1571
1572 if (input->basic.dfi1exists == 1) {
1573 dfi_mode = 0x5; /* DFI1 exists but disabled */
1574 } else {
1575 dfi_mode = 0x1; /* DFI1 does not physically exists */
1576 }
1577 addr = t_master | csr_dfi_mode_addr;
1578 phy_io_write16(phy, addr, dfi_mode);
1579}
1580
1581static void prog_acx4_anib_dis(uint16_t *phy, const struct input *input)
1582{
1583 uint32_t addr;
1584
1585 addr = t_master | csr_acx4_anib_dis_addr;
1586 phy_io_write16(phy, addr, 0x0);
1587 debug("%s 0x%x\n", __func__, phy_io_read16(phy, addr));
1588}
1589
1590static void prog_dfi_camode(uint16_t *phy,
1591 const struct input *input)
1592{
1593 int dfi_camode = 2;
1594 uint32_t addr = t_master | csr_dfi_camode_addr;
1595
1596 phy_io_write16(phy, addr, dfi_camode);
1597}
1598
1599static void prog_cal_drv_str0(uint16_t *phy,
1600 const struct input *input)
1601{
1602 int cal_drv_str0;
1603 int cal_drv_str_pd50;
1604 int cal_drv_str_pu50;
1605 uint32_t addr;
1606
1607 cal_drv_str_pu50 = input->adv.ext_cal_res_val;
1608 cal_drv_str_pd50 = cal_drv_str_pu50;
1609 cal_drv_str0 = cal_drv_str_pu50 << csr_cal_drv_str_pu50_lsb |
1610 cal_drv_str_pd50;
1611 addr = t_master | csr_cal_drv_str0_addr;
1612 phy_io_write16(phy, addr, cal_drv_str0);
1613}
1614
1615static void prog_cal_uclk_info(uint16_t *phy,
1616 const struct input *input)
1617{
1618 int cal_uclk_ticks_per1u_s;
1619 uint32_t addr;
1620
1621 cal_uclk_ticks_per1u_s = input->basic.frequency >> 1;
1622 if (cal_uclk_ticks_per1u_s < 24) {
1623 cal_uclk_ticks_per1u_s = 24;
1624 }
1625
1626 addr = t_master | csr_cal_uclk_info_addr;
1627 phy_io_write16(phy, addr, cal_uclk_ticks_per1u_s);
1628}
1629
1630static void prog_cal_rate(uint16_t *phy,
1631 const struct input *input)
1632{
1633 int cal_rate;
1634 int cal_interval;
1635 int cal_once;
1636 uint32_t addr;
1637
1638 cal_interval = input->adv.cal_interval;
1639 cal_once = input->adv.cal_once;
1640 cal_rate = cal_once << csr_cal_once_lsb |
1641 cal_interval << csr_cal_interval_lsb;
1642 addr = t_master | csr_cal_rate_addr;
1643 phy_io_write16(phy, addr, cal_rate);
1644}
1645
1646static void prog_vref_in_global(uint16_t *phy,
1647 const struct input *input,
1648 const struct ddr4u1d *msg)
1649{
1650 int vref_in_global;
1651 int global_vref_in_dac = 0;
1652 int global_vref_in_sel = 0;
1653 uint32_t addr;
1654
1655 /*
1656 * phy_vref_prcnt = msg->phy_vref / 128.0
1657 * global_vref_in_dac = (phy_vref_prcnt - 0.345) / 0.005;
1658 */
1659 global_vref_in_dac = (msg->phy_vref * 1000 - 345 * 128 + 320) /
1660 (5 * 128);
1661
1662 vref_in_global = global_vref_in_dac << csr_global_vref_in_dac_lsb |
1663 global_vref_in_sel;
1664 addr = t_master | csr_vref_in_global_addr;
1665 phy_io_write16(phy, addr, vref_in_global);
1666}
1667
1668static void prog_dq_dqs_rcv_cntrl(uint16_t *phy,
1669 const struct input *input)
1670{
1671 int lane, byte, b_addr, c_addr;
1672 int dq_dqs_rcv_cntrl;
1673 int gain_curr_adj_defval = 0xb;
1674 int major_mode_dbyte = 3;
1675 int dfe_ctrl_defval = 0;
1676 int ext_vref_range_defval = 0;
1677 int sel_analog_vref = 1;
1678 uint32_t addr;
1679
Pankit Gargdadba6e2021-07-13 13:40:06 +05301680#ifdef ERRATA_DDR_A050958
1681 gain_curr_adj_defval = 0x1f;
1682#endif
1683
Pankaj Guptac518de42020-12-09 14:02:39 +05301684 dq_dqs_rcv_cntrl = gain_curr_adj_defval << csr_gain_curr_adj_lsb |
1685 major_mode_dbyte << csr_major_mode_dbyte_lsb |
1686 dfe_ctrl_defval << csr_dfe_ctrl_lsb |
1687 ext_vref_range_defval << csr_ext_vref_range_lsb |
1688 sel_analog_vref << csr_sel_analog_vref_lsb;
1689 for (byte = 0; byte < input->basic.num_dbyte; byte++) {
1690 c_addr = byte << 12;
1691 for (lane = 0; lane <= 1; lane++) {
1692 b_addr = lane << 8;
1693 addr = t_dbyte | c_addr | b_addr |
1694 csr_dq_dqs_rcv_cntrl_addr;
1695 phy_io_write16(phy, addr, dq_dqs_rcv_cntrl);
1696 }
1697 }
1698}
1699
1700static void prog_mem_alert_control(uint16_t *phy,
1701 const struct input *input)
1702{
1703 int mem_alert_control;
1704 int mem_alert_control2;
1705 int malertpu_en;
1706 int malertrx_en;
1707 int malertvref_level;
1708 int malertpu_stren;
1709 int malertsync_bypass;
1710 int malertdisable_val_defval = 1;
1711 uint32_t addr;
1712
1713 if (input->basic.dram_type == DDR4 && input->adv.mem_alert_en == 1) {
1714 malertpu_en = 1;
1715 malertrx_en = 1;
1716 malertpu_stren = input->adv.mem_alert_puimp;
1717 malertvref_level = input->adv.mem_alert_vref_level;
1718 malertsync_bypass = input->adv.mem_alert_sync_bypass;
1719 mem_alert_control = malertdisable_val_defval << 14 |
1720 malertrx_en << 13 |
1721 malertpu_en << 12 |
1722 malertpu_stren << 8 |
1723 malertvref_level;
1724 mem_alert_control2 = malertsync_bypass <<
1725 csr_malertsync_bypass_lsb;
1726 addr = t_master | csr_mem_alert_control_addr;
1727 phy_io_write16(phy, addr, mem_alert_control);
1728 addr = t_master | csr_mem_alert_control2_addr;
1729 phy_io_write16(phy, addr, mem_alert_control2);
1730 }
1731}
1732
1733static void prog_dfi_freq_ratio(uint16_t *phy,
1734 const struct input *input)
1735{
1736 int dfi_freq_ratio;
1737 uint32_t addr = t_master | csr_dfi_freq_ratio_addr;
1738
1739 dfi_freq_ratio = input->basic.dfi_freq_ratio;
1740 phy_io_write16(phy, addr, dfi_freq_ratio);
1741}
1742
1743static void prog_tristate_mode_ca(uint16_t *phy,
1744 const struct input *input)
1745{
1746 int tristate_mode_ca;
1747 int dis_dyn_adr_tri;
1748 int ddr2tmode;
1749 int ck_dis_val_def = 1;
1750 uint32_t addr = t_master | csr_tristate_mode_ca_addr;
1751
1752 dis_dyn_adr_tri = input->adv.dis_dyn_adr_tri;
1753 ddr2tmode = input->adv.is2ttiming;
1754 tristate_mode_ca = ck_dis_val_def << csr_ck_dis_val_lsb |
1755 ddr2tmode << csr_ddr2tmode_lsb |
1756 dis_dyn_adr_tri << csr_dis_dyn_adr_tri_lsb;
1757 phy_io_write16(phy, addr, tristate_mode_ca);
1758}
1759
1760static void prog_dfi_xlat(uint16_t *phy,
1761 const struct input *input)
1762{
1763 uint16_t loop_vector;
1764 int dfifreqxlat_dat;
1765 int pllbypass_dat;
1766 uint32_t addr;
1767
1768 /* fIXME: Shall unused P1, P2, P3 be bypassed? */
1769 pllbypass_dat = input->basic.pll_bypass; /* only [0] is used */
1770 for (loop_vector = 0; loop_vector < 8; loop_vector++) {
1771 if (loop_vector == 0) {
1772 dfifreqxlat_dat = pllbypass_dat + 0x5555;
1773 } else if (loop_vector == 7) {
1774 dfifreqxlat_dat = 0xf000;
1775 } else {
1776 dfifreqxlat_dat = 0x5555;
1777 }
1778 addr = t_master | (csr_dfi_freq_xlat0_addr + loop_vector);
1779 phy_io_write16(phy, addr, dfifreqxlat_dat);
1780 }
1781}
1782
1783static void prog_dbyte_misc_mode(uint16_t *phy,
1784 const struct input *input,
1785 const struct ddr4u1d *msg)
1786{
1787 int dbyte_misc_mode;
1788 int dq_dqs_rcv_cntrl1;
1789 int dq_dqs_rcv_cntrl1_1;
1790 int byte, c_addr;
1791 uint32_t addr;
1792
1793 dbyte_misc_mode = 0x1 << csr_dbyte_disable_lsb;
1794 dq_dqs_rcv_cntrl1 = 0x1ff << csr_power_down_rcvr_lsb |
1795 0x1 << csr_power_down_rcvr_dqs_lsb |
1796 0x1 << csr_rx_pad_standby_en_lsb;
1797 dq_dqs_rcv_cntrl1_1 = (0x100 << csr_power_down_rcvr_lsb |
1798 csr_rx_pad_standby_en_mask);
1799 for (byte = 0; byte < input->basic.num_dbyte; byte++) {
1800 c_addr = byte << 12;
1801 if (byte <= input->basic.num_active_dbyte_dfi0 - 1) {
1802 /* disable RDBI lane if not used. */
1803 if ((input->basic.dram_data_width != 4) &&
1804 (((msg->mr5 >> 12) & 0x1) == 0)) {
1805 addr = t_dbyte
1806 | c_addr
1807 | csr_dq_dqs_rcv_cntrl1_addr;
1808 phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1_1);
1809 }
1810 } else {
1811 addr = t_dbyte | c_addr | csr_dbyte_misc_mode_addr;
1812 phy_io_write16(phy, addr, dbyte_misc_mode);
1813 addr = t_dbyte | c_addr | csr_dq_dqs_rcv_cntrl1_addr;
1814 phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1);
1815 }
1816 }
1817}
1818
1819static void prog_master_x4config(uint16_t *phy,
1820 const struct input *input)
1821{
1822 int master_x4config;
1823 int x4tg;
1824 uint32_t addr = t_master | csr_master_x4config_addr;
1825
1826 x4tg = input->basic.dram_data_width == 4 ? 0xf : 0;
1827 master_x4config = x4tg << csr_x4tg_lsb;
1828 phy_io_write16(phy, addr, master_x4config);
1829}
1830
1831static void prog_dmipin_present(uint16_t *phy,
1832 const struct input *input,
1833 const struct ddr4u1d *msg)
1834{
1835 int dmipin_present;
1836 uint32_t addr = t_master | csr_dmipin_present_addr;
1837
1838 dmipin_present = (msg->mr5 >> 12) & 0x1;
1839 phy_io_write16(phy, addr, dmipin_present);
1840}
1841
1842static void prog_dfi_phyupd(uint16_t *phy,
1843 const struct input *input)
1844{
1845 int dfiphyupd_dat;
1846 uint32_t addr;
1847
1848 addr = t_master | (csr_dfiphyupd_addr);
1849 dfiphyupd_dat = phy_io_read16(phy, addr) &
1850 ~csr_dfiphyupd_threshold_mask;
1851
1852 phy_io_write16(phy, addr, dfiphyupd_dat);
1853}
1854
1855static void prog_cal_misc2(uint16_t *phy,
1856 const struct input *input)
1857{
1858 int cal_misc2_dat, cal_drv_pdth_data, cal_offsets_dat;
1859 uint32_t addr;
1860
1861 addr = t_master | (csr_cal_misc2_addr);
1862 cal_misc2_dat = phy_io_read16(phy, addr) |
1863 (1 << csr_cal_misc2_err_dis);
1864
1865 phy_io_write16(phy, addr, cal_misc2_dat);
1866
1867 addr = t_master | (csr_cal_offsets_addr);
1868
1869 cal_drv_pdth_data = 0x9 << 6;
1870 cal_offsets_dat = (phy_io_read16(phy, addr) & ~csr_cal_drv_pdth_mask)
1871 | cal_drv_pdth_data;
1872
1873 phy_io_write16(phy, addr, cal_offsets_dat);
1874}
1875
1876static int c_init_phy_config(uint16_t **phy_ptr,
1877 unsigned int ip_rev,
1878 const struct input *input,
1879 const void *msg)
1880{
1881 int i;
1882 uint16_t *phy;
1883 __unused const soc_info_t *soc_info;
1884
1885 for (i = 0; i < NUM_OF_DDRC; i++) {
1886 phy = phy_ptr[i];
1887 if (phy == NULL) {
1888 continue;
1889 }
1890
1891 debug("Initialize PHY %d config\n", i);
1892 prog_dfi_phyupd(phy, input);
1893 prog_cal_misc2(phy, input);
1894 prog_tx_pre_drv_mode(phy, input);
1895 prog_atx_pre_drv_mode(phy, input);
1896 prog_enable_cs_multicast(phy, input); /* rdimm and lrdimm */
1897 prog_dfi_rd_data_cs_dest_map(phy, ip_rev, input, msg);
1898 prog_pll_ctrl2(phy, input);
1899#ifdef DDR_PLL_FIX
1900 soc_info = get_soc_info();
Jiafei Panb27ac802021-07-20 17:14:32 +08001901 debug("SOC_SI_REV = %x\n", soc_info->svr_reg.bf.maj_ver);
1902 if (soc_info->svr_reg.bf.maj_ver == 1) {
Pankaj Guptac518de42020-12-09 14:02:39 +05301903 prog_pll_pwr_dn(phy, input);
1904
1905 /*Enable FFE aka TxEqualizationMode for rev1 SI*/
1906 phy_io_write16(phy, 0x010048, 0x1);
1907 }
1908#endif
1909 prog_ard_ptr_init_val(phy, input);
1910 prog_dqs_preamble_control(phy, input);
1911 prog_dll_lck_param(phy, input);
1912 prog_dll_gain_ctl(phy, input);
1913 prog_proc_odt_time_ctl(phy, input);
1914 prog_tx_odt_drv_stren(phy, input);
1915 prog_tx_impedance_ctrl1(phy, input);
1916 prog_atx_impedance(phy, input);
1917 prog_dfi_mode(phy, input);
1918 prog_dfi_camode(phy, input);
1919 prog_cal_drv_str0(phy, input);
1920 prog_cal_uclk_info(phy, input);
1921 prog_cal_rate(phy, input);
1922 prog_vref_in_global(phy, input, msg);
1923 prog_dq_dqs_rcv_cntrl(phy, input);
1924 prog_mem_alert_control(phy, input);
1925 prog_dfi_freq_ratio(phy, input);
1926 prog_tristate_mode_ca(phy, input);
1927 prog_dfi_xlat(phy, input);
1928 prog_dbyte_misc_mode(phy, input, msg);
1929 prog_master_x4config(phy, input);
1930 prog_dmipin_present(phy, input, msg);
1931 prog_acx4_anib_dis(phy, input);
1932 }
1933
1934 return 0;
1935}
1936
1937static uint32_t get_mail(uint16_t *phy, int stream)
1938{
1939 int timeout;
1940 uint32_t mail = 0U;
1941
1942 timeout = TIMEOUTDEFAULT;
1943 while (((--timeout) != 0) &&
1944 ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs)
1945 & uct_write_prot_shadow_mask) != 0)) {
1946 mdelay(10);
1947 }
1948 if (timeout == 0) {
1949 ERROR("Timeout getting mail from PHY\n");
1950 return 0xFFFF;
1951 }
1952
1953 mail = phy_io_read16(phy, t_apbonly |
1954 csr_uct_write_only_shadow);
1955 if (stream != 0) {
1956 mail |= phy_io_read16(phy, t_apbonly |
1957 csr_uct_dat_write_only_shadow) << 16;
1958 }
1959
1960 /* Ack */
1961 phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 0);
1962
1963 timeout = TIMEOUTDEFAULT;
1964 while (((--timeout) != 0) &&
1965 ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs)
1966 & uct_write_prot_shadow_mask) == 0)) {
1967 mdelay(1);
1968 }
1969 if (timeout == 0) {
1970 ERROR("Timeout ack PHY mail\n");
1971 }
1972
1973 /* completed */
1974 phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 1U);
1975
1976 return mail;
1977}
1978
1979#ifdef DDR_PHY_DEBUG
1980static const char *lookup_msg(uint32_t index, int train2d)
1981{
1982 int i;
1983 int size;
1984 const struct phy_msg *messages;
1985 const char *ptr = NULL;
1986
1987 if (train2d != 0) {
1988 messages = messages_2d;
1989 size = ARRAY_SIZE(messages_2d);
1990 } else {
1991 messages = messages_1d;
1992 size = ARRAY_SIZE(messages_1d);
1993 }
1994 for (i = 0; i < size; i++) {
1995 if (messages[i].index == index) {
1996 ptr = messages[i].msg;
1997 break;
1998 }
1999 }
2000
2001 return ptr;
2002}
2003#endif
2004
2005#define MAX_ARGS 32
2006static void decode_stream_message(uint16_t *phy, int train2d)
2007{
2008 uint32_t index __unused;
2009
2010 __unused const char *format;
2011 __unused uint32_t args[MAX_ARGS];
2012 __unused int i;
2013
2014#ifdef DDR_PHY_DEBUG
2015 index = get_mail(phy, 1);
2016 if ((index & 0xffff) > MAX_ARGS) { /* up to MAX_ARGS args so far */
2017 printf("Program error in %s\n", __func__);
2018 }
2019 for (i = 0; i < (index & 0xffff) && i < MAX_ARGS; i++) {
2020 args[i] = get_mail(phy, 1);
2021 }
2022
2023 format = lookup_msg(index, train2d);
2024 if (format != NULL) {
2025 printf("0x%08x: ", index);
2026 printf(format, args[0], args[1], args[2], args[3], args[4],
2027 args[5], args[6], args[7], args[8], args[9], args[10],
2028 args[11], args[12], args[13], args[14], args[15],
2029 args[16], args[17], args[18], args[19], args[20],
2030 args[21], args[22], args[23], args[24], args[25],
2031 args[26], args[27], args[28], args[29], args[30],
2032 args[31]);
2033 }
2034#endif
2035}
2036
2037static int wait_fw_done(uint16_t *phy, int train2d)
2038{
2039 uint32_t mail = 0U;
2040
2041 while (mail == U(0x0)) {
2042 mail = get_mail(phy, 0);
2043 switch (mail) {
2044 case U(0x7):
2045 debug("%s Training completed\n", train2d ? "2D" : "1D");
2046 break;
2047 case U(0xff):
2048 debug("%s Training failure\n", train2d ? "2D" : "1D");
2049 break;
2050 case U(0x0):
2051 debug("End of initialization\n");
2052 mail = 0U;
2053 break;
2054 case U(0x1):
2055 debug("End of fine write leveling\n");
2056 mail = 0U;
2057 break;
2058 case U(0x2):
2059 debug("End of read enable training\n");
2060 mail = 0U;
2061 break;
2062 case U(0x3):
2063 debug("End of read delay center optimization\n");
2064 mail = 0U;
2065 break;
2066 case U(0x4):
2067 debug("End of write delay center optimization\n");
2068 mail = 0U;
2069 break;
2070 case U(0x5):
2071 debug("End of 2D read delay/voltage center optimztn\n");
2072 mail = 0U;
2073 break;
2074 case U(0x6):
2075 debug("End of 2D write delay/voltage center optmztn\n");
2076 mail = 0U;
2077 break;
2078 case U(0x8):
2079 decode_stream_message(phy, train2d);
2080 mail = 0U;
2081 break;
2082 case U(0x9):
2083 debug("End of max read latency training\n");
2084 mail = 0U;
2085 break;
2086 case U(0xa):
2087 debug("End of read dq deskew training\n");
2088 mail = 0U;
2089 break;
2090 case U(0xc):
2091 debug("End of LRDIMM Specific training, including:\n");
2092 debug("/tDWL, MREP, MRD and MWD\n");
2093 mail = 0U;
2094 break;
2095 case U(0xd):
2096 debug("End of CA training\n");
2097 mail = 0U;
2098 break;
2099 case U(0xfd):
2100 debug("End of MPR read delay center optimization\n");
2101 mail = 0U;
2102 break;
2103 case U(0xfe):
2104 debug("End of Write leveling coarse delay\n");
2105 mail = 0U;
2106 break;
2107 case U(0xffff):
2108 debug("Timed out\n");
2109 break;
2110 default:
2111 mail = 0U;
2112 break;
2113 }
2114 }
2115
2116 if (mail == U(0x7)) {
2117 return 0;
2118 } else if (mail == U(0xff)) {
2119 return -EIO;
2120 } else if (mail == U(0xffff)) {
2121 return -ETIMEDOUT;
2122 }
2123
2124 debug("PHY_GEN2 FW: Unxpected mail = 0x%x\n", mail);
2125
2126 return -EINVAL;
2127}
2128
2129static int g_exec_fw(uint16_t **phy_ptr, int train2d, struct input *input)
2130{
2131 int ret = -EINVAL;
2132 int i;
2133 uint16_t *phy;
2134
2135 for (i = 0; i < NUM_OF_DDRC; i++) {
2136 phy = phy_ptr[i];
2137 if (phy == NULL) {
2138 continue;
2139 }
2140 debug("Applying PLL optimal settings\n");
2141 prog_pll_ctrl2(phy, input);
2142 prog_pll_ctrl(phy, input);
2143 phy_io_write16(phy,
2144 t_apbonly | csr_micro_cont_mux_sel_addr,
2145 0x1);
2146 phy_io_write16(phy,
2147 t_apbonly | csr_micro_reset_addr,
2148 csr_reset_to_micro_mask |
2149 csr_stall_to_micro_mask);
2150 phy_io_write16(phy,
2151 t_apbonly | csr_micro_reset_addr,
2152 csr_stall_to_micro_mask);
2153 phy_io_write16(phy,
2154 t_apbonly | csr_micro_reset_addr,
2155 0);
2156
2157 ret = wait_fw_done(phy, train2d);
2158 if (ret == -ETIMEDOUT) {
2159 ERROR("Wait timed out: Firmware execution on PHY %d\n",
2160 i);
2161 }
2162 }
2163 return ret;
2164}
2165
2166static inline int send_fw(uint16_t *phy,
2167 uint32_t dst,
2168 uint16_t *img,
2169 uint32_t size)
2170{
2171 uint32_t i;
2172
2173 if ((size % 2U) != 0U) {
2174 ERROR("Wrong image size 0x%x\n", size);
2175 return -EINVAL;
2176 }
2177
2178 for (i = 0U; i < size / 2; i++) {
2179 phy_io_write16(phy, dst + i, *(img + i));
2180 }
2181
2182 return 0;
2183}
2184
2185static int load_fw(uint16_t **phy_ptr,
2186 struct input *input,
2187 int train2d,
2188 void *msg,
2189 size_t len,
2190 uintptr_t phy_gen2_fw_img_buf,
2191 int (*img_loadr)(unsigned int, uintptr_t *, uint32_t *),
2192 uint32_t warm_boot_flag)
2193{
2194 uint32_t imem_id, dmem_id;
2195 uintptr_t image_buf;
2196 uint32_t size;
2197 int ret;
2198 int i;
2199 uint16_t *phy;
2200
2201 switch (input->basic.dimm_type) {
2202 case UDIMM:
2203 case SODIMM:
2204 case NODIMM:
2205 imem_id = train2d ? DDR_IMEM_UDIMM_2D_IMAGE_ID :
2206 DDR_IMEM_UDIMM_1D_IMAGE_ID;
2207 dmem_id = train2d ? DDR_DMEM_UDIMM_2D_IMAGE_ID :
2208 DDR_DMEM_UDIMM_1D_IMAGE_ID;
2209 break;
2210 case RDIMM:
2211 imem_id = train2d ? DDR_IMEM_RDIMM_2D_IMAGE_ID :
2212 DDR_IMEM_RDIMM_1D_IMAGE_ID;
2213 dmem_id = train2d ? DDR_DMEM_RDIMM_2D_IMAGE_ID :
2214 DDR_DMEM_RDIMM_1D_IMAGE_ID;
2215 break;
2216 default:
2217 ERROR("Unsupported DIMM type\n");
2218 return -EINVAL;
2219 }
2220
2221 size = PHY_GEN2_MAX_IMAGE_SIZE;
2222 image_buf = (uintptr_t)phy_gen2_fw_img_buf;
Pankaj Guptac518de42020-12-09 14:02:39 +05302223 ret = img_loadr(imem_id, &image_buf, &size);
2224 if (ret != 0) {
2225 ERROR("Failed to load %d firmware.\n", imem_id);
2226 return ret;
2227 }
2228 debug("Loaded Imaged id %d of size %x at address %lx\n",
2229 imem_id, size, image_buf);
2230
2231 for (i = 0; i < NUM_OF_DDRC; i++) {
2232 phy = phy_ptr[i];
2233 if (phy == NULL) {
2234 continue;
2235 }
2236
2237 if (warm_boot_flag != DDR_WARM_BOOT) {
2238 if (train2d == 0) {
2239 phy_io_write16(phy, t_master |
2240 csr_mem_reset_l_addr,
2241 csr_protect_mem_reset_mask);
2242 }
2243 }
2244 /* Enable access to the internal CSRs */
2245 phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 0);
2246
2247 ret = send_fw(phy, PHY_GEN2_IMEM_ADDR,
2248 (uint16_t *)image_buf, size);
2249 if (ret != 0) {
2250 return ret;
2251 }
2252 }
2253
2254 size = PHY_GEN2_MAX_IMAGE_SIZE;
2255 image_buf = (uintptr_t)phy_gen2_fw_img_buf;
2256 ret = img_loadr(dmem_id, &image_buf, &size);
2257 if (ret != 0) {
2258 ERROR("Failed to load %d firmware.\n", dmem_id);
2259 return ret;
2260 }
2261 debug("Loaded Imaged id %d of size %x at address %lx\n",
2262 dmem_id, size, image_buf);
2263 image_buf += len;
2264 size -= len;
2265
2266 for (i = 0; i < NUM_OF_DDRC; i++) {
2267 phy = phy_ptr[i];
2268 if (phy == NULL) {
2269 continue;
2270 }
2271
2272 ret = send_fw(phy, PHY_GEN2_DMEM_ADDR, msg, len);
2273 if (ret != 0) {
2274 return ret;
2275 }
2276
2277 ret = send_fw(phy, PHY_GEN2_DMEM_ADDR + len / 2,
2278 (uint16_t *)image_buf, size);
2279 if (ret != 0) {
2280 return ret;
2281 }
2282 }
2283
2284 return ret;
2285}
2286
2287static void parse_odt(const unsigned int val,
2288 const int read,
2289 const int i,
2290 const unsigned int cs_d0,
2291 const unsigned int cs_d1,
2292 unsigned int *odt)
2293{
2294 int shift = read ? 4 : 0;
2295 int j;
2296
2297 if (i < 0 || i > 3) {
2298 printf("Error: invalid chip-select value\n");
Jiafei Pan91374fb2022-09-02 11:07:15 +08002299 return;
Pankaj Guptac518de42020-12-09 14:02:39 +05302300 }
2301 switch (val) {
2302 case DDR_ODT_CS:
2303 odt[i] |= (1 << i) << shift;
2304 break;
2305 case DDR_ODT_ALL_OTHER_CS:
2306 for (j = 0; j < DDRC_NUM_CS; j++) {
2307 if (i == j) {
2308 continue;
2309 }
2310 if (((cs_d0 | cs_d1) & (1 << j)) == 0) {
2311 continue;
2312 }
2313 odt[j] |= (1 << i) << shift;
2314 }
2315 break;
2316 case DDR_ODT_CS_AND_OTHER_DIMM:
2317 odt[i] |= (1 << i) << 4;
2318 /* fallthrough */
2319 case DDR_ODT_OTHER_DIMM:
2320 for (j = 0; j < DDRC_NUM_CS; j++) {
2321 if ((((cs_d0 & (1 << i)) != 0) &&
2322 ((cs_d1 & (1 << j)) != 0)) ||
2323 (((cs_d1 & (1 << i)) != 0) &&
2324 ((cs_d0 & (1 << j)) != 0))) {
2325 odt[j] |= (1 << i) << shift;
2326 }
2327 }
2328 break;
2329 case DDR_ODT_ALL:
2330 for (j = 0; j < DDRC_NUM_CS; j++) {
2331 if (((cs_d0 | cs_d1) & (1 << j)) == 0) {
2332 continue;
2333 }
2334 odt[j] |= (1 << i) << shift;
2335 }
2336 break;
2337 case DDR_ODT_SAME_DIMM:
2338 for (j = 0; j < DDRC_NUM_CS; j++) {
2339 if ((((cs_d0 & (1 << i)) != 0) &&
2340 ((cs_d0 & (1 << j)) != 0)) ||
2341 (((cs_d1 & (1 << i)) != 0) &&
2342 ((cs_d1 & (1 << j)) != 0))) {
2343 odt[j] |= (1 << i) << shift;
2344 }
2345 }
2346 break;
2347 case DDR_ODT_OTHER_CS_ONSAMEDIMM:
2348 for (j = 0; j < DDRC_NUM_CS; j++) {
2349 if (i == j) {
2350 continue;
2351 }
2352 if ((((cs_d0 & (1 << i)) != 0) &&
2353 ((cs_d0 & (1 << j)) != 0)) ||
2354 (((cs_d1 & (1 << i)) != 0) &&
2355 ((cs_d1 & (1 << j)) != 0))) {
2356 odt[j] |= (1 << i) << shift;
2357 }
2358 }
2359 break;
2360 case DDR_ODT_NEVER:
2361 break;
2362 default:
2363 break;
2364 }
2365}
2366
2367#ifdef DEBUG_DDR_INPUT_CONFIG
2368char *dram_types_str[] = {
2369 "DDR4",
2370 "DDR3",
2371 "LDDDR4",
2372 "LPDDR3",
2373 "LPDDR2",
2374 "DDR5"
2375};
2376
2377char *dimm_types_str[] = {
2378 "UDIMM",
2379 "SODIMM",
2380 "RDIMM",
2381 "LRDIMM",
2382 "NODIMM",
2383};
2384
2385
2386static void print_jason_format(struct input *input,
2387 struct ddr4u1d *msg_1d,
2388 struct ddr4u2d *msg_2d)
2389{
2390
2391 printf("\n{");
2392 printf("\n \"dram_type\": \"%s\",", dram_types_str[input->basic.dram_type]);
2393 printf("\n \"dimm_type\": \"%s\",", dimm_types_str[input->basic.dimm_type]);
2394 printf("\n \"hard_macro_ver\": \"%d\",", input->basic.hard_macro_ver);
2395 printf("\n \"num_dbyte\": \"0x%04x\",", (unsigned int)input->basic.num_dbyte);
2396 printf("\n \"num_active_dbyte_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_active_dbyte_dfi0);
2397 printf("\n \"num_anib\": \"0x%04x\",", (unsigned int)input->basic.num_anib);
2398 printf("\n \"num_rank_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_rank_dfi0);
2399 printf("\n \"num_pstates\": \"0x%04x\",", (unsigned int)input->basic.num_pstates);
2400 printf("\n \"frequency\": \"%d\",", input->basic.frequency);
2401 printf("\n \"pll_bypass\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio);
2402 printf("\n \"dfi_freq_ratio\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio);
2403 printf("\n \"dfi1_exists\": \"0x%04x\",", (unsigned int)input->basic.dfi1exists);
2404 printf("\n \"dram_data_width\": \"0x%04x\",", (unsigned int)input->basic.dram_data_width);
2405 printf("\n \"dram_byte_swap\": \"0x%04x\",", (unsigned int)input->adv.dram_byte_swap);
2406 printf("\n \"ext_cal_res_val\": \"0x%04x\",", (unsigned int)input->adv.ext_cal_res_val);
2407 printf("\n \"tx_slew_rise_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_dq);
2408 printf("\n \"tx_slew_fall_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_dq);
2409 printf("\n \"tx_slew_rise_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_ac);
2410 printf("\n \"tx_slew_fall_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_ac);
2411 printf("\n \"odt_impedance\": \"%d\",", input->adv.odtimpedance);
2412 printf("\n \"tx_impedance\": \"%d\",", input->adv.tx_impedance);
2413 printf("\n \"atx_impedance\": \"%d\",", input->adv.atx_impedance);
2414 printf("\n \"mem_alert_en\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_en);
2415 printf("\n \"mem_alert_pu_imp\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_puimp);
2416 printf("\n \"mem_alert_vref_level\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_vref_level);
2417 printf("\n \"mem_alert_sync_bypass\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_sync_bypass);
2418 printf("\n \"cal_interval\": \"0x%04x\",", (unsigned int)input->adv.cal_interval);
2419 printf("\n \"cal_once\": \"0x%04x\",", (unsigned int)input->adv.cal_once);
2420 printf("\n \"dis_dyn_adr_tri\": \"0x%04x\",", (unsigned int)input->adv.dis_dyn_adr_tri);
2421 printf("\n \"is2t_timing\": \"0x%04x\",", (unsigned int)input->adv.is2ttiming);
2422 printf("\n \"d4rx_preabmle_length\": \"0x%04x\",", (unsigned int)input->adv.d4rx_preamble_length);
2423 printf("\n \"d4tx_preamble_length\": \"0x%04x\",", (unsigned int)input->adv.d4tx_preamble_length);
2424 printf("\n \"msg_misc\": \"0x%02x\",", (unsigned int)msg_1d->msg_misc);
2425 printf("\n \"reserved00\": \"0x%01x\",", (unsigned int)msg_1d->reserved00);
2426 printf("\n \"hdt_ctrl\": \"0x%02x\",", (unsigned int)msg_1d->hdt_ctrl);
2427 printf("\n \"cs_present\": \"0x%02x\",", (unsigned int)msg_1d->cs_present);
2428 printf("\n \"phy_vref\": \"0x%02x\",", (unsigned int)msg_1d->phy_vref);
2429 printf("\n \"dfi_mrl_margin\": \"0x%02x\",", (unsigned int)msg_1d->dfimrlmargin);
2430 printf("\n \"addr_mirror\": \"0x%02x\",", (unsigned int)msg_1d->addr_mirror);
2431 printf("\n \"wr_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0x0f));
2432 printf("\n \"wr_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0x0f));
2433 printf("\n \"wr_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0x0f));
2434 printf("\n \"wr_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0x0f));
2435 printf("\n \"rd_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0xf0));
2436 printf("\n \"rd_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0xf0));
2437 printf("\n \"rd_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0xf0));
2438 printf("\n \"rd_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0xf0));
2439 printf("\n \"d4_misc\": \"0x%01x\",", (unsigned int)msg_1d->d4misc);
2440 printf("\n \"share_2d_vref_results\": \"0x%01x\",", (unsigned int)msg_1d->share2dvref_result);
2441 printf("\n \"sequence_ctrl\": \"0x%04x\",", (unsigned int)msg_1d->sequence_ctrl);
2442 printf("\n \"mr0\": \"0x%04x\",", (unsigned int)msg_1d->mr0);
2443 printf("\n \"mr1\": \"0x%04x\",", (unsigned int)msg_1d->mr1);
2444 printf("\n \"mr2\": \"0x%04x\",", (unsigned int)msg_1d->mr2);
2445 printf("\n \"mr3\": \"0x%04x\",", (unsigned int)msg_1d->mr3);
2446 printf("\n \"mr4\": \"0x%04x\",", (unsigned int)msg_1d->mr4);
2447 printf("\n \"mr5\": \"0x%04x\",", (unsigned int)msg_1d->mr5);
2448 printf("\n \"mr6\": \"0x%04x\",", (unsigned int)msg_1d->mr6);
2449 printf("\n \"alt_cal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_cas_l);
2450 printf("\n \"alt_wcal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_wcas_l);
2451 printf("\n \"sequence_ctrl_2d\": \"0x%04x\",", (unsigned int)msg_2d->sequence_ctrl);
2452 printf("\n \"rtt_nom_wr_park0\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park0);
2453 printf("\n \"rtt_nom_wr_park1\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park1);
2454 printf("\n \"rtt_nom_wr_park2\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park2);
2455 printf("\n \"rtt_nom_wr_park3\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park3);
2456 printf("\n \"rtt_nom_wr_park4\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park4);
2457 printf("\n \"rtt_nom_wr_park5\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park5);
2458 printf("\n \"rtt_nom_wr_park6\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park6);
2459 printf("\n \"rtt_nom_wr_park7\": \"0x%01x\"", (unsigned int)msg_1d->rtt_nom_wr_park7);
2460 printf("\n}");
2461 printf("\n");
2462}
2463#endif
2464
2465int compute_ddr_phy(struct ddr_info *priv)
2466{
2467 const unsigned long clk = priv->clk;
2468 const struct memctl_opt *popts = &priv->opt;
2469 const struct ddr_conf *conf = &priv->conf;
2470 const struct dimm_params *dimm_param = &priv->dimm;
2471 struct ddr_cfg_regs *regs = &priv->ddr_reg;
2472 int ret;
2473 static struct input input;
2474 static struct ddr4u1d msg_1d;
2475 static struct ddr4u2d msg_2d;
2476 unsigned int i;
2477 unsigned int odt_rd, odt_wr;
2478 __unused const soc_info_t *soc_info;
2479#ifdef NXP_APPLY_MAX_CDD
2480 unsigned int tcfg0, tcfg4, rank;
Maninder Singh8666b3c2022-01-31 02:16:10 -07002481#ifdef NXP_WARM_BOOT
2482 struct ddr_ctrl_reg_values ddrctrl_regs;
2483#endif
Pankaj Guptac518de42020-12-09 14:02:39 +05302484#endif
2485
2486 if (dimm_param == NULL) {
2487 ERROR("Empty DIMM parameters.\n");
2488 return -EINVAL;
2489 }
2490
2491 zeromem(&input, sizeof(input));
2492 zeromem(&msg_1d, sizeof(msg_1d));
2493 zeromem(&msg_2d, sizeof(msg_2d));
2494
2495 input.basic.dram_type = DDR4;
2496 /* FIXME: Add condition for LRDIMM */
2497 input.basic.dimm_type = (dimm_param->rdimm != 0) ? RDIMM : UDIMM;
2498 input.basic.num_dbyte = dimm_param->primary_sdram_width / 8 +
2499 dimm_param->ec_sdram_width / 8;
2500 input.basic.num_active_dbyte_dfi0 = input.basic.num_dbyte;
2501 input.basic.num_rank_dfi0 = dimm_param->n_ranks;
2502 input.basic.dram_data_width = dimm_param->device_width;
2503 input.basic.hard_macro_ver = 0xa;
2504 input.basic.num_pstates = 1;
2505 input.basic.dfi_freq_ratio = 1;
2506 input.basic.num_anib = 0xc;
2507 input.basic.train2d = popts->skip2d ? 0 : 1;
2508 input.basic.frequency = (int) (clk / 2000000ul);
2509 debug("frequency = %dMHz\n", input.basic.frequency);
2510 input.cs_d0 = conf->cs_on_dimm[0];
2511#if DDRC_NUM_DIMM > 1
2512 input.cs_d1 = conf->cs_on_dimm[1];
2513#endif
2514 input.mirror = dimm_param->mirrored_dimm;
2515 input.mr[0] = regs->sdram_mode[0] & U(0xffff);
2516 input.mr[1] = regs->sdram_mode[0] >> 16U;
2517 input.mr[2] = regs->sdram_mode[1] >> 16U;
2518 input.mr[3] = regs->sdram_mode[1] & U(0xffff);
2519 input.mr[4] = regs->sdram_mode[8] >> 16U;
2520 input.mr[5] = regs->sdram_mode[8] & U(0xffff);
2521 input.mr[6] = regs->sdram_mode[9] >> 16U;
2522 input.vref = popts->vref_phy;
2523 debug("Vref_phy = %d percent\n", (input.vref * 100U) >> 7U);
2524 for (i = 0U; i < DDRC_NUM_CS; i++) {
2525 if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0U) {
2526 continue;
2527 }
2528 odt_rd = (regs->cs[i].config >> 20U) & U(0x7);
2529 odt_wr = (regs->cs[i].config >> 16U) & U(0x7);
2530 parse_odt(odt_rd, true, i, input.cs_d0, input.cs_d1,
2531 input.odt);
2532 parse_odt(odt_wr, false, i, input.cs_d0, input.cs_d1,
2533 input.odt);
2534 }
2535
2536 /* Do not set sdram_cfg[RD_EN] or sdram_cfg2[RCW_EN] for RDIMM */
2537 if (dimm_param->rdimm != 0U) {
2538 regs->sdram_cfg[0] &= ~(1 << 28U);
2539 regs->sdram_cfg[1] &= ~(1 << 2U);
2540 input.rcw[0] = (regs->sdram_rcw[0] >> 28U) & U(0xf);
2541 input.rcw[1] = (regs->sdram_rcw[0] >> 24U) & U(0xf);
2542 input.rcw[2] = (regs->sdram_rcw[0] >> 20U) & U(0xf);
2543 input.rcw[3] = (regs->sdram_rcw[0] >> 16U) & U(0xf);
2544 input.rcw[4] = (regs->sdram_rcw[0] >> 12U) & U(0xf);
2545 input.rcw[5] = (regs->sdram_rcw[0] >> 8U) & U(0xf);
2546 input.rcw[6] = (regs->sdram_rcw[0] >> 4U) & U(0xf);
2547 input.rcw[7] = (regs->sdram_rcw[0] >> 0U) & U(0xf);
2548 input.rcw[8] = (regs->sdram_rcw[1] >> 28U) & U(0xf);
2549 input.rcw[9] = (regs->sdram_rcw[1] >> 24U) & U(0xf);
2550 input.rcw[10] = (regs->sdram_rcw[1] >> 20U) & U(0xf);
2551 input.rcw[11] = (regs->sdram_rcw[1] >> 16U) & U(0xf);
2552 input.rcw[12] = (regs->sdram_rcw[1] >> 12U) & U(0xf);
2553 input.rcw[13] = (regs->sdram_rcw[1] >> 8U) & U(0xf);
2554 input.rcw[14] = (regs->sdram_rcw[1] >> 4U) & U(0xf);
2555 input.rcw[15] = (regs->sdram_rcw[1] >> 0U) & U(0xf);
2556 input.rcw3x = (regs->sdram_rcw[2] >> 8U) & U(0xff);
2557 }
2558
2559 input.adv.odtimpedance = popts->odt ? popts->odt : 60;
2560 input.adv.tx_impedance = popts->phy_tx_impedance ?
2561 popts->phy_tx_impedance : 28;
2562 input.adv.atx_impedance = popts->phy_atx_impedance ?
2563 popts->phy_atx_impedance : 30;
2564
2565 debug("Initializing input adv data structure\n");
2566 phy_gen2_init_input(&input);
2567
2568 debug("Initializing message block\n");
2569 ret = phy_gen2_msg_init(&msg_1d, &msg_2d, &input);
2570 if (ret != 0) {
2571 ERROR("Init msg failed (error code %d)\n", ret);
2572 return ret;
2573 }
2574
2575 ret = c_init_phy_config(priv->phy, priv->ip_rev, &input, &msg_1d);
2576 if (ret != 0) {
2577 ERROR("Init PHY failed (error code %d)\n", ret);
2578 return ret;
2579 }
2580#ifdef NXP_WARM_BOOT
2581 debug("Warm boot flag value %0x\n", priv->warm_boot_flag);
2582 if (priv->warm_boot_flag == DDR_WARM_BOOT) {
2583 debug("Restoring the Phy training data\n");
2584 // Restore the training data
2585 ret = restore_phy_training_values(priv->phy,
2586 PHY_TRAINING_REGS_ON_FLASH,
2587 priv->num_ctlrs,
Maninder Singh8666b3c2022-01-31 02:16:10 -07002588 input.basic.train2d
2589#ifdef NXP_APPLY_MAX_CDD
2590 , &ddrctrl_regs
2591#endif
2592 );
Pankaj Guptac518de42020-12-09 14:02:39 +05302593 if (ret != 0) {
2594 ERROR("Restoring of training data failed %d\n", ret);
2595 return ret;
2596 }
Maninder Singh8666b3c2022-01-31 02:16:10 -07002597#ifdef NXP_APPLY_MAX_CDD
2598 regs->timing_cfg[0] = ddrctrl_regs.timing_cfg0;
2599 regs->timing_cfg[4] = ddrctrl_regs.timing_cfg4;
2600#endif
Pankaj Guptac518de42020-12-09 14:02:39 +05302601 } else {
2602#endif
Jiafei Pan68e752f2022-04-08 11:10:40 +08002603 /* Mapping IMG buffer firstly */
2604 ret = mmap_add_dynamic_region(priv->phy_gen2_fw_img_buf,
2605 priv->phy_gen2_fw_img_buf,
2606 PHY_GEN2_MAX_IMAGE_SIZE,
2607 MT_MEMORY | MT_RW | MT_SECURE);
2608 if (ret != 0) {
2609 ERROR("Failed to add dynamic memory region.\n");
2610 return ret;
2611 }
Pankaj Guptac518de42020-12-09 14:02:39 +05302612
2613 debug("Load 1D firmware\n");
2614 ret = load_fw(priv->phy, &input, 0, &msg_1d,
2615 sizeof(struct ddr4u1d), priv->phy_gen2_fw_img_buf,
2616 priv->img_loadr, priv->warm_boot_flag);
2617 if (ret != 0) {
2618 ERROR("Loading firmware failed (error code %d)\n", ret);
2619 return ret;
2620 }
2621
2622 debug("Execute firmware\n");
2623 ret = g_exec_fw(priv->phy, 0, &input);
2624 if (ret != 0) {
2625 ERROR("Execution FW failed (error code %d)\n", ret);
2626 }
2627
2628#ifdef NXP_APPLY_MAX_CDD
Jiafei Panb27ac802021-07-20 17:14:32 +08002629 soc_info = get_soc_info();
2630 if (soc_info->svr_reg.bf.maj_ver == 2) {
Pankaj Guptac518de42020-12-09 14:02:39 +05302631 tcfg0 = regs->timing_cfg[0];
2632 tcfg4 = regs->timing_cfg[4];
2633 rank = findrank(conf->cs_in_use);
2634 get_cdd_val(priv->phy, rank, input.basic.frequency,
2635 &tcfg0, &tcfg4);
2636 regs->timing_cfg[0] = tcfg0;
2637 regs->timing_cfg[4] = tcfg4;
2638 }
2639#endif
2640
2641 if ((ret == 0) && (input.basic.train2d != 0)) {
2642 /* 2D training starts here */
2643 debug("Load 2D firmware\n");
2644 ret = load_fw(priv->phy, &input, 1, &msg_2d,
2645 sizeof(struct ddr4u2d),
2646 priv->phy_gen2_fw_img_buf,
2647 priv->img_loadr,
2648 priv->warm_boot_flag);
2649 if (ret != 0) {
2650 ERROR("Loading fw failed (err code %d)\n", ret);
2651 } else {
2652 debug("Execute 2D firmware\n");
2653 ret = g_exec_fw(priv->phy, 1, &input);
2654 if (ret != 0) {
2655 ERROR("Execution FW failed (err %d)\n",
2656 ret);
2657 }
2658 }
2659 }
2660#ifdef NXP_WARM_BOOT
2661 if (priv->warm_boot_flag != DDR_WRM_BOOT_NT_SUPPORTED &&
2662 ret == 0) {
Maninder Singh8666b3c2022-01-31 02:16:10 -07002663#ifdef NXP_APPLY_MAX_CDD
2664 ddrctrl_regs.timing_cfg0 = regs->timing_cfg[0];
2665 ddrctrl_regs.timing_cfg4 = regs->timing_cfg[4];
2666#endif
Pankaj Guptac518de42020-12-09 14:02:39 +05302667 debug("save the phy training data\n");
2668 //Save training data TBD
2669 ret = save_phy_training_values(priv->phy,
2670 PHY_TRAINING_REGS_ON_FLASH,
2671 priv->num_ctlrs,
Maninder Singh8666b3c2022-01-31 02:16:10 -07002672 input.basic.train2d
2673#ifdef NXP_APPLY_MAX_CDD
2674 , &ddrctrl_regs
2675#endif
2676 );
Pankaj Guptac518de42020-12-09 14:02:39 +05302677 if (ret != 0) {
2678 ERROR("Saving training data failed.");
2679 ERROR("Warm boot will fail. Error=%d.\n", ret);
2680 }
2681 }
2682 } /* else */
2683#endif
2684
2685 if (ret == 0) {
2686 debug("Load PIE\n");
2687 i_load_pie(priv->phy, &input, &msg_1d);
2688
2689 NOTICE("DDR4 %s with %d-rank %d-bit bus (x%d)\n",
2690 input.basic.dimm_type == RDIMM ? "RDIMM" :
2691 input.basic.dimm_type == LRDIMM ? "LRDIMM" :
2692 "UDIMM",
2693 dimm_param->n_ranks,
2694 dimm_param->primary_sdram_width,
2695 dimm_param->device_width);
2696 }
2697#ifdef DEBUG_DDR_INPUT_CONFIG
2698 print_jason_format(&input, &msg_1d, &msg_2d);
2699#endif
2700
2701 return ret;
2702}