]> git.sur5r.net Git - u-boot/blobdiff - drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
ARM: mvebu: a38x: sync ddr training code with upstream
[u-boot] / drivers / ddr / marvell / a38x / ddr3_training_ip_engine.c
index 89318a48d9641bc7613e2acb41bef5849c79219f..334c2906fdbf0d73ab3dabe0a968d15077d1ee18 100644 (file)
@@ -3,12 +3,6 @@
  * Copyright (C) Marvell International Ltd. and its affiliates
  */
 
-#include <common.h>
-#include <spl.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/soc.h>
-
 #include "ddr3_init.h"
 
 #define PATTERN_1      0x55555555
@@ -21,6 +15,7 @@ u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
 
 u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS *
                 HWS_SEARCH_DIR_LIMIT];
+u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM];        /* holds the bit status in the byte in wrapper function*/
 
 u16 mask_results_dq_reg_map[] = {
        RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
@@ -43,14 +38,39 @@ u16 mask_results_dq_reg_map[] = {
        RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
        RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
        RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
+#if MAX_BUS_NUM == 9
+       RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG,
+       RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG,
+       RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG,
+       RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG,
+       RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG,
+       RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG,
+       RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG,
+       RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG,
+       RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG,
+       RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG,
+       RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG,
+       RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG,
+       RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG,
+       RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG,
+       RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG,
+       RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG,
+#endif
+       0xffff
 };
 
 u16 mask_results_pup_reg_map[] = {
        RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
        RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG,
-       RESULT_CONTROL_BYTE_PUP_4_REG
+       RESULT_CONTROL_BYTE_PUP_4_REG,
+#if MAX_BUS_NUM == 9
+       RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG,
+       RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG,
+#endif
+       0xffff
 };
 
+#if MAX_BUS_NUM == 5
 u16 mask_results_dq_reg_map_pup3_ecc[] = {
        RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
        RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
@@ -68,17 +88,120 @@ u16 mask_results_dq_reg_map_pup3_ecc[] = {
        RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
        RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
        RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
-       RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
-       RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
-       RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
-       RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
+       RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
+       RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
+       RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
+       RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG
 };
+#endif
 
+#if MAX_BUS_NUM == 5
 u16 mask_results_pup_reg_map_pup3_ecc[] = {
        RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
        RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG,
        RESULT_CONTROL_BYTE_PUP_4_REG
 };
+#endif
+
+struct pattern_info pattern_table_64[] = {
+       /*
+        * num_of_phases_tx, tx_burst_size;
+        * delay_between_bursts, num_of_phases_rx,
+        * start_addr, pattern_len
+        */
+       {0x7, 0x7, 2, 0x7, 0x00000, 8},         /* PATTERN_PBS1 */
+       {0x7, 0x7, 2, 0x7, 0x00080, 8},         /* PATTERN_PBS2 */
+       {0x7, 0x7, 2, 0x7, 0x00100, 8},         /* PATTERN_PBS3 */
+       {0x7, 0x7, 2, 0x7, 0x00030, 8},         /* PATTERN_TEST */
+       {0x7, 0x7, 2, 0x7, 0x00100, 8},         /* PATTERN_RL */
+       {0x7, 0x7, 2, 0x7, 0x00100, 8},         /* PATTERN_RL2 */
+       {0x1f, 0xf, 2, 0xf, 0x00680, 32},       /* PATTERN_STATIC_PBS */
+       {0x1f, 0xf, 2, 0xf, 0x00a80, 32},       /* PATTERN_KILLER_DQ0 */
+       {0x1f, 0xf, 2, 0xf, 0x01280, 32},       /* PATTERN_KILLER_DQ1 */
+       {0x1f, 0xf, 2, 0xf, 0x01a80, 32},       /* PATTERN_KILLER_DQ2 */
+       {0x1f, 0xf, 2, 0xf, 0x02280, 32},       /* PATTERN_KILLER_DQ3 */
+       {0x1f, 0xf, 2, 0xf, 0x02a80, 32},       /* PATTERN_KILLER_DQ4 */
+       {0x1f, 0xf, 2, 0xf, 0x03280, 32},       /* PATTERN_KILLER_DQ5 */
+       {0x1f, 0xf, 2, 0xf, 0x03a80, 32},       /* PATTERN_KILLER_DQ6 */
+       {0x1f, 0xf, 2, 0xf, 0x04280, 32},       /* PATTERN_KILLER_DQ7 */
+       {0x1f, 0xf, 2, 0xf, 0x00e80, 32},       /* PATTERN_KILLER_DQ0_64 */
+       {0x1f, 0xf, 2, 0xf, 0x01680, 32},       /* PATTERN_KILLER_DQ1_64 */
+       {0x1f, 0xf, 2, 0xf, 0x01e80, 32},       /* PATTERN_KILLER_DQ2_64 */
+       {0x1f, 0xf, 2, 0xf, 0x02680, 32},       /* PATTERN_KILLER_DQ3_64 */
+       {0x1f, 0xf, 2, 0xf, 0x02e80, 32},       /* PATTERN_KILLER_DQ4_64 */
+       {0x1f, 0xf, 2, 0xf, 0x03680, 32},       /* PATTERN_KILLER_DQ5_64 */
+       {0x1f, 0xf, 2, 0xf, 0x03e80, 32},       /* PATTERN_KILLER_DQ6_64 */
+       {0x1f, 0xf, 2, 0xf, 0x04680, 32},       /* PATTERN_KILLER_DQ7_64 */
+       {0x1f, 0xf, 2, 0xf, 0x04a80, 32},       /* PATTERN_KILLER_DQ0_INV */
+       {0x1f, 0xf, 2, 0xf, 0x05280, 32},       /* PATTERN_KILLER_DQ1_INV */
+       {0x1f, 0xf, 2, 0xf, 0x05a80, 32},       /* PATTERN_KILLER_DQ2_INV */
+       {0x1f, 0xf, 2, 0xf, 0x06280, 32},       /* PATTERN_KILLER_DQ3_INV */
+       {0x1f, 0xf, 2, 0xf, 0x06a80, 32},       /* PATTERN_KILLER_DQ4_INV */
+       {0x1f, 0xf, 2, 0xf, 0x07280, 32},       /* PATTERN_KILLER_DQ5_INV */
+       {0x1f, 0xf, 2, 0xf, 0x07a80, 32},       /* PATTERN_KILLER_DQ6_INV */
+       {0x1f, 0xf, 2, 0xf, 0x08280, 32},       /* PATTERN_KILLER_DQ7_INV */
+       {0x1f, 0xf, 2, 0xf, 0x04e80, 32},       /* PATTERN_KILLER_DQ0_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x05680, 32},       /* PATTERN_KILLER_DQ1_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x05e80, 32},       /* PATTERN_KILLER_DQ2_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x06680, 32},       /* PATTERN_KILLER_DQ3_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x06e80, 32},       /* PATTERN_KILLER_DQ4_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x07680, 32},       /* PATTERN_KILLER_DQ5_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x07e80, 32},       /* PATTERN_KILLER_DQ6_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x08680, 32},       /* PATTERN_KILLER_DQ7_INV_64 */
+       {0x1f, 0xf, 2, 0xf, 0x08a80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ0 */
+       {0x1f, 0xf, 2, 0xf, 0x09280, 32},       /* PATTERN_SSO_FULL_XTALK_DQ1 */
+       {0x1f, 0xf, 2, 0xf, 0x09a80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ2 */
+       {0x1f, 0xf, 2, 0xf, 0x0a280, 32},       /* PATTERN_SSO_FULL_XTALK_DQ3 */
+       {0x1f, 0xf, 2, 0xf, 0x0aa80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ4 */
+       {0x1f, 0xf, 2, 0xf, 0x0b280, 32},       /* PATTERN_SSO_FULL_XTALK_DQ5 */
+       {0x1f, 0xf, 2, 0xf, 0x0ba80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ6 */
+       {0x1f, 0xf, 2, 0xf, 0x0c280, 32},       /* PATTERN_SSO_FULL_XTALK_DQ7 */
+       {0x1f, 0xf, 2, 0xf, 0x08e80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ0_64 */
+       {0x1f, 0xf, 2, 0xf, 0x09680, 32},       /* PATTERN_SSO_FULL_XTALK_DQ1_64 */
+       {0x1f, 0xf, 2, 0xf, 0x09e80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ2_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0a680, 32},       /* PATTERN_SSO_FULL_XTALK_DQ3_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0ae80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ4_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0b680, 32},       /* PATTERN_SSO_FULL_XTALK_DQ5_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0be80, 32},       /* PATTERN_SSO_FULL_XTALK_DQ6_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0c680, 32},       /* PATTERN_SSO_FULL_XTALK_DQ7_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0ca80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ0 */
+       {0x1f, 0xf, 2, 0xf, 0x0d280, 32},       /* PATTERN_SSO_XTALK_FREE_DQ1 */
+       {0x1f, 0xf, 2, 0xf, 0x0da80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ2 */
+       {0x1f, 0xf, 2, 0xf, 0x0e280, 32},       /* PATTERN_SSO_XTALK_FREE_DQ3 */
+       {0x1f, 0xf, 2, 0xf, 0x0ea80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ4 */
+       {0x1f, 0xf, 2, 0xf, 0x0f280, 32},       /* PATTERN_SSO_XTALK_FREE_DQ5 */
+       {0x1f, 0xf, 2, 0xf, 0x0fa80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ6 */
+       {0x1f, 0xf, 2, 0xf, 0x10280, 32},       /* PATTERN_SSO_XTALK_FREE_DQ7 */
+       {0x1f, 0xf, 2, 0xf, 0x0ce80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ0_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0d680, 32},       /* PATTERN_SSO_XTALK_FREE_DQ1_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0de80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ2_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0e680, 32},       /* PATTERN_SSO_XTALK_FREE_DQ3_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0ee80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ4_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0f680, 32},       /* PATTERN_SSO_XTALK_FREE_DQ5_64 */
+       {0x1f, 0xf, 2, 0xf, 0x0fe80, 32},       /* PATTERN_SSO_XTALK_FREE_DQ6_64 */
+       {0x1f, 0xf, 2, 0xf, 0x10680, 32},       /* PATTERN_SSO_XTALK_FREE_DQ7_64 */
+       {0x1f, 0xf, 2, 0xf, 0x10a80, 32},       /* PATTERN_ISI_XTALK_FREE */
+       {0x1f, 0xf, 2, 0xf, 0x10e80, 32},       /* PATTERN_ISI_XTALK_FREE_64 */
+       {0x1f, 0xf, 2, 0xf, 0x11280, 32},       /* PATTERN_VREF */
+       {0x1f, 0xf, 2, 0xf, 0x11680, 32},       /* PATTERN_VREF_64 */
+       {0x1f, 0xf, 2, 0xf, 0x11a80, 32},       /* PATTERN_VREF_INV */
+       {0x1f, 0xf, 2, 0xf, 0x11e80, 32},       /* PATTERN_FULL_SSO_0T */
+       {0x1f, 0xf, 2, 0xf, 0x12280, 32},       /* PATTERN_FULL_SSO_1T */
+       {0x1f, 0xf, 2, 0xf, 0x12680, 32},       /* PATTERN_FULL_SSO_2T */
+       {0x1f, 0xf, 2, 0xf, 0x12a80, 32},       /* PATTERN_FULL_SSO_3T */
+       {0x1f, 0xf, 2, 0xf, 0x12e80, 32},       /* PATTERN_RESONANCE_1T */
+       {0x1f, 0xf, 2, 0xf, 0x13280, 32},       /* PATTERN_RESONANCE_2T */
+       {0x1f, 0xf, 2, 0xf, 0x13680, 32},       /* PATTERN_RESONANCE_3T */
+       {0x1f, 0xf, 2, 0xf, 0x13a80, 32},       /* PATTERN_RESONANCE_4T */
+       {0x1f, 0xf, 2, 0xf, 0x13e80, 32},       /* PATTERN_RESONANCE_5T */
+       {0x1f, 0xf, 2, 0xf, 0x14280, 32},       /* PATTERN_RESONANCE_6T */
+       {0x1f, 0xf, 2, 0xf, 0x14680, 32},       /* PATTERN_RESONANCE_7T */
+       {0x1f, 0xf, 2, 0xf, 0x14a80, 32},       /* PATTERN_RESONANCE_8T */
+       {0x1f, 0xf, 2, 0xf, 0x14e80, 32},       /* PATTERN_RESONANCE_9T */
+       {0x1f, 0xf, 2, 0xf, 0x15280, 32},       /* PATTERN_ZERO */
+       {0x1f, 0xf, 2, 0xf, 0x15680, 32}        /* PATTERN_ONE */
+       /* Note: actual start_address is "<< 3" of defined address */
+};
 
 struct pattern_info pattern_table_16[] = {
        /*
@@ -87,7 +210,10 @@ struct pattern_info pattern_table_16[] = {
         */
        {1, 1, 2, 1, 0x0080, 2},        /* PATTERN_PBS1 */
        {1, 1, 2, 1, 0x00c0, 2},        /* PATTERN_PBS2 */
+       {1, 1, 2, 1, 0x0380, 2},        /* PATTERN_PBS3 */
+       {1, 1, 2, 1, 0x0040, 2},        /* PATTERN_TEST */
        {1, 1, 2, 1, 0x0100, 2},        /* PATTERN_RL */
+       {1, 1, 2, 1, 0x0000, 2},        /* PATTERN_RL2 */
        {0xf, 0x7, 2, 0x7, 0x0140, 16}, /* PATTERN_STATIC_PBS */
        {0xf, 0x7, 2, 0x7, 0x0190, 16}, /* PATTERN_KILLER_DQ0 */
        {0xf, 0x7, 2, 0x7, 0x01d0, 16}, /* PATTERN_KILLER_DQ1 */
@@ -97,15 +223,29 @@ struct pattern_info pattern_table_16[] = {
        {0xf, 0x7, 2, 0x7, 0x02d0, 16}, /* PATTERN_KILLER_DQ5 */
        {0xf, 0x7, 2, 0x7, 0x0310, 16}, /* PATTERN_KILLER_DQ6 */
        {0xf, 0x7, 2, 0x7, 0x0350, 16}, /* PATTERN_KILLER_DQ7 */
-       {1, 1, 2, 1, 0x0380, 2},        /* PATTERN_PBS3 */
-       {1, 1, 2, 1, 0x0000, 2},        /* PATTERN_RL2 */
-       {1, 1, 2, 1, 0x0040, 2},        /* PATTERN_TEST */
+       {0xf, 0x7, 2, 0x7, 0x04c0, 16}, /* PATTERN_VREF */
        {0xf, 0x7, 2, 0x7, 0x03c0, 16}, /* PATTERN_FULL_SSO_1T */
        {0xf, 0x7, 2, 0x7, 0x0400, 16}, /* PATTERN_FULL_SSO_2T */
        {0xf, 0x7, 2, 0x7, 0x0440, 16}, /* PATTERN_FULL_SSO_3T */
        {0xf, 0x7, 2, 0x7, 0x0480, 16}, /* PATTERN_FULL_SSO_4T */
-       {0xf, 0x7, 2, 0x7, 0x04c0, 16}  /* PATTERN_VREF */
-       /*Note: actual start_address is <<3 of defined addess */
+       {0xf, 7, 2, 7, 0x6280, 16},     /* PATTERN_SSO_FULL_XTALK_DQ1 */
+       {0xf, 7, 2, 7, 0x6680, 16},     /* PATTERN_SSO_FULL_XTALK_DQ1 */
+       {0xf, 7, 2, 7, 0x6A80, 16},     /* PATTERN_SSO_FULL_XTALK_DQ2 */
+       {0xf, 7, 2, 7, 0x6E80, 16},     /* PATTERN_SSO_FULL_XTALK_DQ3 */
+       {0xf, 7, 2, 7, 0x7280, 16},     /* PATTERN_SSO_FULL_XTALK_DQ4 */
+       {0xf, 7, 2, 7, 0x7680, 16},     /* PATTERN_SSO_FULL_XTALK_DQ5 */
+       {0xf, 7, 2, 7, 0x7A80, 16},     /* PATTERN_SSO_FULL_XTALK_DQ6 */
+       {0xf, 7, 2, 7, 0x7E80, 16},     /* PATTERN_SSO_FULL_XTALK_DQ7 */
+       {0xf, 7, 2, 7, 0x8280, 16},     /* PATTERN_SSO_XTALK_FREE_DQ0 */
+       {0xf, 7, 2, 7, 0x8680, 16},     /* PATTERN_SSO_XTALK_FREE_DQ1 */
+       {0xf, 7, 2, 7, 0x8A80, 16},     /* PATTERN_SSO_XTALK_FREE_DQ2 */
+       {0xf, 7, 2, 7, 0x8E80, 16},     /* PATTERN_SSO_XTALK_FREE_DQ3 */
+       {0xf, 7, 2, 7, 0x9280, 16},     /* PATTERN_SSO_XTALK_FREE_DQ4 */
+       {0xf, 7, 2, 7, 0x9680, 16},     /* PATTERN_SSO_XTALK_FREE_DQ5 */
+       {0xf, 7, 2, 7, 0x9A80, 16},     /* PATTERN_SSO_XTALK_FREE_DQ6 */
+       {0xf, 7, 2, 7, 0x9E80, 16},     /* PATTERN_SSO_XTALK_FREE_DQ7 */
+       {0xf, 7, 2, 7, 0xA280, 16}      /* PATTERN_ISI_XTALK_FREE */
+       /* Note: actual start_address is "<< 3" of defined address */
 };
 
 struct pattern_info pattern_table_32[] = {
@@ -115,7 +255,10 @@ struct pattern_info pattern_table_32[] = {
         */
        {3, 3, 2, 3, 0x0080, 4},        /* PATTERN_PBS1 */
        {3, 3, 2, 3, 0x00c0, 4},        /* PATTERN_PBS2 */
+       {3, 3, 2, 3, 0x0380, 4},        /* PATTERN_PBS3 */
+       {3, 3, 2, 3, 0x0040, 4},        /* PATTERN_TEST */
        {3, 3, 2, 3, 0x0100, 4},        /* PATTERN_RL */
+       {3, 3, 2, 3, 0x0000, 4},        /* PATTERN_RL2 */
        {0x1f, 0xf, 2, 0xf, 0x0140, 32},        /* PATTERN_STATIC_PBS */
        {0x1f, 0xf, 2, 0xf, 0x0190, 32},        /* PATTERN_KILLER_DQ0 */
        {0x1f, 0xf, 2, 0xf, 0x01d0, 32},        /* PATTERN_KILLER_DQ1 */
@@ -125,15 +268,29 @@ struct pattern_info pattern_table_32[] = {
        {0x1f, 0xf, 2, 0xf, 0x02d0, 32},        /* PATTERN_KILLER_DQ5 */
        {0x1f, 0xf, 2, 0xf, 0x0310, 32},        /* PATTERN_KILLER_DQ6 */
        {0x1f, 0xf, 2, 0xf, 0x0350, 32},        /* PATTERN_KILLER_DQ7 */
-       {3, 3, 2, 3, 0x0380, 4},        /* PATTERN_PBS3 */
-       {3, 3, 2, 3, 0x0000, 4},        /* PATTERN_RL2 */
-       {3, 3, 2, 3, 0x0040, 4},        /* PATTERN_TEST */
+       {0x1f, 0xf, 2, 0xf, 0x04c0, 32},        /* PATTERN_VREF */
        {0x1f, 0xf, 2, 0xf, 0x03c0, 32},        /* PATTERN_FULL_SSO_1T */
        {0x1f, 0xf, 2, 0xf, 0x0400, 32},        /* PATTERN_FULL_SSO_2T */
        {0x1f, 0xf, 2, 0xf, 0x0440, 32},        /* PATTERN_FULL_SSO_3T */
        {0x1f, 0xf, 2, 0xf, 0x0480, 32},        /* PATTERN_FULL_SSO_4T */
-       {0x1f, 0xf, 2, 0xf, 0x04c0, 32} /* PATTERN_VREF */
-       /*Note: actual start_address is <<3 of defined addess */
+       {0x1f, 0xF, 2, 0xf, 0x6280, 32},        /* PATTERN_SSO_FULL_XTALK_DQ0 */
+       {0x1f, 0xF, 2, 0xf, 0x6680, 32},        /* PATTERN_SSO_FULL_XTALK_DQ1 */
+       {0x1f, 0xF, 2, 0xf, 0x6A80, 32},        /* PATTERN_SSO_FULL_XTALK_DQ2 */
+       {0x1f, 0xF, 2, 0xf, 0x6E80, 32},        /* PATTERN_SSO_FULL_XTALK_DQ3 */
+       {0x1f, 0xF, 2, 0xf, 0x7280, 32},        /* PATTERN_SSO_FULL_XTALK_DQ4 */
+       {0x1f, 0xF, 2, 0xf, 0x7680, 32},        /* PATTERN_SSO_FULL_XTALK_DQ5 */
+       {0x1f, 0xF, 2, 0xf, 0x7A80, 32},        /* PATTERN_SSO_FULL_XTALK_DQ6 */
+       {0x1f, 0xF, 2, 0xf, 0x7E80, 32},        /* PATTERN_SSO_FULL_XTALK_DQ7 */
+       {0x1f, 0xF, 2, 0xf, 0x8280, 32},        /* PATTERN_SSO_XTALK_FREE_DQ0 */
+       {0x1f, 0xF, 2, 0xf, 0x8680, 32},        /* PATTERN_SSO_XTALK_FREE_DQ1 */
+       {0x1f, 0xF, 2, 0xf, 0x8A80, 32},        /* PATTERN_SSO_XTALK_FREE_DQ2 */
+       {0x1f, 0xF, 2, 0xf, 0x8E80, 32},        /* PATTERN_SSO_XTALK_FREE_DQ3 */
+       {0x1f, 0xF, 2, 0xf, 0x9280, 32},        /* PATTERN_SSO_XTALK_FREE_DQ4 */
+       {0x1f, 0xF, 2, 0xf, 0x9680, 32},        /* PATTERN_SSO_XTALK_FREE_DQ5 */
+       {0x1f, 0xF, 2, 0xf, 0x9A80, 32},        /* PATTERN_SSO_XTALK_FREE_DQ6 */
+       {0x1f, 0xF, 2, 0xf, 0x9E80, 32},        /* PATTERN_SSO_XTALK_FREE_DQ7 */
+       {0x1f, 0xF, 2, 0xf, 0xA280, 32}         /* PATTERN_ISI_XTALK_FREE */
+       /* Note: actual start_address is "<< 3" of defined address */
 };
 
 u32 train_dev_num;
@@ -165,6 +322,10 @@ u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
        return buf_ptr;
 }
 
+enum {
+       PASS,
+       FAIL
+};
 /*
  * IP Training search
  * Note: for one edge search only from fail to pass, else jitter can
@@ -182,18 +343,19 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
                         enum hws_ddr_cs cs_type, u32 cs_num,
                         enum hws_training_ip_stat *train_status)
 {
-       u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, poll_cnt,
+       u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt,
                reg_data, pup_id;
        u32 tx_burst_size;
        u32 delay_between_burst;
        u32 rd_mode;
-       u32 read_data[MAX_INTERFACE_NUM];
+       u32 data;
        struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
        u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
        u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
-       if (pup_num >= tm->num_of_bus_per_interface) {
+       if (pup_num >= octets_per_if_num) {
                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
                                         ("pup_num %d not valid\n", pup_num));
        }
@@ -213,20 +375,20 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
                /* All CSs to CS0     */
                CHECK_STATUS(ddr3_tip_if_write
                             (dev_num, access_type, interface_num,
-                             CS_ENABLE_REG, 1 << 3, 1 << 3));
+                             DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3));
                /* All CSs to CS0     */
                CHECK_STATUS(ddr3_tip_if_write
                             (dev_num, access_type, interface_num,
-                             ODPG_DATA_CONTROL_REG,
+                             ODPG_DATA_CTRL_REG,
                              (0x3 | (effective_cs << 26)), 0xc000003));
        } else {
                CHECK_STATUS(ddr3_tip_if_write
                             (dev_num, access_type, interface_num,
-                             CS_ENABLE_REG, 0, 1 << 3));
+                             DUAL_DUNIT_CFG_REG, 0, 1 << 3));
                /*  CS select */
                CHECK_STATUS(ddr3_tip_if_write
                             (dev_num, access_type, interface_num,
-                             ODPG_DATA_CONTROL_REG, 0x3 | cs_num << 26,
+                             ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26,
                              0x3 | 3 << 26));
        }
 
@@ -248,7 +410,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
        reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa;
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, access_type, interface_num,
-                     ODPG_WRITE_READ_MODE_ENABLE_REG, reg_data,
+                     ODPG_WR_RD_MODE_ENA_REG, reg_data,
                      MASK_ALL_BITS));
        reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6;
        reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ?
@@ -271,13 +433,13 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
 
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, access_type, interface_num,
-                     ODPG_TRAINING_CONTROL_REG,
+                     GENERAL_TRAINING_OPCODE_REG,
                      reg_data | (0x7 << 8) | (0x7 << 11),
                      (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) |
                       (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20))));
        reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8);
        CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, access_type, interface_num, ODPG_OBJ1_OPCODE_REG,
+                    (dev_num, access_type, interface_num, OPCODE_REG0_REG(1),
                      1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26),
                      0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26)));
 
