2 * Copyright (C) Marvell International Ltd. and its affiliates
4 * SPDX-License-Identifier: GPL-2.0
10 #include <asm/arch/cpu.h>
11 #include <asm/arch/soc.h>
13 #include "ddr3_init.h"
15 /* List of allowed frequency listed in order of enum hws_ddr_freq */
16 u32 freq_val[DDR_FREQ_LIMIT] = {
17 0, /*DDR_FREQ_LOW_FREQ */
18 400, /*DDR_FREQ_400, */
19 533, /*DDR_FREQ_533, */
20 666, /*DDR_FREQ_667, */
21 800, /*DDR_FREQ_800, */
22 933, /*DDR_FREQ_933, */
23 1066, /*DDR_FREQ_1066, */
24 311, /*DDR_FREQ_311, */
25 333, /*DDR_FREQ_333, */
26 467, /*DDR_FREQ_467, */
27 850, /*DDR_FREQ_850, */
28 600, /*DDR_FREQ_600 */
29 300, /*DDR_FREQ_300 */
30 900, /*DDR_FREQ_900 */
31 360, /*DDR_FREQ_360 */
32 1000 /*DDR_FREQ_1000 */
35 /* Table for CL values per frequency for each speed bin index */
36 struct cl_val_per_freq cas_latency_table[] = {
38 * 400M 667M 933M 311M 467M 600M 360
39 * 100M 533M 800M 1066M 333M 850M 900
40 * 1000 (the order is 100, 400, 533 etc.)
43 { {6, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
45 { {6, 6, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 6, 0, 6, 0} },
47 { {6, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 0, 5, 0, 5, 0} },
49 { {6, 6, 7, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6, 0, 6, 0} },
51 { {6, 6, 8, 0, 0, 0, 0, 6, 6, 8, 0, 0, 6, 0, 6, 0} },
53 { {6, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
55 { {6, 5, 7, 8, 0, 0, 0, 5, 5, 7, 0, 8, 5, 0, 5, 0} },
57 { {6, 6, 8, 9, 0, 0, 0, 6, 6, 8, 0, 9, 6, 0, 6, 0} },
59 { {6, 6, 8, 10, 0, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0}
61 { {6, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
63 { {6, 5, 6, 8, 9, 0, 0, 5, 5, 6, 0, 8, 5, 0, 5, 0} },
65 { {6, 5, 7, 9, 10, 0, 0, 5, 5, 7, 0, 9, 5, 0, 5, 0} },
67 { {6, 6, 8, 10, 11, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0 } },
69 { {6, 5, 6, 8, 9, 11, 0, 5, 5, 6, 11, 8, 5, 0, 5, 0} },
71 { {6, 5, 7, 8, 10, 11, 0, 5, 5, 7, 11, 8, 5, 11, 5, 11} },
73 { {6, 6, 7, 9, 11, 12, 0, 6, 6, 7, 12, 9, 6, 12, 6, 12} },
75 { {6, 6, 8, 10, 11, 13, 0, 6, 6, 8, 13, 10, 6, 13, 6, 13} },
77 { {6, 5, 6, 7, 9, 10, 11, 5, 5, 6, 10, 7, 5, 11, 5, 11} },
79 { {6, 5, 6, 8, 9, 11, 12, 5, 5, 6, 11, 8, 5, 12, 5, 12} },
81 { {6, 5, 7, 9, 10, 12, 13, 5, 5, 7, 12, 9, 5, 13, 5, 13} },
83 { {6, 6, 7, 9, 11, 13, 14, 6, 6, 7, 13, 9, 6, 14, 6, 14} },
85 { {6, 6, 7, 9, 0, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
87 { {6, 6, 7, 9, 11, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
89 { {6, 6, 7, 9, 11, 13, 0, 6, 6, 7, 13, 9, 6, 13, 6, 13} },
92 /* Table for CWL values per speedbin index */
93 struct cl_val_per_freq cas_write_latency_table[] = {
95 * 400M 667M 933M 311M 467M 600M 360
96 * 100M 533M 800M 1066M 333M 850M 900
97 * (the order is 100, 400, 533 etc.)
100 { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
102 { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
104 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
106 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
108 { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
110 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
112 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
114 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
116 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
118 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
120 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
122 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
124 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
126 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
128 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
130 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
132 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
134 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
136 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
138 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
140 { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
142 { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
144 { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
146 { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
149 u8 twr_mask_table[] = {
169 u8 cl_mask_table[] = {
188 u8 cwl_mask_table[] = {
207 /* RFC values (in ns) */
216 u32 speed_bin_table_t_rc[] = {
240 u32 speed_bin_table_t_rcd_t_rp[] = {
265 PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
266 PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM
269 static u8 pattern_killer_pattern_table_map[KILLER_PATTERN_LENGTH * 2][2] = {
270 /*Aggressor / Victim */
337 static u8 pattern_vref_pattern_table_map[] = {
338 /* 1 means 0xffffffff, 0 is 0x0 */
349 /* Return speed Bin value for selected index and t* element */
350 u32 speed_bin_table(u8 index, enum speed_bin_table_elements element)
357 result = speed_bin_table_t_rcd_t_rp[index];
372 result = speed_bin_table_t_rc[index];
374 case SPEED_BIN_TRRD1K:
384 case SPEED_BIN_TRRD2K:
400 case SPEED_BIN_TFAW1K:
412 case SPEED_BIN_TFAW2K:
441 static inline u32 pattern_table_get_killer_word(u8 dqs, u8 index)
446 for (i = 0; i < 8; i++) {
448 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
449 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
450 byte |= pattern_killer_pattern_table_map[index][role] << i;
453 return byte | (byte << 8) | (byte << 16) | (byte << 24);
456 static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
458 u8 i, byte0 = 0, byte1 = 0;
461 for (i = 0; i < 8; i++) {
463 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
464 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
465 byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i;
468 for (i = 0; i < 8; i++) {
470 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
471 (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
472 byte1 |= pattern_killer_pattern_table_map
473 [index * 2 + 1][role] << i;
476 return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24);
479 static inline u32 pattern_table_get_sso_word(u8 sso, u8 index)
483 if (0 == ((index / step) & 1))
489 static inline u32 pattern_table_get_vref_word(u8 index)
491 if (0 == ((pattern_vref_pattern_table_map[index / 8] >>
498 static inline u32 pattern_table_get_vref_word16(u8 index)
500 if (0 == pattern_killer_pattern_table_map
501 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
502 0 == pattern_killer_pattern_table_map
503 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
505 else if (1 == pattern_killer_pattern_table_map
506 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
507 0 == pattern_killer_pattern_table_map
508 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
510 else if (0 == pattern_killer_pattern_table_map
511 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
512 1 == pattern_killer_pattern_table_map
513 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
519 static inline u32 pattern_table_get_static_pbs_word(u8 index)
523 temp = ((0x00ff << (index / 3)) & 0xff00) >> 8;
525 return temp | (temp << 8) | (temp << 16) | (temp << 24);
528 inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
531 struct hws_topology_map *tm = ddr3_get_topology_map();
533 if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) {
538 if (index == 0 || index == 2 || index == 5 ||
540 pattern = PATTERN_55;
542 pattern = PATTERN_AA;
545 if (0 == (index & 1))
546 pattern = PATTERN_55;
548 pattern = PATTERN_AA;
552 pattern = PATTERN_00;
554 pattern = PATTERN_80;
556 case PATTERN_STATIC_PBS:
557 pattern = pattern_table_get_static_pbs_word(index);
559 case PATTERN_KILLER_DQ0:
560 case PATTERN_KILLER_DQ1:
561 case PATTERN_KILLER_DQ2:
562 case PATTERN_KILLER_DQ3:
563 case PATTERN_KILLER_DQ4:
564 case PATTERN_KILLER_DQ5:
565 case PATTERN_KILLER_DQ6:
566 case PATTERN_KILLER_DQ7:
567 pattern = pattern_table_get_killer_word(
568 (u8)(type - PATTERN_KILLER_DQ0), index);
572 pattern = PATTERN_00;
574 pattern = PATTERN_01;
577 if (index > 1 && index < 6)
578 pattern = PATTERN_20;
580 pattern = PATTERN_00;
582 case PATTERN_FULL_SSO0:
583 case PATTERN_FULL_SSO1:
584 case PATTERN_FULL_SSO2:
585 case PATTERN_FULL_SSO3:
586 pattern = pattern_table_get_sso_word(
587 (u8)(type - PATTERN_FULL_SSO0), index);
590 pattern = pattern_table_get_vref_word(index);
602 pattern = PATTERN_55AA;
606 pattern = PATTERN_00;
608 pattern = PATTERN_80;
610 case PATTERN_STATIC_PBS:
611 pattern = PATTERN_00FF;
613 case PATTERN_KILLER_DQ0:
614 case PATTERN_KILLER_DQ1:
615 case PATTERN_KILLER_DQ2:
616 case PATTERN_KILLER_DQ3:
617 case PATTERN_KILLER_DQ4:
618 case PATTERN_KILLER_DQ5:
619 case PATTERN_KILLER_DQ6:
620 case PATTERN_KILLER_DQ7:
621 pattern = pattern_table_get_killer_word16(
622 (u8)(type - PATTERN_KILLER_DQ0), index);
626 pattern = PATTERN_00;
628 pattern = PATTERN_01;
631 pattern = PATTERN_0080;
633 case PATTERN_FULL_SSO0:
634 pattern = 0x0000ffff;
636 case PATTERN_FULL_SSO1:
637 case PATTERN_FULL_SSO2:
638 case PATTERN_FULL_SSO3:
639 pattern = pattern_table_get_sso_word(
640 (u8)(type - PATTERN_FULL_SSO1), index);
643 pattern = pattern_table_get_vref_word16(index);