1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) Marvell International Ltd. and its affiliates
9 #include <asm/arch/cpu.h>
10 #include <asm/arch/soc.h>
12 #include "ddr3_init.h"
14 /* List of allowed frequency listed in order of enum hws_ddr_freq */
15 u32 freq_val[DDR_FREQ_LIMIT] = {
16 0, /*DDR_FREQ_LOW_FREQ */
17 400, /*DDR_FREQ_400, */
18 533, /*DDR_FREQ_533, */
19 666, /*DDR_FREQ_667, */
20 800, /*DDR_FREQ_800, */
21 933, /*DDR_FREQ_933, */
22 1066, /*DDR_FREQ_1066, */
23 311, /*DDR_FREQ_311, */
24 333, /*DDR_FREQ_333, */
25 467, /*DDR_FREQ_467, */
26 850, /*DDR_FREQ_850, */
27 600, /*DDR_FREQ_600 */
28 300, /*DDR_FREQ_300 */
29 900, /*DDR_FREQ_900 */
30 360, /*DDR_FREQ_360 */
31 1000 /*DDR_FREQ_1000 */
34 /* Table for CL values per frequency for each speed bin index */
35 struct cl_val_per_freq cas_latency_table[] = {
37 * 400M 667M 933M 311M 467M 600M 360
38 * 100M 533M 800M 1066M 333M 850M 900
39 * 1000 (the order is 100, 400, 533 etc.)
42 { {6, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
44 { {6, 6, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 6, 0, 6, 0} },
46 { {6, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 0, 5, 0, 5, 0} },
48 { {6, 6, 7, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6, 0, 6, 0} },
50 { {6, 6, 8, 0, 0, 0, 0, 6, 6, 8, 0, 0, 6, 0, 6, 0} },
52 { {6, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
54 { {6, 5, 7, 8, 0, 0, 0, 5, 5, 7, 0, 8, 5, 0, 5, 0} },
56 { {6, 6, 8, 9, 0, 0, 0, 6, 6, 8, 0, 9, 6, 0, 6, 0} },
58 { {6, 6, 8, 10, 0, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0}
60 { {6, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
62 { {6, 5, 6, 8, 9, 0, 0, 5, 5, 6, 0, 8, 5, 0, 5, 0} },
64 { {6, 5, 7, 9, 10, 0, 0, 5, 5, 7, 0, 9, 5, 0, 5, 0} },
66 { {6, 6, 8, 10, 11, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0 } },
68 { {6, 5, 6, 8, 9, 11, 0, 5, 5, 6, 11, 8, 5, 0, 5, 0} },
70 { {6, 5, 7, 8, 10, 11, 0, 5, 5, 7, 11, 8, 5, 11, 5, 11} },
72 { {6, 6, 7, 9, 11, 12, 0, 6, 6, 7, 12, 9, 6, 12, 6, 12} },
74 { {6, 6, 8, 10, 11, 13, 0, 6, 6, 8, 13, 10, 6, 13, 6, 13} },
76 { {6, 5, 6, 7, 9, 10, 11, 5, 5, 6, 10, 7, 5, 11, 5, 11} },
78 { {6, 5, 6, 8, 9, 11, 12, 5, 5, 6, 11, 8, 5, 12, 5, 12} },
80 { {6, 5, 7, 9, 10, 12, 13, 5, 5, 7, 12, 9, 5, 13, 5, 13} },
82 { {6, 6, 7, 9, 11, 13, 14, 6, 6, 7, 13, 9, 6, 14, 6, 14} },
84 { {6, 6, 7, 9, 0, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
86 { {6, 6, 7, 9, 11, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
88 { {6, 6, 7, 9, 11, 13, 0, 6, 6, 7, 13, 9, 6, 13, 6, 13} },
91 /* Table for CWL values per speedbin index */
92 struct cl_val_per_freq cas_write_latency_table[] = {
94 * 400M 667M 933M 311M 467M 600M 360
95 * 100M 533M 800M 1066M 333M 850M 900
96 * (the order is 100, 400, 533 etc.)
99 { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
101 { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
103 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
105 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
107 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
109 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
111 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
113 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
115 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
117 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
119 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
121 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
123 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
125 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
127 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
129 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
131 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
133 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
135 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
137 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
139 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
141 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
143 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
145 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
148 u8 twr_mask_table[] = {
168 u8 cl_mask_table[] = {
187 u8 cwl_mask_table[] = {
206 /* RFC values (in ns) */
215 u32 speed_bin_table_t_rc[] = {
239 u32 speed_bin_table_t_rcd_t_rp[] = {
264 PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
265 PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM
268 static u8 pattern_killer_pattern_table_map[KILLER_PATTERN_LENGTH * 2][2] = {
269 /*Aggressor / Victim */
336 static u8 pattern_vref_pattern_table_map[] = {
337 /* 1 means 0xffffffff, 0 is 0x0 */
348 /* Return speed Bin value for selected index and t* element */
349 u32 speed_bin_table(u8 index, enum speed_bin_table_elements element)
356 result = speed_bin_table_t_rcd_t_rp[index];
371 result = speed_bin_table_t_rc[index];
373 case SPEED_BIN_TRRD1K:
383 case SPEED_BIN_TRRD2K:
399 case SPEED_BIN_TFAW1K:
411 case SPEED_BIN_TFAW2K:
433 case SPEED_BIN_TXPDLL:
443 static inline u32 pattern_table_get_killer_word(u8 dqs, u8 index)
448 for (i = 0; i < 8; i++) {
450 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
451 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
452 byte |= pattern_killer_pattern_table_map[index][role] << i;
455 return byte | (byte << 8) | (byte << 16) | (byte << 24);
458 static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
460 u8 i, byte0 = 0, byte1 = 0;
463 for (i = 0; i < 8; i++) {
465 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
466 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
467 byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i;
470 for (i = 0; i < 8; i++) {
472 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
473 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
474 byte1 |= pattern_killer_pattern_table_map
475 [index * 2 + 1][role] << i;
478 return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24);
481 static inline u32 pattern_table_get_sso_word(u8 sso, u8 index)
485 if (0 == ((index / step) & 1))
491 static inline u32 pattern_table_get_vref_word(u8 index)
493 if (0 == ((pattern_vref_pattern_table_map[index / 8] >>
500 static inline u32 pattern_table_get_vref_word16(u8 index)
502 if (0 == pattern_killer_pattern_table_map
503 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
504 0 == pattern_killer_pattern_table_map
505 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
507 else if (1 == pattern_killer_pattern_table_map
508 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
509 0 == pattern_killer_pattern_table_map
510 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
512 else if (0 == pattern_killer_pattern_table_map
513 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
514 1 == pattern_killer_pattern_table_map
515 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
521 static inline u32 pattern_table_get_static_pbs_word(u8 index)
525 temp = ((0x00ff << (index / 3)) & 0xff00) >> 8;
527 return temp | (temp << 8) | (temp << 16) | (temp << 24);
530 inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
533 struct hws_topology_map *tm = ddr3_get_topology_map();
535 if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) {
540 if (index == 0 || index == 2 || index == 5 ||
542 pattern = PATTERN_55;
544 pattern = PATTERN_AA;
547 if (0 == (index & 1))
548 pattern = PATTERN_55;
550 pattern = PATTERN_AA;
554 pattern = PATTERN_00;
556 pattern = PATTERN_80;
558 case PATTERN_STATIC_PBS:
559 pattern = pattern_table_get_static_pbs_word(index);
561 case PATTERN_KILLER_DQ0:
562 case PATTERN_KILLER_DQ1:
563 case PATTERN_KILLER_DQ2:
564 case PATTERN_KILLER_DQ3:
565 case PATTERN_KILLER_DQ4:
566 case PATTERN_KILLER_DQ5:
567 case PATTERN_KILLER_DQ6:
568 case PATTERN_KILLER_DQ7:
569 pattern = pattern_table_get_killer_word(
570 (u8)(type - PATTERN_KILLER_DQ0), index);
574 pattern = PATTERN_00;
576 pattern = PATTERN_01;
579 if (index > 1 && index < 6)
580 pattern = PATTERN_20;
582 pattern = PATTERN_00;
584 case PATTERN_FULL_SSO0:
585 case PATTERN_FULL_SSO1:
586 case PATTERN_FULL_SSO2:
587 case PATTERN_FULL_SSO3:
588 pattern = pattern_table_get_sso_word(
589 (u8)(type - PATTERN_FULL_SSO0), index);
592 pattern = pattern_table_get_vref_word(index);
604 pattern = PATTERN_55AA;
608 pattern = PATTERN_00;
610 pattern = PATTERN_80;
612 case PATTERN_STATIC_PBS:
613 pattern = PATTERN_00FF;
615 case PATTERN_KILLER_DQ0:
616 case PATTERN_KILLER_DQ1:
617 case PATTERN_KILLER_DQ2:
618 case PATTERN_KILLER_DQ3:
619 case PATTERN_KILLER_DQ4:
620 case PATTERN_KILLER_DQ5:
621 case PATTERN_KILLER_DQ6:
622 case PATTERN_KILLER_DQ7:
623 pattern = pattern_table_get_killer_word16(
624 (u8)(type - PATTERN_KILLER_DQ0), index);
628 pattern = PATTERN_00;
630 pattern = PATTERN_01;
633 pattern = PATTERN_0080;
635 case PATTERN_FULL_SSO0:
636 pattern = 0x0000ffff;
638 case PATTERN_FULL_SSO1:
639 case PATTERN_FULL_SSO2:
640 case PATTERN_FULL_SSO3:
641 pattern = pattern_table_get_sso_word(
642 (u8)(type - PATTERN_FULL_SSO1), index);
645 pattern = pattern_table_get_vref_word16(index);