@@ -286,7 +448,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
         * Max number of iterations
         */
        CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
-                                      ODPG_OBJ1_ITER_CNT_REG, num_iter,
+                                      OPCODE_REG1_REG(1), num_iter,
                                       0xffff));
        if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
            direction == OPER_READ) {
@@ -294,12 +456,10 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
                 * Write2_dunit(0x10c0, 0x5f , [7:0])
                 * MC PBS Reg Address at DDR PHY
                 */
-               reg_data = 0x5f +
-                       effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET;
+               reg_data = PBS_RX_BCAST_PHY_REG(effective_cs);
        } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
                   direction == OPER_WRITE) {
-               reg_data = 0x1f +
-                       effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET;
+               reg_data = PBS_TX_BCAST_PHY_REG(effective_cs);
        } else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
                   direction == OPER_WRITE) {
                /*
@@ -310,11 +470,11 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
                 * Write2_dunit(0x10c0, 0x1 , [7:0])
                 * ADLL WR Reg Address at DDR PHY
                 */
-               reg_data = 1 + effective_cs * CS_REGISTER_ADDR_OFFSET;
+               reg_data = CTX_PHY_REG(effective_cs);
        } else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
                   direction == OPER_READ) {
                /* ADLL RD Reg Address at DDR PHY */
-               reg_data = 3 + effective_cs * CS_REGISTER_ADDR_OFFSET;
+               reg_data = CRX_PHY_REG(effective_cs);
        } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
                   direction == OPER_WRITE) {
                /* TBD not defined in 0.5.0 requirement  */
@@ -325,12 +485,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
 
        reg_data |= (0x6 << 28);
        CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, access_type, interface_num, CALIB_OBJ_PRFA_REG,
+                    (dev_num, access_type, interface_num, CAL_PHY_REG(1),
                      reg_data | (init_value << 8),
                      0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28)));
 
