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