-       mask_dq_num_of_regs = tm->num_of_bus_per_interface * BUS_WIDTH_IN_BITS;
-       mask_pup_num_of_regs = tm->num_of_bus_per_interface;
+       mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS;
+       mask_pup_num_of_regs = octets_per_if_num;
 
        if (result_type == RESULT_PER_BIT) {
                for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
@@ -342,15 +502,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
                }
 
                /* Mask disabled buses */
-               for (pup_id = 0; pup_id < tm->num_of_bus_per_interface;
+               for (pup_id = 0; pup_id < octets_per_if_num;
                     pup_id++) {
-                       if (IS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
+                       if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
                                continue;
 
-                       for (index_cnt = (mask_dq_num_of_regs - pup_id * 8);
-                            index_cnt <
-                                    (mask_dq_num_of_regs - (pup_id + 1) * 8);
-                            index_cnt++) {
+                       for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) {
                                CHECK_STATUS(ddr3_tip_if_write
                                             (dev_num, access_type,
                                              interface_num,
@@ -384,89 +541,24 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
                }
        }
 
-       /* Start Training Trigger */
-       CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
-                                      ODPG_TRAINING_TRIGGER_REG, 1, 1));
-       /* wait for all RFU tests to finish (or timeout) */
-       /* WA for 16 bit mode, more investigation needed */
-       mdelay(1);
-
-       /* Training "Done ?" */
-       for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) {
-               if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0)
-                       continue;
-
-               if (interface_mask & (1 << index_cnt)) {
-                       /* need to check results for this Dunit */
-                       for (poll_cnt = 0; poll_cnt < max_polling_for_done;
-                            poll_cnt++) {
-                               CHECK_STATUS(ddr3_tip_if_read
-                                            (dev_num, ACCESS_TYPE_UNICAST,
-                                             index_cnt,
-                                             ODPG_TRAINING_STATUS_REG,
-                                             &reg_data, MASK_ALL_BITS));
-                               if ((reg_data & 0x2) != 0) {
-                                       /*done */
-                                       train_status[index_cnt] =
-                                               HWS_TRAINING_IP_STATUS_SUCCESS;
-                                       break;
-                               }
-                       }
-
-                       if (poll_cnt == max_polling_for_done) {
-                               train_status[index_cnt] =
-                                       HWS_TRAINING_IP_STATUS_TIMEOUT;
-                       }
-               }
-               /* Be sure that ODPG done */
-               CHECK_STATUS(is_odpg_access_done(dev_num, index_cnt));
-       }
-
-       /* Write ODPG done in Dunit */
-       CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_STATUS_DONE_REG, 0, 0x1));
+       /* trigger training */
+       mv_ddr_training_enable();
 
-       /* wait for all Dunit tests to finish (or timeout) */
-       /* Training "Done ?" */
-       /* Training "Pass ?" */
-       for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) {
-               if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0)
-                       continue;
-
-               if (interface_mask & (1 << index_cnt)) {
-                       /* need to check results for this Dunit */
-                       for (poll_cnt = 0; poll_cnt < max_polling_for_done;
-                            poll_cnt++) {
-                               CHECK_STATUS(ddr3_tip_if_read
-                                            (dev_num, ACCESS_TYPE_UNICAST,
-                                             index_cnt,
-                                             ODPG_TRAINING_TRIGGER_REG,
-                                             read_data, MASK_ALL_BITS));
-                               reg_data = read_data[index_cnt];
-                               if ((reg_data & 0x2) != 0) {
-                                       /* done */
-                                       if ((reg_data & 0x4) == 0) {
-                                               train_status[index_cnt] =
-                                                       HWS_TRAINING_IP_STATUS_SUCCESS;
-                                       } else {
-                                               train_status[index_cnt] =
-                                                       HWS_TRAINING_IP_STATUS_FAIL;
-                                       }
-                                       break;
-                               }
-                       }
+       /* wa for 16-bit mode: wait for all rfu tests to finish or timeout */
+       mdelay(1);
 
-                       if (poll_cnt == max_polling_for_done) {
-                               train_status[index_cnt] =
-                                       HWS_TRAINING_IP_STATUS_TIMEOUT;
-                       }
-               }
+       /* check for training done */
+       if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) {
+               train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT;
+       } else { /* training done; check for pass */
+               if (data == PASS)
+                       train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS;
+               else
+                       train_status[0] = HWS_TRAINING_IP_STATUS_FAIL;
        }
 
-       CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS));
+       ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+                         ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
 
        return MV_OK;
 }
@@ -480,32 +572,47 @@ int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
 {
        u32 pattern_length_cnt = 0;
        struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        for (pattern_length_cnt = 0;
             pattern_length_cnt < pattern_table[pattern].pattern_len;
-            pattern_length_cnt++) {
-               CHECK_STATUS(ddr3_tip_if_write
-                            (dev_num, access_type, if_id,
-                             ODPG_PATTERN_DATA_LOW_REG,
-                             pattern_table_get_word(dev_num, pattern,
-                                                    (u8) (pattern_length_cnt *
-                                                          2)), MASK_ALL_BITS));
-               CHECK_STATUS(ddr3_tip_if_write
-                            (dev_num, access_type, if_id,
-                             ODPG_PATTERN_DATA_HI_REG,
-                             pattern_table_get_word(dev_num, pattern,
-                                                    (u8) (pattern_length_cnt *
-                                                          2 + 1)),
-                             MASK_ALL_BITS));
+            pattern_length_cnt++) {    /* FIXME: the ecc patch below is only for a7040 A0 */
+               if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) {
+                       CHECK_STATUS(ddr3_tip_if_write
+                                    (dev_num, access_type, if_id,
+                                     ODPG_DATA_WR_DATA_LOW_REG,
+                                     pattern_table_get_word(dev_num, pattern,
+                                                            (u8) (pattern_length_cnt)),
+                                     MASK_ALL_BITS));
+                       CHECK_STATUS(ddr3_tip_if_write
+                                    (dev_num, access_type, if_id,
+                                     ODPG_DATA_WR_DATA_HIGH_REG,
+                                     pattern_table_get_word(dev_num, pattern,
+                                                            (u8) (pattern_length_cnt)),
+                                     MASK_ALL_BITS));
+               } else {
+                       CHECK_STATUS(ddr3_tip_if_write
+                                    (dev_num, access_type, if_id,
+                                             ODPG_DATA_WR_DATA_LOW_REG,
+                                     pattern_table_get_word(dev_num, pattern,
+                                                            (u8) (pattern_length_cnt * 2)),
+                                     MASK_ALL_BITS));
+                       CHECK_STATUS(ddr3_tip_if_write
+                                    (dev_num, access_type, if_id,
+                                     ODPG_DATA_WR_DATA_HIGH_REG,
+                                     pattern_table_get_word(dev_num, pattern,
+                                                            (u8) (pattern_length_cnt * 2 + 1)),
+                                     MASK_ALL_BITS));
+               }
                CHECK_STATUS(ddr3_tip_if_write
                             (dev_num, access_type, if_id,
-                             ODPG_PATTERN_ADDR_REG, pattern_length_cnt,
+                             ODPG_DATA_WR_ADDR_REG, pattern_length_cnt,
                              MASK_ALL_BITS));
        }
 
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, access_type, if_id,
-                     ODPG_PATTERN_ADDR_OFFSET_REG, load_addr, MASK_ALL_BITS));
+                     ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS));
 
        return MV_OK;
 }
@@ -527,7 +634,7 @@ int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
                      (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) |
                      (addr_stress_jump << 29));
        ret = ddr3_tip_if_write(dev_num, access_type, if_id,
-                               ODPG_DATA_CONTROL_REG, data_value, 0xaffffffc);
+                               ODPG_DATA_CTRL_REG, data_value, 0xaffffffc);
        if (ret != MV_OK)
                return ret;
 
@@ -597,7 +704,8 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
        u32 read_data[MAX_INTERFACE_NUM];
        u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
        u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        /*
         * Agreed assumption: all CS mask contain same number of bits,
@@ -605,11 +713,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
         * all pups
         */
        CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, ACCESS_TYPE_UNICAST, if_id, CS_ENABLE_REG,
+                    (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG,
                      (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3)));
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, ACCESS_TYPE_UNICAST, if_id,
-                     ODPG_DATA_CONTROL_REG, (cs_num_type << 26), (3 << 26)));
+                     ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26)));
        DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
                                 ("Read_from_d_b %d cs_type %d oper %d result_type %d direction %d search %d pup_num %d if_id %d pup_access_type %d\n",
                                  is_read_from_db, cs_num_type, operation,
@@ -621,7 +729,7 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
                                         ("ddr3_tip_read_training_result load_res = NULL"));
                return MV_FAIL;
        }
-       if (pup_num >= tm->num_of_bus_per_interface) {
+       if (pup_num >= octets_per_if_num) {
                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
                                         ("pup_num %d not valid\n", pup_num));
        }
@@ -639,11 +747,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
        } else {                /*pup_access_type == ACCESS_TYPE_MULTICAST) */
 
                start_pup = 0;
-               end_pup = tm->num_of_bus_per_interface - 1;
+               end_pup = octets_per_if_num - 1;
        }
 
        for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) {
-               VALIDATE_ACTIVE(tm->bus_act_mask, pup_cnt);
+               VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt);
                DEBUG_TRAINING_IP_ENGINE(
                        DEBUG_LEVEL_TRACE,
                        ("if_id %d start_pup %d end_pup %d pup_cnt %d\n",
@@ -689,11 +797,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
                                                      MASK_ALL_BITS));
                                        if (is_check_result_validity == 1) {
                                                if ((read_data[if_id] &
-                                                    0x02000000) == 0) {
+                                                    TIP_ENG_LOCK) == 0) {
                                                        interface_train_res
                                                                [reg_offset] =
-                                                               0x02000000 +
-                                                               64 + cons_tap;
+                                                               TIP_ENG_LOCK +
+                                                               TIP_TX_DLL_RANGE_MAX;
                                                } else {
                                                        interface_train_res
                                                                [reg_offset] =
@@ -737,60 +845,27 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
 int ddr3_tip_load_all_pattern_to_mem(u32 dev_num)
 {
        u32 pattern = 0, if_id;
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
-               VALIDATE_ACTIVE(tm->if_act_mask, if_id);
+               VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
                training_result[training_stage][if_id] = TEST_SUCCESS;
        }
 
        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
-               VALIDATE_ACTIVE(tm->if_act_mask, if_id);
+               VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
                /* enable single cs */
                CHECK_STATUS(ddr3_tip_if_write
                             (dev_num, ACCESS_TYPE_UNICAST, if_id,
-                             CS_ENABLE_REG, (1 << 3), (1 << 3)));
+                             DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
        }
 
-       for (pattern = 0; pattern < PATTERN_LIMIT; pattern++)
+       for (pattern = 0; pattern < PATTERN_LAST; pattern++)
                ddr3_tip_load_pattern_to_mem(dev_num, pattern);
 
        return MV_OK;
 }
 
-/*
- * Wait till ODPG access is ready
- */
-int is_odpg_access_done(u32 dev_num, u32 if_id)
-{
-       u32 poll_cnt = 0, data_value;
-       u32 read_data[MAX_INTERFACE_NUM];
-
-       for (poll_cnt = 0; poll_cnt < MAX_POLLING_ITERATIONS; poll_cnt++) {
-               CHECK_STATUS(ddr3_tip_if_read
-                            (dev_num, ACCESS_TYPE_UNICAST, if_id,
-                             ODPG_BIST_DONE, read_data, MASK_ALL_BITS));
-               data_value = read_data[if_id];
-               if (((data_value >> ODPG_BIST_DONE_BIT_OFFS) & 0x1) ==
-                   ODPG_BIST_DONE_BIT_VALUE) {
-                               data_value = data_value & 0xfffffffe;
-                               CHECK_STATUS(ddr3_tip_if_write
-                                            (dev_num, ACCESS_TYPE_UNICAST,
-                                             if_id, ODPG_BIST_DONE, data_value,
-                                             MASK_ALL_BITS));
-                               break;
-                       }
-       }
-
-       if (poll_cnt >= MAX_POLLING_ITERATIONS) {
-               DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
-                                        ("Bist Activate: poll failure 2\n"));
-               return MV_FAIL;
-       }
-
-       return MV_OK;
-}
-
 /*
  * Load specific pattern to memory using ODPG
  */
@@ -798,7 +873,7 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern)
 {
        u32 reg_data, if_id;
        struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        /* load pattern to memory */
        /*
@@ -813,73 +888,65 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern)
                (effective_cs << 26);
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_DATA_CONTROL_REG, reg_data, MASK_ALL_BITS));
+                     ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS));
        /* ODPG Write enable from BIST */
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_DATA_CONTROL_REG, (0x1 | (effective_cs << 26)),
+                     ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)),
                      0xc000003));
        /* disable error injection */
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_WRITE_DATA_ERROR_REG, 0, 0x1));
+                     ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1));
        /* load pattern to ODPG */
        ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
                                      PARAM_NOT_CARE, pattern,
                                      pattern_table[pattern].start_addr);
 
-       for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
-               if (IS_ACTIVE(tm->if_act_mask, if_id) == 0)
-                       continue;
+       if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
+               for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+                       VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
 
+                       CHECK_STATUS(ddr3_tip_if_write
+                                    (dev_num, ACCESS_TYPE_UNICAST, if_id,
+                                     SDRAM_ODT_CTRL_HIGH_REG,
+                                     0x3, 0xf));
+               }
+
+               mv_ddr_odpg_enable();
+       } else {
                CHECK_STATUS(ddr3_tip_if_write
-                            (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1498,
-                             0x3, 0xf));
+                            (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+                             ODPG_DATA_CTRL_REG, (u32)(0x1 << 31),
+                             (u32)(0x1 << 31)));
        }
-
-       CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_ENABLE_REG, 0x1 << ODPG_ENABLE_OFFS,
-                     (0x1 << ODPG_ENABLE_OFFS)));
-
        mdelay(1);
 
-       for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
-               VALIDATE_ACTIVE(tm->if_act_mask, if_id);
-               CHECK_STATUS(is_odpg_access_done(dev_num, if_id));
-       }
+       if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK)
+               return MV_FAIL;
 
        /* Disable ODPG and stop write to memory */
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_DATA_CONTROL_REG, (0x1 << 30), (u32) (0x3 << 30)));
+                     ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30)));
 
        /* return to default */
        CHECK_STATUS(ddr3_tip_if_write
                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
-                     ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS));
-
-       /* Disable odt0 for CS0 training - need to adjust for multy CS */
-       CHECK_STATUS(ddr3_tip_if_write
-                    (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498,
-                     0x0, 0xf));
+                     ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS));
 
+       if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
+               /* Disable odt0 for CS0 training - need to adjust for multy CS */
+               CHECK_STATUS(ddr3_tip_if_write
+                            (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+                             SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf));
+       }
        /* temporary added */
        mdelay(1);
 
        return MV_OK;
 }
 
-/*
- * Load specific pattern to memory using CPU
- */
-int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern,
-                                       u32 offset)
-{
-       /* eranba - TBD */
-       return MV_OK;
-}
-
 /*
  * Training search routine
  */
@@ -902,8 +969,9 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
        u32 interface_num = 0, start_if, end_if, init_value_used;
        enum hws_search_dir search_dir_id, start_search, end_search;
        enum hws_edge_compare edge_comp_used;
-       u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       u8 cons_tap = 0;
+       u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        if (train_status == NULL) {
                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
@@ -913,12 +981,12 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
 
        if ((train_cs_type > CS_NON_SINGLE) ||
            (edge_comp >= EDGE_PFP) ||
-           (pattern >= PATTERN_LIMIT) ||
+           (pattern >= PATTERN_LAST) ||
            (direction > OPER_WRITE_AND_READ) ||
            (search_dir > HWS_HIGH2LOW) ||
            (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) ||
            (result_type > RESULT_PER_BYTE) ||
-           (pup_num >= tm->num_of_bus_per_interface) ||
+           (pup_num >= octets_per_if_num) ||
            (pup_access_type > ACCESS_TYPE_MULTICAST) ||
            (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) {
                DEBUG_TRAINING_IP_ENGINE(
@@ -968,7 +1036,7 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
 
                for (interface_num = start_if; interface_num <= end_if;
                     interface_num++) {
-                       VALIDATE_ACTIVE(tm->if_act_mask, interface_num);
+                       VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num);
                        cs_num = 0;
                        CHECK_STATUS(ddr3_tip_read_training_result
                                     (dev_num, interface_num, pup_access_type,
@@ -982,48 +1050,99 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
 
        return MV_OK;
 }
-
 /*
  * Training search & read result routine
+ * This function implements the search algorithm
+ * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l
+ * this function handles rx and tx search cases
+ * in case of rx it only triggers the search (l2h and h2l)
+ * in case of tx there are 3 optional algorithm phases:
+ * phase 1:
+ * it first triggers the search and handles the results as following (phase 1):
+ * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases:
+ *  1. BIT_LOW_UI      0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31
+ *  2. BIT_HIGH_UI     32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32
+ *  3. BIT_SPLIT_IN    VW_L <= 31 & VW_H >= 32
+ *  4. BIT_SPLIT_OUT*  VW_H < 32 &  VW_L > 32
+ * note: the VW units is adll taps
+ * phase 2:
+ * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h
+ * because only this case is not locked by the search engine in the first search trigger (phase 1).
+ * phase 3:
+ * each subphy is categorized according to its bits definition.
+ * the sub-phy cases are as follows:
+ *  1.BYTE_NOT_DEFINED                 the byte has not yet been categorized
+ *  2.BYTE_HOMOGENEOUS_LOW             0 =< VW =< 31
+ *  3.BYTE_HOMOGENEOUS_HIGH            32 =< VW =< 63
+ *  4.BYTE_HOMOGENEOUS_SPLIT_IN                VW_L <= 31 & VW_H >= 32
+ *                                     or the center of all bits in the byte  =< 31
+ *  5.BYTE_HOMOGENEOUS_SPLIT_OUT       VW_H < 32 &  VW_L > 32
+ *  6.BYTE_SPLIT_OUT_MIX               at least one bits is in split out state and one bit is in other
+ *                                     or the center of all bits in the byte => 32
+ * after the two phases above a center valid window for each subphy is calculated accordingly:
+ * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy.
+ * now decisions are made in each subphy as following:
+ * all subphys which are homogeneous remains as is
+ * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32
+ *     mark this subphy as homogeneous split in.
+ * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following
+ * all bits which are BIT_LOW_UI will be added with 64 adll,
+ * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs
  */
 int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type,
-                                u32 if_id,
-                                enum hws_access_type pup_access_type,
-                                u32 pup_num,
-                                enum hws_training_result result_type,
-                                enum hws_control_element control_element,
-                                enum hws_search_dir search_dir,
-                                enum hws_dir direction, u32 interface_mask,
-                                u32 init_value_l2h, u32 init_value_h2l,
-                                u32 num_iter, enum hws_pattern pattern,
-                                enum hws_edge_compare edge_comp,
-                                enum hws_ddr_cs train_cs_type, u32 cs_num,
-                                enum hws_training_ip_stat *train_status)
+       u32 if_id,
+       enum hws_access_type pup_access_type,
+       u32 pup_num,
+       enum hws_training_result result_type,
+       enum hws_control_element control_element,
+       enum hws_search_dir search_dir,
+       enum hws_dir direction, u32 interface_mask,
+       u32 init_value_l2h, u32 init_value_h2l,
+       u32 num_iter, enum hws_pattern pattern,
+       enum hws_edge_compare edge_comp,
+       enum hws_ddr_cs train_cs_type, u32 cs_num,
+       enum hws_training_ip_stat *train_status)
 {
        u8 e1, e2;
-       u32 interface_cnt, bit_id, start_if, end_if, bit_end = 0;
+       u32 bit_id, start_if, end_if, bit_end = 0;
        u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 };
        u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
        u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0;
-       u8 pup_id;
-       struct hws_topology_map *tm = ddr3_get_topology_map();
-
-       if (pup_num >= tm->num_of_bus_per_interface) {
+       u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0};
+       u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+       u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+       u8 center_subphy_adll_window[MAX_BUS_NUM];
+       u8 min_center_subphy_adll[MAX_BUS_NUM];
+       u8 max_center_subphy_adll[MAX_BUS_NUM];
+       u32 *l2h_if_train_res = NULL;
+       u32 *h2l_if_train_res = NULL;
+       enum hws_search_dir search_dir_id;
+       int status;
+       u32 bit_lock_result;
+
+       u8 sybphy_id;
+       u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+       if (pup_num >= octets_per_if_num) {
                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
-                                        ("pup_num %d not valid\n", pup_num));
+                       ("pup_num %d not valid\n", pup_num));
        }
 
        if (if_id >= MAX_INTERFACE_NUM) {
                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
-                                        ("if_id %d not valid\n", if_id));
+                       ("if_id %d not valid\n", if_id));
        }
 
-       CHECK_STATUS(ddr3_tip_ip_training_wrapper_int
-                    (dev_num, access_type, if_id, pup_access_type, pup_num,
-                     ALL_BITS_PER_PUP, result_type, control_element,
-                     search_dir, direction, interface_mask, init_value_l2h,
-                     init_value_h2l, num_iter, pattern, edge_comp,
-                     train_cs_type, cs_num, train_status));
+       status = ddr3_tip_ip_training_wrapper_int
+               (dev_num, access_type, if_id, pup_access_type, pup_num,
+               ALL_BITS_PER_PUP, result_type, control_element,
+               search_dir, direction, interface_mask, init_value_l2h,
+               init_value_h2l, num_iter, pattern, edge_comp,
+               train_cs_type, cs_num, train_status);
+
+       if (MV_OK != status)
+               return status;
 
        if (access_type == ACCESS_TYPE_MULTICAST) {
                start_if = 0;
@@ -1033,181 +1152,337 @@ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type,
                end_if = if_id;
        }
 
-       for (interface_cnt = start_if; interface_cnt <= end_if;
-            interface_cnt++) {
-               VALIDATE_ACTIVE(tm->if_act_mask, interface_cnt);
-               for (pup_id = 0;
-                    pup_id <= (tm->num_of_bus_per_interface - 1); pup_id++) {
-                       VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
+       for (if_id = start_if; if_id <= end_if; if_id++) {
+               VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+               /* zero the database */
+               bit_bit_mask_active = 0;        /* clean the flag for level2 search */
+               memset(bit_state, 0, sizeof(bit_state));
+               /* phase 1 */
+               for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
+                       VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
                        if (result_type == RESULT_PER_BIT)
-                               bit_end = BUS_WIDTH_IN_BITS - 1;
+                               bit_end = BUS_WIDTH_IN_BITS;
                        else
                                bit_end = 0;
 
-                       bit_bit_mask[pup_id] = 0;
-                       for (bit_id = 0; bit_id <= bit_end; bit_id++) {
-                               enum hws_search_dir search_dir_id;
-                               for (search_dir_id = HWS_LOW2HIGH;
-                                    search_dir_id <= HWS_HIGH2LOW;
-                                    search_dir_id++) {
-                                       CHECK_STATUS
-                                               (ddr3_tip_read_training_result
-                                                (dev_num, interface_cnt,
-                                                 ACCESS_TYPE_UNICAST, pup_id,
-                                                 bit_id, search_dir_id,
-                                                 direction, result_type,
-                                                 TRAINING_LOAD_OPERATION_UNLOAD,
-                                                 CS_SINGLE,
-                                                 &result[search_dir_id],
-                                                 1, 0, 0));
+                       /* zero the data base */
+                       bit_bit_mask[sybphy_id] = 0;
+                       byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED;
+                       for (bit_id = 0; bit_id < bit_end; bit_id++) {
+                               h2l_adll_value[sybphy_id][bit_id] = 64;
+                               l2h_adll_value[sybphy_id][bit_id] = 0;
+                               for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW;
+                                       search_dir_id++) {
+                                       status = ddr3_tip_read_training_result
+                                               (dev_num, if_id,
+                                                       ACCESS_TYPE_UNICAST, sybphy_id, bit_id,
+                                                       search_dir_id, direction, result_type,
+                                                       TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
+                                                       &result[search_dir_id], 1, 0, 0);
+
+                                       if (MV_OK != status)
+                                               return status;
                                }
-                               e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0],
-                                                   EDGE_1);
-                               e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0],
-                                                   EDGE_1);
-                               DEBUG_TRAINING_IP_ENGINE(
-                                       DEBUG_LEVEL_INFO,
-                                       ("wrapper if_id %d pup_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n",
-                                        interface_cnt, pup_id, bit_id,
-                                        result[HWS_LOW2HIGH][0], e1,
+
+                               e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1);
+                               e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1);
+                               DEBUG_TRAINING_IP_ENGINE
+                                       (DEBUG_LEVEL_INFO,
+                                        ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n",
+                                        if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1,
                                         result[HWS_HIGH2LOW][0], e2));
-                               /* TBD validate is valid only for tx */
-                               if (VALIDATE_TRAINING_LIMIT(e1, e2) == 1 &&
-                                   GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) &&
-                                   GET_LOCK_RESULT(result[HWS_LOW2HIGH][0])) {
-                                       /* Mark problem bits */
-                                       bit_bit_mask[pup_id] |= 1 << bit_id;
-                                       bit_bit_mask_active = 1;
+                               bit_lock_result =
+                                       (GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) &&
+                                               GET_LOCK_RESULT(result[HWS_HIGH2LOW][0]));
+
+                               if (bit_lock_result) {
+                                       /* in case of read operation set the byte status as homogeneous low */
+                                       if (direction == OPER_READ) {
+                                               byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW;
+                                       } else if ((e2 - e1) > 32) { /* oper_write */
+                                               /* split out */
+                                               bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
+                                                       BIT_SPLIT_OUT;
+                                               byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT;
+                                               /* mark problem bits */
+                                               bit_bit_mask[sybphy_id] |= (1 << bit_id);
+                                               bit_bit_mask_active = 1;
+                                               DEBUG_TRAINING_IP_ENGINE
+                                                       (DEBUG_LEVEL_TRACE,
+                                                        ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n",
+                                                        if_id, sybphy_id, bit_id));
+                                       } else {
+                                               /* low ui */
+                                               if (e1 <= 31 && e2 <= 31) {
+                                                       bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
+                                                               BIT_LOW_UI;
+                                                       byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW;
+                                                       l2h_adll_value[sybphy_id][bit_id] = e1;
+                                                       h2l_adll_value[sybphy_id][bit_id] = e2;
+                                                       DEBUG_TRAINING_IP_ENGINE
+                                                               (DEBUG_LEVEL_TRACE,
+                                                                ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n",
+                                                                if_id, sybphy_id, bit_id));
+                                               }
+                                                       /* high ui */
+                                               if (e1 >= 32 && e2 >= 32) {
+                                                       bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
+                                                               BIT_HIGH_UI;
+                                                       byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH;
+                                                       l2h_adll_value[sybphy_id][bit_id] = e1;
+                                                       h2l_adll_value[sybphy_id][bit_id] = e2;
+                                                       DEBUG_TRAINING_IP_ENGINE
+                                                               (DEBUG_LEVEL_TRACE,
+                                                                ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n",
+                                                                if_id, sybphy_id, bit_id));
+                                               }
+                                               /* split in */
+                                               if (e1 <= 31 && e2 >= 32) {
+                                                       bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
+                                                               BIT_SPLIT_IN;
+                                                       byte_status[if_id][sybphy_id] |=
+                                                               BYTE_HOMOGENEOUS_SPLIT_IN;
+                                                       l2h_adll_value[sybphy_id][bit_id] = e1;
+                                                       h2l_adll_value[sybphy_id][bit_id] = e2;
+                                                       DEBUG_TRAINING_IP_ENGINE
+                                                               (DEBUG_LEVEL_TRACE,
+                                                                ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n",
+                                                                if_id, sybphy_id, bit_id));
+                                               }
+                                       }
+                               } else {
+                                       DEBUG_TRAINING_IP_ENGINE
+                                               (DEBUG_LEVEL_INFO,
+                                                ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)"
+                                                "h2l 0x%x (e2 0x%x): bit cannot be categorized\n",
+                                                if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1,
+                                                result[HWS_HIGH2LOW][0], e2));
+                                       /* mark the byte as not defined */
+                                       byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED;
+                                       break; /* continue to next pup - no reason to analyze this byte */
                                }
-                       }       /* For all bits */
-               }               /* For all PUPs */
+                       } /* for all bits */
+               } /* for all PUPs */
 
-               /* Fix problem bits */
+               /* phase 2 will occur only in write operation */
                if (bit_bit_mask_active != 0) {
-                       u32 *l2h_if_train_res = NULL;
-                       u32 *h2l_if_train_res = NULL;
-                       l2h_if_train_res =
-                               ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH,
-                                                    result_type,
-                                                    interface_cnt);
-                       h2l_if_train_res =
-                               ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW,
-                                                    result_type,
-                                                    interface_cnt);
-
-                       ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST,
-                                            interface_cnt,
-                                            ACCESS_TYPE_MULTICAST,
-                                            PARAM_NOT_CARE, result_type,
-                                            control_element, HWS_LOW2HIGH,
-                                            direction, interface_mask,
-                                            num_iter / 2, num_iter / 2,
-                                            pattern, EDGE_FP, train_cs_type,
-                                            cs_num, train_status);
-
-                       for (pup_id = 0;
-                            pup_id <= (tm->num_of_bus_per_interface - 1);
-                            pup_id++) {
-                               VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
-
-                               if (bit_bit_mask[pup_id] == 0)
-                                       continue;
-
-                               for (bit_id = 0; bit_id <= bit_end; bit_id++) {
-                                       if ((bit_bit_mask[pup_id] &
-                                            (1 << bit_id)) == 0)
+                       l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id);
+                       h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id);
+                       /* search from middle to end */
+                       ddr3_tip_ip_training
+                               (dev_num, ACCESS_TYPE_UNICAST,
+                                if_id, ACCESS_TYPE_MULTICAST,
+                                PARAM_NOT_CARE, result_type,
+                                control_element, HWS_LOW2HIGH,
+                                direction, interface_mask,
+                                num_iter / 2, num_iter / 2,
+                                pattern, EDGE_FP, train_cs_type,
+                                cs_num, train_status);
+
+                       for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
+                               VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
+                               if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) {
+                                       if (bit_bit_mask[sybphy_id] == 0)
+                                               continue; /* this byte bits have no split out state */
+
+                                       for (bit_id = 0; bit_id < bit_end; bit_id++) {
+                                               if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0)
+                                                       continue; /* this bit is non split goto next bit */
+
+                                               /* enter the result to the data base */
+                                               status = ddr3_tip_read_training_result
+                                                       (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id,
+                                                        bit_id, HWS_LOW2HIGH, direction, result_type,
+                                                        TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
+                                                        &l2h_if_train_res, 0, 0, 1);
+
+                                               if (MV_OK != status)
+                                                       return status;
+
+                                               l2h_adll_value[sybphy_id][bit_id] =
+                                                       l2h_if_train_res[sybphy_id *
+                                                       BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK;
+                                       }
+                               }
+                       }
+                       /* Search from middle to start */
+                       ddr3_tip_ip_training
+                               (dev_num, ACCESS_TYPE_UNICAST,
+                                if_id, ACCESS_TYPE_MULTICAST,
+                                PARAM_NOT_CARE, result_type,
+                                control_element, HWS_HIGH2LOW,
+                                direction, interface_mask,
+                                num_iter / 2, num_iter / 2,
+                                pattern, EDGE_FP, train_cs_type,
+                                cs_num, train_status);
+
+                       for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
+                               VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
+                               if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) {
+                                       if (bit_bit_mask[sybphy_id] == 0)
                                                continue;
-                                       CHECK_STATUS
-                                               (ddr3_tip_read_training_result
-                                                (dev_num, interface_cnt,
-                                                 ACCESS_TYPE_UNICAST, pup_id,
-                                                 bit_id, HWS_LOW2HIGH,
-                                                 direction,
-                                                 result_type,
-                                                 TRAINING_LOAD_OPERATION_UNLOAD,
-                                                 CS_SINGLE, &l2h_if_train_res,
-                                                 0, 0, 1));
+
+                                       for (bit_id = 0; bit_id < bit_end; bit_id++) {
+                                               if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0)
+                                                       continue;
+
+                                               status = ddr3_tip_read_training_result
+                                                       (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id,
+                                                        bit_id, HWS_HIGH2LOW, direction, result_type,
+                                                        TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
+                                                        &h2l_if_train_res, 0, cons_tap, 1);
+
+                                               if (MV_OK != status)
+                                                       return status;
+
+                                               h2l_adll_value[sybphy_id][bit_id] =
+                                                       h2l_if_train_res[sybphy_id *
+                                                       BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK;
+                                       }
                                }
                        }
+               } /* end if bit_bit_mask_active */
+               /*
+                       * phase 3 will occur only in write operation
+                       * find the maximum and the minimum center of each subphy
+                       */
+               for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
+                       VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
+
+                       if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) {
+                               /* clear the arrays and parameters */
+                               center_subphy_adll_window[sybphy_id] = 0;
+                               max_center_subphy_adll[sybphy_id] = 0;
+                               min_center_subphy_adll[sybphy_id] = 64;
+                               /* find the max and min center adll value in the current subphy */
+                               for (bit_id = 0; bit_id < bit_end; bit_id++) {
+                                       /* debug print all the bit edges after alignment */
+                                       DEBUG_TRAINING_IP_ENGINE
+                                               (DEBUG_LEVEL_TRACE,
+                                                ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n",
+                                                if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id],
+                                                h2l_adll_value[sybphy_id][bit_id]));
+
+                                       if (((l2h_adll_value[sybphy_id][bit_id] +
+                                             h2l_adll_value[sybphy_id][bit_id]) / 2) >
+                                             max_center_subphy_adll[sybphy_id])
+                                               max_center_subphy_adll[sybphy_id] =
+                                               (l2h_adll_value[sybphy_id][bit_id] +
+                                                h2l_adll_value[sybphy_id][bit_id]) / 2;
+                                       if (((l2h_adll_value[sybphy_id][bit_id] +
+                                             h2l_adll_value[sybphy_id][bit_id]) / 2) <
+                                             min_center_subphy_adll[sybphy_id])
+                                               min_center_subphy_adll[sybphy_id] =
+                                               (l2h_adll_value[sybphy_id][bit_id] +
+                                                h2l_adll_value[sybphy_id][bit_id]) / 2;
+                               }
 
-                       ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST,
-                                            interface_cnt,
-                                            ACCESS_TYPE_MULTICAST,
-                                            PARAM_NOT_CARE, result_type,
-                                            control_element, HWS_HIGH2LOW,
-                                            direction, interface_mask,
-                                            num_iter / 2, num_iter / 2,
-                                            pattern, EDGE_FP, train_cs_type,
-                                            cs_num, train_status);
-
-                       for (pup_id = 0;
-                            pup_id <= (tm->num_of_bus_per_interface - 1);
-                            pup_id++) {
-                               VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
-
-                               if (bit_bit_mask[pup_id] == 0)
-                                       continue;
-
-                               for (bit_id = 0; bit_id <= bit_end; bit_id++) {
-                                       if ((bit_bit_mask[pup_id] &
-                                            (1 << bit_id)) == 0)
-                                               continue;
-                                       CHECK_STATUS
-                                               (ddr3_tip_read_training_result
-                                                (dev_num, interface_cnt,
-                                                 ACCESS_TYPE_UNICAST, pup_id,
-                                                 bit_id, HWS_HIGH2LOW, direction,
-                                                 result_type,
-                                                 TRAINING_LOAD_OPERATION_UNLOAD,
-                                                 CS_SINGLE, &h2l_if_train_res,
-                                                 0, cons_tap, 1));
+                               /* calculate the center of the current subphy */
+                               center_subphy_adll_window[sybphy_id] =
+                                       max_center_subphy_adll[sybphy_id] -
+                                       min_center_subphy_adll[sybphy_id];
+                               DEBUG_TRAINING_IP_ENGINE
+                                       (DEBUG_LEVEL_TRACE,
+                                        ("if_id %d sybphy_id %d min center %d max center %d center %d\n",
+                                        if_id, sybphy_id, min_center_subphy_adll[sybphy_id],
+                                        max_center_subphy_adll[sybphy_id],
+                                        center_subphy_adll_window[sybphy_id]));
+                       }
+               }
+               /*
+                       * check byte state and fix bits state if needed
+                       * in case the level 1 and 2 above subphy results are
+                       * homogeneous continue to the next subphy
+                       */
+               for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
+                       VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
+                       if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) ||
+                           (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) ||
+                           (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) ||
+                           (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) ||
+                           (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED))
+                       continue;
+
+                       /*
+                        * in case all of the bits in the current subphy are
+                        * less than 32 which will find alignment in the subphy bits
+                        * mark this subphy as homogeneous split in
+                       */
+                       if (center_subphy_adll_window[sybphy_id] <= 31)
+                               byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN;
+
+                       /*
+                               * in case the current byte is split_out and the center is bigger than 31
+                               * the byte can be aligned. in this case add 64 to the the low ui bits aligning it
+                               * to the other ui bits
+                               */
+                       if (center_subphy_adll_window[sybphy_id] >= 32) {
+                               byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX;
+
+                               DEBUG_TRAINING_IP_ENGINE
+                                       (DEBUG_LEVEL_TRACE,
+                                        ("if_id %d sybphy_id %d byte state 0x%x\n",
+                                        if_id, sybphy_id, byte_status[if_id][sybphy_id]));
+                               for (bit_id = 0; bit_id < bit_end; bit_id++) {
+                                       if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) {
+                                               l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64;
+                                               h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64;
+                                       }
+                                       DEBUG_TRAINING_IP_ENGINE
+                                               (DEBUG_LEVEL_TRACE,
+                                                ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n",
+                                                if_id, sybphy_id, bit_id));
                                }
                        }
-               }               /* if bit_bit_mask_active */
-       }                       /* For all Interfacess */
+               }
+       } /* for all interfaces */
 
        return MV_OK;
 }
 
+u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id)
+{
+       return byte_status[if_id][subphy_id];
+}
+
+void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data)
+{
+       byte_status[if_id][subphy_id] = byte_status_data;
+}
+
 /*
  * Load phy values
  */
 int ddr3_tip_load_phy_values(int b_load)
 {
        u32 bus_cnt = 0, if_id, dev_num = 0;
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
-               VALIDATE_ACTIVE(tm->if_act_mask, if_id);
-               for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES();
-                    bus_cnt++) {
-                       VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt);
+               VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+               for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
+                       VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
                        if (b_load == 1) {
                                CHECK_STATUS(ddr3_tip_bus_read
                                             (dev_num, if_id,
                                              ACCESS_TYPE_UNICAST, bus_cnt,
                                              DDR_PHY_DATA,
-                                             WRITE_CENTRALIZATION_PHY_REG +
-                                             (effective_cs *
-                                              CS_REGISTER_ADDR_OFFSET),
+                                             CTX_PHY_REG(effective_cs),
                                              &phy_reg_bk[if_id][bus_cnt]
                                              [0]));
                                CHECK_STATUS(ddr3_tip_bus_read
                                             (dev_num, if_id,
                                              ACCESS_TYPE_UNICAST, bus_cnt,
                                              DDR_PHY_DATA,
-                                             RL_PHY_REG +
-                                             (effective_cs *
-                                              CS_REGISTER_ADDR_OFFSET),
+                                             RL_PHY_REG(effective_cs),
                                              &phy_reg_bk[if_id][bus_cnt]
                                              [1]));
                                CHECK_STATUS(ddr3_tip_bus_read
                                             (dev_num, if_id,
                                              ACCESS_TYPE_UNICAST, bus_cnt,
                                              DDR_PHY_DATA,
-                                             READ_CENTRALIZATION_PHY_REG +
-                                             (effective_cs *
-                                              CS_REGISTER_ADDR_OFFSET),
+                                             CRX_PHY_REG(effective_cs),
                                              &phy_reg_bk[if_id][bus_cnt]
                                              [2]));
                        } else {
@@ -1215,27 +1490,21 @@ int ddr3_tip_load_phy_values(int b_load)
                                             (dev_num, ACCESS_TYPE_UNICAST,
                                              if_id, ACCESS_TYPE_UNICAST,
                                              bus_cnt, DDR_PHY_DATA,
-                                             WRITE_CENTRALIZATION_PHY_REG +
-                                             (effective_cs *
-                                              CS_REGISTER_ADDR_OFFSET),
+                                             CTX_PHY_REG(effective_cs),
                                              phy_reg_bk[if_id][bus_cnt]
                                              [0]));
                                CHECK_STATUS(ddr3_tip_bus_write
                                             (dev_num, ACCESS_TYPE_UNICAST,
                                              if_id, ACCESS_TYPE_UNICAST,
                                              bus_cnt, DDR_PHY_DATA,
-                                             RL_PHY_REG +
-                                             (effective_cs *
-                                              CS_REGISTER_ADDR_OFFSET),
+                                             RL_PHY_REG(effective_cs),
                                              phy_reg_bk[if_id][bus_cnt]
                                              [1]));
                                CHECK_STATUS(ddr3_tip_bus_write
                                             (dev_num, ACCESS_TYPE_UNICAST,
                                              if_id, ACCESS_TYPE_UNICAST,
                                              bus_cnt, DDR_PHY_DATA,
-                                             READ_CENTRALIZATION_PHY_REG +
-                                             (effective_cs *
-                                              CS_REGISTER_ADDR_OFFSET),
+                                             CRX_PHY_REG(effective_cs),
                                              phy_reg_bk[if_id][bus_cnt]
                                              [2]));
                        }
@@ -1257,7 +1526,8 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
        enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
        u32 *res = NULL;
        u32 search_state = 0;
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        ddr3_tip_load_phy_values(1);
 
@@ -1279,11 +1549,11 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
 
                        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
                             if_id++) {
-                               VALIDATE_ACTIVE(tm->if_act_mask, if_id);
+                               VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
                                for (pup_id = 0; pup_id <
-                                            tm->num_of_bus_per_interface;
+                                            octets_per_if_num;
                                     pup_id++) {
-                                       VALIDATE_ACTIVE(tm->bus_act_mask,
+                                       VALIDATE_BUS_ACTIVE(tm->bus_act_mask,
                                                        pup_id);
                                        CHECK_STATUS
                                                (ddr3_tip_read_training_result
@@ -1322,11 +1592,20 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
        return MV_OK;
 }
 
+int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr)
+{
+       pattern_tbl[pattern].start_addr = addr;
+
+       return 0;
+}
+
 struct pattern_info *ddr3_tip_get_pattern_table()
 {
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
-       if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0)
+       if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask))
+               return pattern_table_64;
+       else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0)
                return pattern_table_32;
        else
                return pattern_table_16;
@@ -1334,20 +1613,63 @@ struct pattern_info *ddr3_tip_get_pattern_table()
 
 u16 *ddr3_tip_get_mask_results_dq_reg()
 {
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+#if MAX_BUS_NUM == 5
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
                return mask_results_dq_reg_map_pup3_ecc;
        else
+#endif
                return mask_results_dq_reg_map;
 }
 
 u16 *ddr3_tip_get_mask_results_pup_reg_map()
 {
-       struct hws_topology_map *tm = ddr3_get_topology_map();
+#if MAX_BUS_NUM == 5
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
 
        if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
                return mask_results_pup_reg_map_pup3_ecc;
        else
+#endif
                return mask_results_pup_reg_map;
 }
+
+/* load expected dm pattern to odpg */
+#define LOW_NIBBLE_BYTE_MASK   0xf
+#define HIGH_NIBBLE_BYTE_MASK  0xf0
+int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern,
+                                  enum dm_direction dm_dir)
+{
+       struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+       struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+       u32 pattern_len = 0;
+       u32 data_low, data_high;
+       u8 dm_data;
+
+       for (pattern_len = 0;
+            pattern_len < pattern_table[pattern].pattern_len;
+            pattern_len++) {
+               if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) {
+                       data_low = pattern_table_get_word(0, pattern, (u8)pattern_len);
+                       data_high = data_low;
+               } else {
+                       data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2));
+                       data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1));
+               }
+
+               /* odpg mbus dm definition is opposite to ddr4 protocol */
+               if (dm_dir == DM_DIR_INVERSE)
+                       dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK));
+               else
+                       dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK);
+
+               ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS);
+               ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS);
+               ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG,
+                                 pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS),
+                                 MASK_ALL_BITS);
+       }
+
+       return MV_OK;
+}