aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/ddr/marvell/a38x
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/ddr/marvell/a38x')
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/Makefile19
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_debug.c1386
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.c148
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.h192
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_logging_def.h104
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h924
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training.c2898
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_bist.c603
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_centralization.c716
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_db.c874
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c677
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.h13
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip.h146
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h57
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_centralization.h14
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h94
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h167
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c1680
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h86
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h120
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_pbs.h40
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h117
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.c1963
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.h15
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_pbs.c1012
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h146
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr_topology_def.h228
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/ddr_training_ip_db.h13
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/dram_if.h13
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_build_message.c3
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.c47
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.h54
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.c1446
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.h243
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_regs.h465
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.c375
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.h295
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c102
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h95
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.c362
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.h332
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_training_db.h40
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/seq_exec.h64
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/xor.c464
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/xor.h90
-rw-r--r--roms/u-boot/drivers/ddr/marvell/a38x/xor_regs.h235
46 files changed, 19177 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/Makefile b/roms/u-boot/drivers/ddr/marvell/a38x/Makefile
new file mode 100644
index 000000000..8251d6db6
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_SPL_BUILD) += mv_ddr_plat.o
+obj-$(CONFIG_SPL_BUILD) += mv_ddr_sys_env_lib.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_debug.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_init.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_bist.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_centralization.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_db.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_hw_algo.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_ip_engine.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_leveling.o
+obj-$(CONFIG_SPL_BUILD) += ddr3_training_pbs.o
+obj-$(CONFIG_SPL_BUILD) += mv_ddr_build_message.o
+obj-$(CONFIG_SPL_BUILD) += mv_ddr_common.o
+obj-$(CONFIG_SPL_BUILD) += mv_ddr_spd.o
+obj-$(CONFIG_SPL_BUILD) += mv_ddr_topology.o
+obj-$(CONFIG_SPL_BUILD) += xor.o
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_debug.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_debug.c
new file mode 100644
index 000000000..f5fc964d6
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -0,0 +1,1386 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_training_db.h"
+#include "mv_ddr_regs.h"
+
+u8 is_reg_dump = 0;
+u8 debug_pbs = DEBUG_LEVEL_ERROR;
+
+/*
+ * API to change flags outside of the lib
+ */
+#if defined(SILENT_LIB)
+void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level)
+{
+ /* do nothing */
+}
+#else /* SILENT_LIB */
+/* Debug flags for other Training modules */
+u8 debug_training_static = DEBUG_LEVEL_ERROR;
+u8 debug_training = DEBUG_LEVEL_ERROR;
+u8 debug_leveling = DEBUG_LEVEL_ERROR;
+u8 debug_centralization = DEBUG_LEVEL_ERROR;
+u8 debug_training_ip = DEBUG_LEVEL_ERROR;
+u8 debug_training_bist = DEBUG_LEVEL_ERROR;
+u8 debug_training_hw_alg = DEBUG_LEVEL_ERROR;
+u8 debug_training_access = DEBUG_LEVEL_ERROR;
+u8 debug_training_device = DEBUG_LEVEL_ERROR;
+
+
+void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ ddr3_hws_set_log_level(block, tm->debug_level);
+};
+
+void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level)
+{
+ switch (block) {
+ case DEBUG_BLOCK_STATIC:
+ debug_training_static = level;
+ break;
+ case DEBUG_BLOCK_TRAINING_MAIN:
+ debug_training = level;
+ break;
+ case DEBUG_BLOCK_LEVELING:
+ debug_leveling = level;
+ break;
+ case DEBUG_BLOCK_CENTRALIZATION:
+ debug_centralization = level;
+ break;
+ case DEBUG_BLOCK_PBS:
+ debug_pbs = level;
+ break;
+ case DEBUG_BLOCK_ALG:
+ debug_training_hw_alg = level;
+ break;
+ case DEBUG_BLOCK_DEVICE:
+ debug_training_device = level;
+ break;
+ case DEBUG_BLOCK_ACCESS:
+ debug_training_access = level;
+ break;
+ case DEBUG_STAGES_REG_DUMP:
+ if (level == DEBUG_LEVEL_TRACE)
+ is_reg_dump = 1;
+ else
+ is_reg_dump = 0;
+ break;
+ case DEBUG_BLOCK_ALL:
+ default:
+ debug_training_static = level;
+ debug_training = level;
+ debug_leveling = level;
+ debug_centralization = level;
+ debug_pbs = level;
+ debug_training_hw_alg = level;
+ debug_training_access = level;
+ debug_training_device = level;
+ }
+}
+#endif /* SILENT_LIB */
+
+#if defined(DDR_VIEWER_TOOL)
+static char *convert_freq(enum mv_ddr_freq freq);
+#if defined(EXCLUDE_SWITCH_DEBUG)
+u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
+u32 ctrl_adll1[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
+u32 ctrl_level_phase[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
+#endif /* EXCLUDE_SWITCH_DEBUG */
+#endif /* DDR_VIEWER_TOOL */
+
+struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM];
+u8 is_default_centralization = 0;
+u8 is_tune_result = 0;
+u8 is_validate_window_per_if = 0;
+u8 is_validate_window_per_pup = 0;
+u8 sweep_cnt = 1;
+u32 is_bist_reset_bit = 1;
+u8 is_run_leveling_sweep_tests;
+
+static struct hws_xsb_info xsb_info[MAX_DEVICE_NUM];
+
+/*
+ * Dump Dunit & Phy registers
+ */
+int ddr3_tip_reg_dump(u32 dev_num)
+{
+ u32 if_id, reg_addr, data_value, bus_id;
+ u32 read_data[MAX_INTERFACE_NUM];
+ 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();
+
+ printf("-- dunit registers --\n");
+ for (reg_addr = 0x1400; reg_addr < 0x19f0; reg_addr += 4) {
+ printf("0x%x ", reg_addr);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, reg_addr, read_data,
+ MASK_ALL_BITS));
+ printf("0x%x ", read_data[if_id]);
+ }
+ printf("\n");
+ }
+
+ printf("-- Phy registers --\n");
+ for (reg_addr = 0; reg_addr <= 0xff; reg_addr++) {
+ printf("0x%x ", reg_addr);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0;
+ bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA, reg_addr,
+ &data_value));
+ printf("0x%x ", data_value);
+ }
+ for (bus_id = 0;
+ bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_CONTROL, reg_addr,
+ &data_value));
+ printf("0x%x ", data_value);
+ }
+ }
+ printf("\n");
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Register access func registration
+ */
+int ddr3_tip_init_config_func(u32 dev_num,
+ struct hws_tip_config_func_db *config_func)
+{
+ if (config_func == NULL)
+ return MV_BAD_PARAM;
+
+ memcpy(&config_func_info[dev_num], config_func,
+ sizeof(struct hws_tip_config_func_db));
+
+ return MV_OK;
+}
+
+/*
+ * Get training result info pointer
+ */
+enum hws_result *ddr3_tip_get_result_ptr(u32 stage)
+{
+ return training_result[stage];
+}
+
+/*
+ * Device info read
+ */
+int ddr3_tip_get_device_info(u32 dev_num, struct ddr3_device_info *info_ptr)
+{
+ if (config_func_info[dev_num].tip_get_device_info_func != NULL) {
+ return config_func_info[dev_num].
+ tip_get_device_info_func((u8) dev_num, info_ptr);
+ }
+
+ return MV_FAIL;
+}
+
+#if defined(DDR_VIEWER_TOOL)
+/*
+ * Convert freq to character string
+ */
+static char *convert_freq(enum mv_ddr_freq freq)
+{
+ switch (freq) {
+ case MV_DDR_FREQ_LOW_FREQ:
+ return "MV_DDR_FREQ_LOW_FREQ";
+
+ case MV_DDR_FREQ_400:
+ return "400";
+
+ case MV_DDR_FREQ_533:
+ return "533";
+
+ case MV_DDR_FREQ_667:
+ return "667";
+
+ case MV_DDR_FREQ_800:
+ return "800";
+
+ case MV_DDR_FREQ_933:
+ return "933";
+
+ case MV_DDR_FREQ_1066:
+ return "1066";
+
+ case MV_DDR_FREQ_311:
+ return "311";
+
+ case MV_DDR_FREQ_333:
+ return "333";
+
+ case MV_DDR_FREQ_467:
+ return "467";
+
+ case MV_DDR_FREQ_850:
+ return "850";
+
+ case MV_DDR_FREQ_900:
+ return "900";
+
+ case MV_DDR_FREQ_360:
+ return "MV_DDR_FREQ_360";
+
+ case MV_DDR_FREQ_1000:
+ return "MV_DDR_FREQ_1000";
+
+ default:
+ return "Unknown Frequency";
+ }
+}
+
+/*
+ * Convert device ID to character string
+ */
+static char *convert_dev_id(u32 dev_id)
+{
+ switch (dev_id) {
+ case 0x6800:
+ return "A38xx";
+ case 0x6900:
+ return "A39XX";
+ case 0xf400:
+ return "AC3";
+ case 0xfc00:
+ return "BC2";
+
+ default:
+ return "Unknown Device";
+ }
+}
+
+/*
+ * Convert device ID to character string
+ */
+static char *convert_mem_size(u32 dev_id)
+{
+ switch (dev_id) {
+ case 0:
+ return "512 MB";
+ case 1:
+ return "1 GB";
+ case 2:
+ return "2 GB";
+ case 3:
+ return "4 GB";
+ case 4:
+ return "8 GB";
+
+ default:
+ return "wrong mem size";
+ }
+}
+
+int print_device_info(u8 dev_num)
+{
+ struct ddr3_device_info info_ptr;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ CHECK_STATUS(ddr3_tip_get_device_info(dev_num, &info_ptr));
+ printf("=== DDR setup START===\n");
+ printf("\tDevice ID: %s\n", convert_dev_id(info_ptr.device_id));
+ printf("\tDDR3 CK delay: %d\n", info_ptr.ck_delay);
+ print_topology(tm);
+ printf("=== DDR setup END===\n");
+
+ return MV_OK;
+}
+
+void hws_ddr3_tip_sweep_test(int enable)
+{
+ if (enable) {
+ is_validate_window_per_if = 1;
+ is_validate_window_per_pup = 1;
+ debug_training = DEBUG_LEVEL_TRACE;
+ } else {
+ is_validate_window_per_if = 0;
+ is_validate_window_per_pup = 0;
+ }
+}
+#endif /* DDR_VIEWER_TOOL */
+
+char *ddr3_tip_convert_tune_result(enum hws_result tune_result)
+{
+ switch (tune_result) {
+ case TEST_FAILED:
+ return "FAILED";
+ case TEST_SUCCESS:
+ return "PASS";
+ case NO_TEST_DONE:
+ return "NOT COMPLETED";
+ default:
+ return "Un-KNOWN";
+ }
+}
+
+/*
+ * Print log info
+ */
+int ddr3_tip_print_log(u32 dev_num, u32 mem_addr)
+{
+ u32 if_id = 0;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+#if defined(DDR_VIEWER_TOOL)
+ if ((is_validate_window_per_if != 0) ||
+ (is_validate_window_per_pup != 0)) {
+ u32 is_pup_log = 0;
+ enum mv_ddr_freq freq;
+
+ freq = tm->interface_params[first_active_if].memory_freq;
+
+ is_pup_log = (is_validate_window_per_pup != 0) ? 1 : 0;
+ printf("===VALIDATE WINDOW LOG START===\n");
+ printf("DDR Frequency: %s ======\n", convert_freq(freq));
+ /* print sweep windows */
+ ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 1, is_pup_log);
+ ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 0, is_pup_log);
+#if defined(EXCLUDE_SWITCH_DEBUG)
+ if (is_run_leveling_sweep_tests == 1) {
+ ddr3_tip_run_leveling_sweep_test(dev_num, sweep_cnt, 0, is_pup_log);
+ ddr3_tip_run_leveling_sweep_test(dev_num, sweep_cnt, 1, is_pup_log);
+ }
+#endif /* EXCLUDE_SWITCH_DEBUG */
+ ddr3_tip_print_all_pbs_result(dev_num);
+ ddr3_tip_print_wl_supp_result(dev_num);
+ printf("===VALIDATE WINDOW LOG END ===\n");
+ CHECK_STATUS(ddr3_tip_restore_dunit_regs(dev_num));
+ ddr3_tip_reg_dump(dev_num);
+ }
+#endif /* DDR_VIEWER_TOOL */
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("IF %d Status:\n", if_id));
+
+ if (mask_tune_func & INIT_CONTROLLER_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tInit Controller: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[INIT_CONTROLLER]
+ [if_id])));
+ }
+ if (mask_tune_func & SET_LOW_FREQ_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tLow freq Config: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[SET_LOW_FREQ]
+ [if_id])));
+ }
+ if (mask_tune_func & LOAD_PATTERN_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tLoad Pattern: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[LOAD_PATTERN]
+ [if_id])));
+ }
+ if (mask_tune_func & SET_MEDIUM_FREQ_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tMedium freq Config: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[SET_MEDIUM_FREQ]
+ [if_id])));
+ }
+ if (mask_tune_func & WRITE_LEVELING_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tWL: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[WRITE_LEVELING]
+ [if_id])));
+ }
+ if (mask_tune_func & LOAD_PATTERN_2_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tLoad Pattern: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[LOAD_PATTERN_2]
+ [if_id])));
+ }
+ if (mask_tune_func & READ_LEVELING_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tRL: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[READ_LEVELING]
+ [if_id])));
+ }
+ if (mask_tune_func & WRITE_LEVELING_SUPP_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tWL Supp: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[WRITE_LEVELING_SUPP]
+ [if_id])));
+ }
+ if (mask_tune_func & PBS_RX_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tPBS RX: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[PBS_RX]
+ [if_id])));
+ }
+ if (mask_tune_func & PBS_TX_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tPBS TX: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[PBS_TX]
+ [if_id])));
+ }
+ if (mask_tune_func & SET_TARGET_FREQ_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tTarget freq Config: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[SET_TARGET_FREQ]
+ [if_id])));
+ }
+ if (mask_tune_func & WRITE_LEVELING_TF_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tWL TF: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[WRITE_LEVELING_TF]
+ [if_id])));
+ }
+ if (mask_tune_func & READ_LEVELING_TF_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tRL TF: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[READ_LEVELING_TF]
+ [if_id])));
+ }
+ if (mask_tune_func & WRITE_LEVELING_SUPP_TF_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tWL TF Supp: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result
+ [WRITE_LEVELING_SUPP_TF]
+ [if_id])));
+ }
+ if (mask_tune_func & CENTRALIZATION_RX_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tCentr RX: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[CENTRALIZATION_RX]
+ [if_id])));
+ }
+ if (mask_tune_func & VREF_CALIBRATION_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tVREF_CALIBRATION: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[VREF_CALIBRATION]
+ [if_id])));
+ }
+ if (mask_tune_func & CENTRALIZATION_TX_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tCentr TX: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[CENTRALIZATION_TX]
+ [if_id])));
+ }
+ }
+
+ return MV_OK;
+}
+
+#if !defined(EXCLUDE_DEBUG_PRINTS)
+/*
+ * Print stability log info
+ */
+int ddr3_tip_print_stability_log(u32 dev_num)
+{
+ u8 if_id = 0, csindex = 0, bus_id = 0, idx = 0;
+ u32 reg_data;
+ u32 read_data[MAX_INTERFACE_NUM];
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /* Title print */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ printf("Title: I/F# , Tj, Calibration_n0, Calibration_p0, Calibration_n1, Calibration_p1, Calibration_n2, Calibration_p2,");
+ for (csindex = 0; csindex < max_cs; csindex++) {
+ printf("CS%d , ", csindex);
+ printf("\n");
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ printf("VWTx, VWRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, Cen_tx, Cen_rx, Vref, DQVref,");
+ printf("\t\t");
+ for (idx = 0; idx < 11; idx++)
+ printf("PBSTx-Pad%d,", idx);
+ printf("\t\t");
+ for (idx = 0; idx < 11; idx++)
+ printf("PBSRx-Pad%d,", idx);
+ }
+ }
+ printf("\n");
+
+ /* Data print */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ printf("Data: %d,%d,", if_id,
+ (config_func_info[dev_num].tip_get_temperature != NULL)
+ ? (config_func_info[dev_num].
+ tip_get_temperature(dev_num)) : (0));
+
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x14c8,
+ read_data, MASK_ALL_BITS));
+ printf("%d,%d,", ((read_data[if_id] & 0x3f0) >> 4),
+ ((read_data[if_id] & 0xfc00) >> 10));
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x17c8,
+ read_data, MASK_ALL_BITS));
+ printf("%d,%d,", ((read_data[if_id] & 0x3f0) >> 4),
+ ((read_data[if_id] & 0xfc00) >> 10));
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1dc8,
+ read_data, MASK_ALL_BITS));
+ printf("%d,%d,", ((read_data[if_id] & 0x3f0000) >> 16),
+ ((read_data[if_id] & 0xfc00000) >> 22));
+
+ for (csindex = 0; csindex < max_cs; csindex++) {
+ printf("CS%d , ", csindex);
+ for (bus_id = 0; bus_id < MAX_BUS_NUM; bus_id++) {
+ printf("\n");
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ RESULT_PHY_REG +
+ csindex, &reg_data);
+ printf("%d,%d,", (reg_data & 0x1f),
+ ((reg_data & 0x3e0) >> 5));
+ /* WL */
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ WL_PHY_REG(csindex),
+ &reg_data);
+ printf("%d,%d,%d,",
+ (reg_data & 0x1f) +
+ ((reg_data & 0x1c0) >> 6) * 32,
+ (reg_data & 0x1f),
+ (reg_data & 0x1c0) >> 6);
+ /* RL */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id,
+ RD_DATA_SMPL_DLYS_REG,
+ read_data, MASK_ALL_BITS));
+ read_data[if_id] =
+ (read_data[if_id] &
+ (0x1f << (8 * csindex))) >>
+ (8 * csindex);
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA,
+ RL_PHY_REG(csindex),
+ &reg_data);
+ printf("%d,%d,%d,%d,",
+ (reg_data & 0x1f) +
+ ((reg_data & 0x1c0) >> 6) * 32 +
+ read_data[if_id] * 64,
+ (reg_data & 0x1f),
+ ((reg_data & 0x1c0) >> 6),
+ read_data[if_id]);
+ /* Centralization */
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA,
+ CTX_PHY_REG(csindex),
+ &reg_data);
+ printf("%d,", (reg_data & 0x3f));
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA,
+ CRX_PHY_REG(csindex),
+ &reg_data);
+ printf("%d,", (reg_data & 0x1f));
+ /* Vref */
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA,
+ PAD_CFG_PHY_REG,
+ &reg_data);
+ printf("%d,", (reg_data & 0x7));
+ /* DQVref */
+ /* Need to add the Read Function from device */
+ printf("%d,", 0);
+ printf("\t\t");
+ for (idx = 0; idx < 11; idx++) {
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ 0x10 +
+ 16 * csindex +
+ idx, &reg_data);
+ printf("%d,", (reg_data & 0x3f));
+ }
+ printf("\t\t");
+ for (idx = 0; idx < 11; idx++) {
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ 0x50 +
+ 16 * csindex +
+ idx, &reg_data);
+ printf("%d,", (reg_data & 0x3f));
+ }
+ }
+ }
+ }
+ printf("\n");
+
+ return MV_OK;
+}
+#endif /* EXCLUDE_DEBUG_PRINTS */
+
+/*
+ * Register XSB information
+ */
+int ddr3_tip_register_xsb_info(u32 dev_num, struct hws_xsb_info *xsb_info_table)
+{
+ memcpy(&xsb_info[dev_num], xsb_info_table, sizeof(struct hws_xsb_info));
+ return MV_OK;
+}
+
+/*
+ * Read ADLL Value
+ */
+int ddr3_tip_read_adll_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
+ u32 reg_addr, u32 mask)
+{
+ u32 data_value;
+ u32 if_id = 0, bus_id = 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();
+
+ /*
+ * multi CS support - reg_addr is calucalated in calling function
+ * with CS offset
+ */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0; bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id,
+ DDR_PHY_DATA, reg_addr,
+ &data_value));
+ pup_values[if_id *
+ octets_per_if_num + bus_id] =
+ data_value & mask;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Write ADLL Value
+ */
+int ddr3_tip_write_adll_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
+ u32 reg_addr)
+{
+ u32 if_id = 0, bus_id = 0;
+ u32 data;
+ 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();
+
+ /*
+ * multi CS support - reg_addr is calucalated in calling function
+ * with CS offset
+ */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0; bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ data = pup_values[if_id *
+ octets_per_if_num +
+ bus_id];
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ reg_addr, data));
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Read Phase Value
+ */
+int read_phase_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
+ int reg_addr, u32 mask)
+{
+ u32 data_value;
+ u32 if_id = 0, bus_id = 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();
+
+ /* multi CS support - reg_addr is calucalated in calling function with CS offset */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id,
+ DDR_PHY_DATA, reg_addr,
+ &data_value));
+ pup_values[if_id * octets_per_if_num + bus_id] = data_value & mask;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Write Leveling Value
+ */
+int write_leveling_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
+ u32 pup_ph_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], int reg_addr)
+{
+ u32 if_id = 0, bus_id = 0;
+ u32 data;
+ 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();
+
+ /* multi CS support - reg_addr is calucalated in calling function with CS offset */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0 ; bus_id < octets_per_if_num ; bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ data = pup_values[if_id * octets_per_if_num + bus_id] +
+ pup_ph_values[if_id * octets_per_if_num + bus_id];
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id,
+ DDR_PHY_DATA,
+ reg_addr,
+ data));
+ }
+ }
+
+ return 0;
+}
+
+#if !defined(EXCLUDE_SWITCH_DEBUG)
+struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM];
+u32 start_xsb_offset = 0;
+u8 is_rl_old = 0;
+u8 is_freq_old = 0;
+u8 is_dfs_disabled = 0;
+u32 default_centrlization_value = 0x12;
+u32 activate_select_before_run_alg = 1, activate_deselect_after_run_alg = 1,
+ rl_test = 0, reset_read_fifo = 0;
+int debug_acc = 0;
+u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
+
+u32 xsb_test_table[][8] = {
+ {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555,
+ 0x66666666, 0x77777777},
+ {0x88888888, 0x99999999, 0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc, 0xdddddddd,
+ 0xeeeeeeee, 0xffffffff},
+ {0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff},
+ {0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff},
+ {0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff},
+ {0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff},
+ {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff},
+ {0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000},
+ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff}
+};
+
+int ddr3_tip_print_adll(void)
+{
+ u32 bus_cnt = 0, if_id, data_p1, data_p2, ui_data3, dev_num = 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();
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ 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);
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_cnt,
+ DDR_PHY_DATA, 0x1, &data_p1));
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST,
+ bus_cnt, DDR_PHY_DATA, 0x2, &data_p2));
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST,
+ bus_cnt, DDR_PHY_DATA, 0x3, &ui_data3));
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ (" IF %d bus_cnt %d phy_reg_1_data 0x%x phy_reg_2_data 0x%x phy_reg_3_data 0x%x\n",
+ if_id, bus_cnt, data_p1, data_p2,
+ ui_data3));
+ }
+ }
+
+ return MV_OK;
+}
+
+#endif /* EXCLUDE_SWITCH_DEBUG */
+
+#if defined(DDR_VIEWER_TOOL)
+/*
+ * Print ADLL
+ */
+int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM])
+{
+ u32 i, j;
+ 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 (j = 0; j < octets_per_if_num; j++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, j);
+ for (i = 0; i < MAX_INTERFACE_NUM; i++)
+ printf("%d ,", adll[i * octets_per_if_num + j]);
+ }
+ printf("\n");
+
+ return MV_OK;
+}
+
+int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM])
+{
+ u32 i, j;
+ 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 (j = 0; j < octets_per_if_num; j++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, j);
+ for (i = 0; i < MAX_INTERFACE_NUM; i++)
+ printf("%d ,", adll[i * octets_per_if_num + j] >> 6);
+ }
+ printf("\n");
+
+ return MV_OK;
+}
+#endif /* DDR_VIEWER_TOOL */
+
+#if !defined(EXCLUDE_SWITCH_DEBUG)
+/* byte_index - only byte 0, 1, 2, or 3, oxff - test all bytes */
+static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst,
+ u32 byte_index)
+{
+ u32 burst_cnt = 0, addr_offset, i_id;
+ int b_is_fail = 0;
+
+ addr_offset =
+ (byte_index ==
+ 0xff) ? (u32) 0xffffffff : (u32) (0xff << (byte_index * 8));
+ for (burst_cnt = 0; burst_cnt < EXT_ACCESS_BURST_LENGTH; burst_cnt++) {
+ if ((p_src[burst_cnt] & addr_offset) !=
+ (p_dst[if_id] & addr_offset))
+ b_is_fail = 1;
+ }
+
+ if (b_is_fail == 1) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("IF %d exp: ", if_id));
+ for (i_id = 0; i_id <= MAX_INTERFACE_NUM - 1; i_id++) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("0x%8x ", p_src[i_id]));
+ }
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("\n_i_f %d rcv: ", if_id));
+ for (i_id = 0; i_id <= MAX_INTERFACE_NUM - 1; i_id++) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("(0x%8x ", p_dst[i_id]));
+ }
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("\n "));
+ }
+
+ return b_is_fail;
+}
+#endif /* EXCLUDE_SWITCH_DEBUG */
+
+#if defined(DDR_VIEWER_TOOL)
+/*
+ * Sweep validation
+ */
+int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction,
+ u32 mode)
+{
+ u32 pup = 0, start_pup = 0, end_pup = 0;
+ u32 adll = 0, rep = 0, pattern_idx = 0;
+ u32 res[MAX_INTERFACE_NUM] = { 0 };
+ int if_id = 0;
+ u32 adll_value = 0;
+ u32 reg;
+ enum hws_access_type pup_access;
+ u32 cs;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ 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();
+
+ repeat_num = 2;
+
+ if (mode == 1) {
+ /* per pup */
+ start_pup = 0;
+ end_pup = octets_per_if_num - 1;
+ pup_access = ACCESS_TYPE_UNICAST;
+ } else {
+ start_pup = 0;
+ end_pup = 0;
+ pup_access = ACCESS_TYPE_MULTICAST;
+ }
+
+ for (cs = 0; cs < max_cs; cs++) {
+ reg = (direction == 0) ? CTX_PHY_REG(cs) : CRX_PHY_REG(cs);
+ for (adll = 0; adll < ADLL_LENGTH; adll++) {
+ for (if_id = 0;
+ if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE
+ (tm->if_act_mask,
+ if_id);
+ for (pup = start_pup; pup <= end_pup; pup++) {
+ ctrl_sweepres[adll][if_id][pup] =
+ 0;
+ }
+ }
+ }
+
+ for (adll = 0; adll < (MAX_INTERFACE_NUM * MAX_BUS_NUM); adll++)
+ ctrl_adll[adll] = 0;
+ /* Save DQS value(after algorithm run) */
+ ddr3_tip_read_adll_value(dev_num, ctrl_adll,
+ reg, MASK_ALL_BITS);
+
+ /*
+ * Sweep ADLL from 0:31 on all I/F on all Pup and perform
+ * BIST on each stage.
+ */
+ for (pup = start_pup; pup <= end_pup; pup++) {
+ for (adll = 0; adll < ADLL_LENGTH; adll++) {
+ for (rep = 0; rep < repeat_num; rep++) {
+ for (pattern_idx = PATTERN_KILLER_DQ0;
+ pattern_idx < PATTERN_LAST;
+ pattern_idx++) {
+ adll_value =
+ (direction == 0) ? (adll * 2) : adll;
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, 0,
+ pup_access, pup, DDR_PHY_DATA,
+ reg, adll_value));
+ hws_ddr3_run_bist(dev_num, sweep_pattern, res,
+ cs);
+ /* ddr3_tip_reset_fifo_ptr(dev_num); */
+ for (if_id = 0;
+ if_id < MAX_INTERFACE_NUM;
+ if_id++) {
+ VALIDATE_IF_ACTIVE
+ (tm->if_act_mask,
+ if_id);
+ ctrl_sweepres[adll][if_id][pup]
+ += res[if_id];
+ if (mode == 1) {
+ CHECK_STATUS
+ (ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ pup,
+ DDR_PHY_DATA,
+ reg,
+ ctrl_adll[if_id *
+ cs *
+ octets_per_if_num
+ + pup]));
+ }
+ }
+ }
+ }
+ }
+ }
+ printf("Final, CS %d,%s, Sweep, Result, Adll,", cs,
+ ((direction == 0) ? "TX" : "RX"));
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (mode == 1) {
+ for (pup = start_pup; pup <= end_pup; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ printf("I/F%d-PHY%d , ", if_id, pup);
+ }
+ } else {
+ printf("I/F%d , ", if_id);
+ }
+ }
+ printf("\n");
+
+ for (adll = 0; adll < ADLL_LENGTH; adll++) {
+ adll_value = (direction == 0) ? (adll * 2) : adll;
+ printf("Final,%s, Sweep, Result, %d ,",
+ ((direction == 0) ? "TX" : "RX"), adll_value);
+
+ for (if_id = 0;
+ if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = start_pup; pup <= end_pup; pup++) {
+ printf("%8d , ",
+ ctrl_sweepres[adll][if_id]
+ [pup]);
+ }
+ }
+ printf("\n");
+ }
+
+ /*
+ * Write back to the phy the Rx DQS value, we store in
+ * the beginning.
+ */
+ ddr3_tip_write_adll_value(dev_num, ctrl_adll, reg);
+ /* print adll results */
+ ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, MASK_ALL_BITS);
+ printf("%s, DQS, ADLL,,,", (direction == 0) ? "Tx" : "Rx");
+ print_adll(dev_num, ctrl_adll);
+ }
+ ddr3_tip_reset_fifo_ptr(dev_num);
+
+ return 0;
+}
+
+#if defined(EXCLUDE_SWITCH_DEBUG)
+int ddr3_tip_run_leveling_sweep_test(int dev_num, u32 repeat_num,
+ u32 direction, u32 mode)
+{
+ u32 pup = 0, start_pup = 0, end_pup = 0, start_adll = 0;
+ u32 adll = 0, rep = 0, pattern_idx = 0;
+ u32 read_data[MAX_INTERFACE_NUM];
+ u32 res[MAX_INTERFACE_NUM] = { 0 };
+ int if_id = 0, gap = 0;
+ u32 adll_value = 0;
+ u32 reg;
+ enum hws_access_type pup_access;
+ u32 cs;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ 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 (mode == 1) { /* per pup */
+ start_pup = 0;
+ end_pup = octets_per_if_num - 1;
+ pup_access = ACCESS_TYPE_UNICAST;
+ } else {
+ start_pup = 0;
+ end_pup = 0;
+ pup_access = ACCESS_TYPE_MULTICAST;
+ }
+
+ for (cs = 0; cs < max_cs; cs++) {
+ reg = (direction == 0) ? WL_PHY_REG(cs) : RL_PHY_REG(cs);
+ for (adll = 0; adll < ADLL_LENGTH; adll++) {
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = start_pup; pup <= end_pup; pup++)
+ ctrl_sweepres[adll][if_id][pup] = 0;
+ }
+ }
+
+ for (adll = 0; adll < MAX_INTERFACE_NUM * MAX_BUS_NUM; adll++) {
+ ctrl_adll[adll] = 0;
+ ctrl_level_phase[adll] = 0;
+ ctrl_adll1[adll] = 0;
+ }
+
+ /* save leveling value after running algorithm */
+ ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, 0x1f);
+ read_phase_value(dev_num, ctrl_level_phase, reg, 0x7 << 6);
+
+ if (direction == 0)
+ ddr3_tip_read_adll_value(dev_num, ctrl_adll1,
+ CTX_PHY_REG(cs), MASK_ALL_BITS);
+
+ /* Sweep ADLL from 0 to 31 on all interfaces, all pups,
+ * and perform BIST on each stage
+ */
+ for (pup = start_pup; pup <= end_pup; pup++) {
+ for (adll = 0; adll < ADLL_LENGTH; adll++) {
+ for (rep = 0; rep < repeat_num; rep++) {
+ adll_value = (direction == 0) ? (adll * 2) : (adll * 3);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ start_adll = ctrl_adll[if_id * cs * octets_per_if_num + pup] +
+ (ctrl_level_phase[if_id * cs *
+ octets_per_if_num +
+ pup] >> 6) * 32;
+
+ if (direction == 0)
+ start_adll = (start_adll > 32) ? (start_adll - 32) : 0;
+ else
+ start_adll = (start_adll > 48) ? (start_adll - 48) : 0;
+
+ adll_value += start_adll;
+
+ gap = ctrl_adll1[if_id * cs * octets_per_if_num + pup] -
+ ctrl_adll[if_id * cs * octets_per_if_num + pup];
+ gap = (((adll_value % 32) + gap) % 64);
+
+ adll_value = ((adll_value % 32) +
+ (((adll_value - (adll_value % 32)) / 32) << 6));
+
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ pup_access,
+ pup,
+ DDR_PHY_DATA,
+ reg,
+ adll_value));
+ if (direction == 0)
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ pup_access,
+ pup,
+ DDR_PHY_DATA,
+ CTX_PHY_REG(cs),
+ gap));
+ }
+
+ for (pattern_idx = PATTERN_KILLER_DQ0;
+ pattern_idx < PATTERN_LAST;
+ pattern_idx++) {
+ hws_ddr3_run_bist(dev_num, sweep_pattern, res, cs);
+ ddr3_tip_reset_fifo_ptr(dev_num);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (pup != 4) { /* TODO: remove literal */
+ ctrl_sweepres[adll][if_id][pup] += res[if_id];
+ } else {
+ CHECK_STATUS(ddr3_tip_if_read(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ 0x1458,
+ read_data,
+ MASK_ALL_BITS));
+ ctrl_sweepres[adll][if_id][pup] += read_data[if_id];
+ CHECK_STATUS(ddr3_tip_if_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ 0x1458,
+ 0x0,
+ 0xFFFFFFFF));
+ CHECK_STATUS(ddr3_tip_if_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ 0x145C,
+ 0x0,
+ 0xFFFFFFFF));
+ }
+ }
+ }
+ }
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ start_adll = ctrl_adll[if_id * cs * octets_per_if_num + pup] +
+ ctrl_level_phase[if_id * cs * octets_per_if_num + pup];
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, pup_access, pup,
+ DDR_PHY_DATA, reg, start_adll));
+ if (direction == 0)
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ pup_access,
+ pup,
+ DDR_PHY_DATA,
+ CTX_PHY_REG(cs),
+ ctrl_adll1[if_id *
+ cs *
+ octets_per_if_num +
+ pup]));
+ }
+ }
+
+ printf("Final,CS %d,%s,Leveling,Result,Adll,", cs, ((direction == 0) ? "TX" : "RX"));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (mode == 1) {
+ for (pup = start_pup; pup <= end_pup; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ printf("I/F%d-PHY%d , ", if_id, pup);
+ }
+ } else {
+ printf("I/F%d , ", if_id);
+ }
+ }
+ printf("\n");
+
+ for (adll = 0; adll < ADLL_LENGTH; adll++) {
+ adll_value = (direction == 0) ? ((adll * 2) - 32) : ((adll * 3) - 48);
+ printf("Final,%s,LevelingSweep,Result, %d ,", ((direction == 0) ? "TX" : "RX"), adll_value);
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = start_pup; pup <= end_pup; pup++)
+ printf("%8d , ", ctrl_sweepres[adll][if_id][pup]);
+ }
+ printf("\n");
+ }
+
+ /* write back to the phy the Rx DQS value, we store in the beginning */
+ write_leveling_value(dev_num, ctrl_adll, ctrl_level_phase, reg);
+ if (direction == 0)
+ ddr3_tip_write_adll_value(dev_num, ctrl_adll1, CTX_PHY_REG(cs));
+
+ /* print adll results */
+ ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, MASK_ALL_BITS);
+ printf("%s,DQS,Leveling,,,", (direction == 0) ? "Tx" : "Rx");
+ print_adll(dev_num, ctrl_adll);
+ print_ph(dev_num, ctrl_level_phase);
+ }
+ ddr3_tip_reset_fifo_ptr(dev_num);
+
+ return 0;
+}
+#endif /* EXCLUDE_SWITCH_DEBUG */
+
+void print_topology(struct mv_ddr_topology_map *topology_db)
+{
+ u32 ui, uj;
+ u32 dev_num = 0;
+
+ printf("\tinterface_mask: 0x%x\n", topology_db->if_act_mask);
+ printf("\tNumber of buses: 0x%x\n",
+ ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE));
+ printf("\tbus_act_mask: 0x%x\n", topology_db->bus_act_mask);
+
+ for (ui = 0; ui < MAX_INTERFACE_NUM; ui++) {
+ VALIDATE_IF_ACTIVE(topology_db->if_act_mask, ui);
+ printf("\n\tInterface ID: %d\n", ui);
+ printf("\t\tDDR Frequency: %s\n",
+ convert_freq(topology_db->
+ interface_params[ui].memory_freq));
+ printf("\t\tSpeed_bin: %d\n",
+ topology_db->interface_params[ui].speed_bin_index);
+ printf("\t\tBus_width: %d\n",
+ (4 << topology_db->interface_params[ui].bus_width));
+ printf("\t\tMem_size: %s\n",
+ convert_mem_size(topology_db->
+ interface_params[ui].memory_size));
+ printf("\t\tCAS-WL: %d\n",
+ topology_db->interface_params[ui].cas_wl);
+ printf("\t\tCAS-L: %d\n",
+ topology_db->interface_params[ui].cas_l);
+ printf("\t\tTemperature: %d\n",
+ topology_db->interface_params[ui].interface_temp);
+ printf("\n");
+ for (uj = 0; uj < 4; uj++) {
+ printf("\t\tBus %d parameters- CS Mask: 0x%x\t", uj,
+ topology_db->interface_params[ui].
+ as_bus_params[uj].cs_bitmask);
+ printf("Mirror: 0x%x\t",
+ topology_db->interface_params[ui].
+ as_bus_params[uj].mirror_enable_bitmask);
+ printf("DQS Swap is %s \t",
+ (topology_db->
+ interface_params[ui].as_bus_params[uj].
+ is_dqs_swap == 1) ? "enabled" : "disabled");
+ printf("Ck Swap:%s\t",
+ (topology_db->
+ interface_params[ui].as_bus_params[uj].
+ is_ck_swap == 1) ? "enabled" : "disabled");
+ printf("\n");
+ }
+ }
+}
+#endif /* DDR_VIEWER_TOOL */
+
+#if !defined(EXCLUDE_SWITCH_DEBUG)
+/*
+ * Execute XSB Test transaction (rd/wr/both)
+ */
+int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type,
+ u32 read_type, u32 burst_length)
+{
+ u32 seq = 0, if_id = 0, addr, cnt;
+ int ret = MV_OK, ret_tmp;
+ u32 data_read[MAX_INTERFACE_NUM];
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ addr = mem_addr;
+ for (cnt = 0; cnt <= burst_length; cnt++) {
+ seq = (seq + 1) % 8;
+ if (write_type != 0) {
+ CHECK_STATUS(ddr3_tip_ext_write
+ (dev_num, if_id, addr, 1,
+ xsb_test_table[seq]));
+ }
+ if (read_type != 0) {
+ CHECK_STATUS(ddr3_tip_ext_read
+ (dev_num, if_id, addr, 1,
+ data_read));
+ }
+ if ((read_type != 0) && (write_type != 0)) {
+ ret_tmp =
+ ddr3_tip_compare(if_id,
+ xsb_test_table[seq],
+ data_read,
+ 0xff);
+ addr += (EXT_ACCESS_BURST_LENGTH * 4);
+ ret = (ret != MV_OK) ? ret : ret_tmp;
+ }
+ }
+ }
+
+ return ret;
+}
+
+#else /*EXCLUDE_SWITCH_DEBUG */
+u32 start_xsb_offset = 0;
+
+int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type,
+ u32 read_type, u32 burst_length)
+{
+ return MV_OK;
+}
+
+#endif /* EXCLUDE_SWITCH_DEBUG */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.c
new file mode 100644
index 000000000..f878b4512
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_common.h"
+
+static char *ddr_type = "DDR3";
+
+/*
+ * generic_init_controller controls D-unit configuration:
+ * '1' - dynamic D-unit configuration,
+ */
+u8 generic_init_controller = 1;
+
+static int mv_ddr_training_params_set(u8 dev_num);
+
+/*
+ * Name: ddr3_init - Main DDR3 Init function
+ * Desc: This routine initialize the DDR3 MC and runs HW training.
+ * Args: None.
+ * Notes:
+ * Returns: None.
+ */
+int ddr3_init(void)
+{
+ int status;
+ int is_manual_cal_done;
+
+ /* Print mv_ddr version */
+ mv_ddr_ver_print();
+
+ mv_ddr_pre_training_fixup();
+
+ /* SoC/Board special initializations */
+ mv_ddr_pre_training_soc_config(ddr_type);
+
+ /* Set log level for training library */
+ mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL);
+
+ mv_ddr_early_init();
+
+ if (mv_ddr_topology_map_update()) {
+ printf("mv_ddr: failed to update topology\n");
+ return MV_FAIL;
+ }
+
+ if (mv_ddr_early_init2() != MV_OK)
+ return MV_FAIL;
+
+ /* Set training algorithm's parameters */
+ status = mv_ddr_training_params_set(0);
+ if (MV_OK != status)
+ return status;
+
+ mv_ddr_mc_config();
+
+ is_manual_cal_done = mv_ddr_manual_cal_do();
+
+ mv_ddr_mc_init();
+
+ if (!is_manual_cal_done) {
+ }
+
+
+ status = ddr3_silicon_post_init();
+ if (MV_OK != status) {
+ printf("DDR3 Post Init - FAILED 0x%x\n", status);
+ return status;
+ }
+
+ /* PHY initialization (Training) */
+ status = hws_ddr3_tip_run_alg(0, ALGO_TYPE_DYNAMIC);
+ if (MV_OK != status) {
+ printf("%s Training Sequence - FAILED\n", ddr_type);
+ return status;
+ }
+
+
+ /* Post MC/PHY initializations */
+ mv_ddr_post_training_soc_config(ddr_type);
+
+ mv_ddr_post_training_fixup();
+
+ if (mv_ddr_is_ecc_ena())
+ mv_ddr_mem_scrubbing();
+
+ printf("mv_ddr: completed successfully\n");
+
+ return MV_OK;
+}
+
+/*
+ * Name: mv_ddr_training_params_set
+ * Desc:
+ * Args:
+ * Notes: sets internal training params
+ * Returns:
+ */
+static int mv_ddr_training_params_set(u8 dev_num)
+{
+ struct tune_train_params params;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ int status;
+ u32 cs_num;
+ int ck_delay;
+
+ cs_num = mv_ddr_cs_num_get();
+ ck_delay = mv_ddr_ck_delay_get();
+
+ /* NOTE: do not remove any field initilization */
+ params.ck_delay = TUNE_TRAINING_PARAMS_CK_DELAY;
+ params.phy_reg3_val = TUNE_TRAINING_PARAMS_PHYREG3VAL;
+ params.g_zpri_data = TUNE_TRAINING_PARAMS_PRI_DATA;
+ params.g_znri_data = TUNE_TRAINING_PARAMS_NRI_DATA;
+ params.g_zpri_ctrl = TUNE_TRAINING_PARAMS_PRI_CTRL;
+ params.g_znri_ctrl = TUNE_TRAINING_PARAMS_NRI_CTRL;
+ params.g_znodt_data = TUNE_TRAINING_PARAMS_N_ODT_DATA;
+ params.g_zpodt_ctrl = TUNE_TRAINING_PARAMS_P_ODT_CTRL;
+ params.g_znodt_ctrl = TUNE_TRAINING_PARAMS_N_ODT_CTRL;
+
+ params.g_zpodt_data = TUNE_TRAINING_PARAMS_P_ODT_DATA;
+ params.g_dic = TUNE_TRAINING_PARAMS_DIC;
+ params.g_rtt_nom = TUNE_TRAINING_PARAMS_RTT_NOM;
+ if (cs_num == 1) {
+ params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_1CS;
+ params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS;
+ } else {
+ params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_2CS;
+ params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS;
+ }
+
+ if (ck_delay > 0)
+ params.ck_delay = ck_delay;
+
+ /* Use platform specific override ODT value */
+ if (tm->odt_config)
+ params.g_odt_config = tm->odt_config;
+
+ status = ddr3_tip_tune_training_params(dev_num, &params);
+ if (MV_OK != status) {
+ printf("%s Training Sequence - FAILED\n", ddr_type);
+ return status;
+ }
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.h
new file mode 100644
index 000000000..055516b67
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_INIT_H
+#define _DDR3_INIT_H
+
+#include "ddr_ml_wrapper.h"
+#include "mv_ddr_plat.h"
+
+#include "seq_exec.h"
+#include "ddr3_logging_def.h"
+#include "ddr3_training_hw_algo.h"
+#include "ddr3_training_ip.h"
+#include "ddr3_training_ip_centralization.h"
+#include "ddr3_training_ip_engine.h"
+#include "ddr3_training_ip_flow.h"
+#include "ddr3_training_ip_pbs.h"
+#include "ddr3_training_ip_prv_if.h"
+#include "ddr3_training_leveling.h"
+#include "xor.h"
+
+/* For checking function return values */
+#define CHECK_STATUS(orig_func) \
+ { \
+ int status; \
+ status = orig_func; \
+ if (MV_OK != status) \
+ return status; \
+ }
+
+#define SUB_VERSION 0
+
+enum log_level {
+ MV_LOG_LEVEL_0,
+ MV_LOG_LEVEL_1,
+ MV_LOG_LEVEL_2,
+ MV_LOG_LEVEL_3
+};
+
+/* TODO: consider to move to misl phy driver */
+#define MISL_PHY_DRV_P_OFFS 0x7
+#define MISL_PHY_DRV_N_OFFS 0x0
+#define MISL_PHY_ODT_P_OFFS 0x6
+#define MISL_PHY_ODT_N_OFFS 0x0
+
+/* Globals */
+extern u8 debug_training, debug_calibration, debug_ddr4_centralization,
+ debug_tap_tuning, debug_dm_tuning;
+extern u8 is_reg_dump;
+extern u8 generic_init_controller;
+/* list of allowed frequency listed in order of enum mv_ddr_freq */
+extern u32 is_pll_old;
+extern struct pattern_info pattern_table[];
+extern u8 debug_centralization, debug_training_ip, debug_training_bist,
+ debug_pbs, debug_training_static, debug_leveling;
+extern struct hws_tip_config_func_db config_func_info[];
+extern u8 twr_mask_table[];
+extern u8 cl_mask_table[];
+extern u8 cwl_mask_table[];
+extern u32 speed_bin_table_t_rc[];
+extern u32 speed_bin_table_t_rcd_t_rp[];
+
+extern u32 vref_init_val;
+extern u32 g_zpri_data;
+extern u32 g_znri_data;
+extern u32 g_zpri_ctrl;
+extern u32 g_znri_ctrl;
+extern u32 g_zpodt_data;
+extern u32 g_znodt_data;
+extern u32 g_zpodt_ctrl;
+extern u32 g_znodt_ctrl;
+extern u32 g_dic;
+extern u32 g_odt_config;
+extern u32 g_rtt_nom;
+extern u32 g_rtt_wr;
+extern u32 g_rtt_park;
+
+extern u8 debug_training_access;
+extern u32 first_active_if;
+extern u32 delay_enable, ck_delay, ca_delay;
+extern u32 mask_tune_func;
+extern u32 rl_version;
+extern int rl_mid_freq_wa;
+extern u8 calibration_update_control; /* 2 external only, 1 is internal only */
+extern enum mv_ddr_freq medium_freq;
+
+extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM];
+extern enum mv_ddr_freq low_freq;
+extern enum auto_tune_stage training_stage;
+extern u32 is_pll_before_init;
+extern u32 is_adll_calib_before_init;
+extern u32 is_dfs_in_init;
+extern int wl_debug_delay;
+extern u32 silicon_delay[MAX_DEVICE_NUM];
+extern u32 start_pattern, end_pattern;
+extern u32 phy_reg0_val;
+extern u32 phy_reg1_val;
+extern u32 phy_reg2_val;
+extern u32 phy_reg3_val;
+extern enum hws_pattern sweep_pattern;
+extern enum hws_pattern pbs_pattern;
+extern u32 g_znri_data;
+extern u32 g_zpri_data;
+extern u32 g_znri_ctrl;
+extern u32 g_zpri_ctrl;
+extern u32 finger_test, p_finger_start, p_finger_end, n_finger_start,
+ n_finger_end, p_finger_step, n_finger_step;
+extern u32 mode_2t;
+extern u32 xsb_validate_type;
+extern u32 xsb_validation_base_address;
+extern u32 odt_additional;
+extern u32 debug_mode;
+extern u32 debug_dunit;
+extern u32 clamp_tbl[];
+extern u32 freq_mask[MAX_DEVICE_NUM][MV_DDR_FREQ_LAST];
+
+extern u32 maxt_poll_tries;
+extern u32 is_bist_reset_bit;
+
+extern u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+extern u32 effective_cs;
+extern int ddr3_tip_centr_skip_min_win_check;
+extern u32 *dq_map_table;
+
+extern u8 debug_training_hw_alg;
+
+extern u32 start_xsb_offset;
+extern u32 odt_config;
+
+extern u16 mask_results_dq_reg_map[];
+
+extern u32 target_freq;
+extern u32 dfs_low_freq;
+
+extern u32 nominal_avs;
+extern u32 extension_avs;
+
+
+/* Prototypes */
+int ddr3_init(void);
+int ddr3_tip_enable_init_sequence(u32 dev_num);
+
+int ddr3_hws_hw_training(enum hws_algo_type algo_mode);
+int mv_ddr_early_init(void);
+int mv_ddr_early_init2(void);
+int ddr3_silicon_post_init(void);
+int ddr3_post_run_alg(void);
+void ddr3_new_tip_ecc_scrub(void);
+
+int ddr3_tip_reg_write(u32 dev_num, u32 reg_addr, u32 data);
+int ddr3_tip_reg_read(u32 dev_num, u32 reg_addr, u32 *data, u32 reg_mask);
+int ddr3_silicon_get_ddr_target_freq(u32 *ddr_freq);
+
+int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]);
+int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]);
+int read_phase_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
+ int reg_addr, u32 mask);
+int write_leveling_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
+ u32 pup_ph_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], int reg_addr);
+int ddr3_tip_restore_dunit_regs(u32 dev_num);
+void print_topology(struct mv_ddr_topology_map *tm);
+
+u32 mv_board_id_get(void);
+
+int ddr3_load_topology_map(void);
+void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level);
+void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block);
+int ddr3_tip_tune_training_params(u32 dev_num,
+ struct tune_train_params *params);
+void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps);
+void ddr3_fast_path_static_cs_size_config(u32 cs_ena);
+u32 mv_board_id_index_get(u32 board_id);
+void ddr3_set_log_level(u32 n_log_level);
+
+int hws_ddr3_cs_base_adr_calc(u32 if_id, u32 cs, u32 *cs_base_addr);
+
+int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode);
+int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode);
+void mv_ddr_mc_config(void);
+int mv_ddr_mc_init(void);
+void mv_ddr_set_calib_controller(void);
+/* TODO: consider to move to misl phy driver */
+unsigned int mv_ddr_misl_phy_drv_data_p_get(void);
+unsigned int mv_ddr_misl_phy_drv_data_n_get(void);
+unsigned int mv_ddr_misl_phy_drv_ctrl_p_get(void);
+unsigned int mv_ddr_misl_phy_drv_ctrl_n_get(void);
+unsigned int mv_ddr_misl_phy_odt_p_get(void);
+unsigned int mv_ddr_misl_phy_odt_n_get(void);
+
+#endif /* _DDR3_INIT_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_logging_def.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_logging_def.h
new file mode 100644
index 000000000..ad9da1cff
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_logging_def.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_LOGGING_CONFIG_H
+#define _DDR3_LOGGING_CONFIG_H
+
+#ifdef SILENT_LIB
+#define DEBUG_TRAINING_BIST_ENGINE(level, s)
+#define DEBUG_TRAINING_IP(level, s)
+#define DEBUG_CENTRALIZATION_ENGINE(level, s)
+#define DEBUG_TRAINING_HW_ALG(level, s)
+#define DEBUG_TRAINING_IP_ENGINE(level, s)
+#define DEBUG_LEVELING(level, s)
+#define DEBUG_PBS_ENGINE(level, s)
+#define DEBUG_TRAINING_STATIC_IP(level, s)
+#define DEBUG_TRAINING_ACCESS(level, s)
+#else
+#ifdef LIB_FUNCTIONAL_DEBUG_ONLY
+#define DEBUG_TRAINING_BIST_ENGINE(level, s)
+#define DEBUG_TRAINING_IP_ENGINE(level, s)
+#define DEBUG_TRAINING_IP(level, s) \
+ if (level >= debug_training) \
+ printf s
+#define DEBUG_CENTRALIZATION_ENGINE(level, s) \
+ if (level >= debug_centralization) \
+ printf s
+#define DEBUG_TRAINING_HW_ALG(level, s) \
+ if (level >= debug_training_hw_alg) \
+ printf s
+#define DEBUG_LEVELING(level, s) \
+ if (level >= debug_leveling) \
+ printf s
+#define DEBUG_PBS_ENGINE(level, s) \
+ if (level >= debug_pbs) \
+ printf s
+#define DEBUG_TRAINING_STATIC_IP(level, s) \
+ if (level >= debug_training_static) \
+ printf s
+#define DEBUG_TRAINING_ACCESS(level, s) \
+ if (level >= debug_training_access) \
+ printf s
+#else
+#define DEBUG_TRAINING_BIST_ENGINE(level, s) \
+ if (level >= debug_training_bist) \
+ printf s
+
+#define DEBUG_TRAINING_IP_ENGINE(level, s) \
+ if (level >= debug_training_ip) \
+ printf s
+#define DEBUG_TRAINING_IP(level, s) \
+ if (level >= debug_training) \
+ printf s
+#define DEBUG_CENTRALIZATION_ENGINE(level, s) \
+ if (level >= debug_centralization) \
+ printf s
+#define DEBUG_TRAINING_HW_ALG(level, s) \
+ if (level >= debug_training_hw_alg) \
+ printf s
+#define DEBUG_LEVELING(level, s) \
+ if (level >= debug_leveling) \
+ printf s
+#define DEBUG_PBS_ENGINE(level, s) \
+ if (level >= debug_pbs) \
+ printf s
+#define DEBUG_TRAINING_STATIC_IP(level, s) \
+ if (level >= debug_training_static) \
+ printf s
+#define DEBUG_TRAINING_ACCESS(level, s) \
+ if (level >= debug_training_access) \
+ printf s
+#endif
+#endif
+
+
+/* Logging defines */
+enum mv_ddr_debug_level {
+ DEBUG_LEVEL_TRACE = 1,
+ DEBUG_LEVEL_INFO = 2,
+ DEBUG_LEVEL_ERROR = 3,
+ DEBUG_LEVEL_LAST
+};
+
+enum ddr_lib_debug_block {
+ DEBUG_BLOCK_STATIC,
+ DEBUG_BLOCK_TRAINING_MAIN,
+ DEBUG_BLOCK_LEVELING,
+ DEBUG_BLOCK_CENTRALIZATION,
+ DEBUG_BLOCK_PBS,
+ DEBUG_BLOCK_IP,
+ DEBUG_BLOCK_BIST,
+ DEBUG_BLOCK_ALG,
+ DEBUG_BLOCK_DEVICE,
+ DEBUG_BLOCK_ACCESS,
+ DEBUG_STAGES_REG_DUMP,
+ /* All excluding IP and REG_DUMP, should be enabled separatelly */
+ DEBUG_BLOCK_ALL
+};
+
+int ddr3_tip_print_log(u32 dev_num, u32 mem_addr);
+int ddr3_tip_print_stability_log(u32 dev_num);
+
+#endif /* _DDR3_LOGGING_CONFIG_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h
new file mode 100644
index 000000000..1e2260b87
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h
@@ -0,0 +1,924 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef __DDR3_PATTERNS_64_H
+#define __DDR3_PATTERNS_64_H
+
+#define FAB_OPT 21
+/*
+ * Patterns Declerations
+ */
+
+u32 wl_sup_pattern[LEN_WL_SUP_PATTERN] __aligned(32) = {
+ 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d,
+ 0x14131211, 0x18171615, 0x1c1b1a19, 0x201f1e1d,
+ 0x24232221, 0x28272625, 0x2c2b2a29, 0x302f2e2d,
+ 0x34333231, 0x38373635, 0x3c3b3a39, 0x403f3e3d,
+ 0x44434241, 0x48474645, 0x4c4b4a49, 0x504f4e4d,
+ 0x54535251, 0x58575655, 0x5c5b5a59, 0x605f5e5d,
+ 0x64636261, 0x68676665, 0x6c6b6a69, 0x706f6e6d,
+ 0x74737271, 0x78777675, 0x7c7b7a79, 0x807f7e7d
+};
+
+u32 pbs_pattern_32b[2][LEN_PBS_PATTERN] __aligned(32) = {
+ {
+ 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa, 0x55555555
+ },
+ {
+ 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa,
+ 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa,
+ 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa,
+ 0x55555555, 0xaaaaaaaa, 0x55555555, 0xaaaaaaaa
+ }
+};
+
+u32 pbs_pattern_64b[2][LEN_PBS_PATTERN] __aligned(32) = {
+ {
+ 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555,
+ 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555,
+ 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555,
+ 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555
+ },
+ {
+ 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa,
+ 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa,
+ 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa,
+ 0x55555555, 0x55555555, 0xaaaaaaaa, 0xaaaaaaaa
+ }
+};
+
+u32 rl_pattern[LEN_STD_PATTERN] __aligned(32) = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x01010101, 0x01010101, 0x01010101, 0x01010101
+};
+
+u32 killer_pattern_32b[DQ_NUM][LEN_KILLER_PATTERN] __aligned(32) = {
+ {
+ 0x01010101, 0x00000000, 0x01010101, 0xffffffff,
+ 0x01010101, 0x00000000, 0x01010101, 0xffffffff,
+ 0xfefefefe, 0xfefefefe, 0x01010101, 0xfefefefe,
+ 0xfefefefe, 0xfefefefe, 0x01010101, 0xfefefefe,
+ 0x01010101, 0xfefefefe, 0x01010101, 0x01010101,
+ 0x01010101, 0xfefefefe, 0x01010101, 0x01010101,
+ 0xfefefefe, 0x01010101, 0xfefefefe, 0x00000000,
+ 0xfefefefe, 0x01010101, 0xfefefefe, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x01010101,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x01010101,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xfefefefe,
+ 0x00000000, 0x00000000, 0x00000000, 0xfefefefe,
+ 0xfefefefe, 0xffffffff, 0x00000000, 0x00000000,
+ 0xfefefefe, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xfefefefe, 0x00000000, 0xfefefefe, 0x00000000,
+ 0xfefefefe, 0x00000000, 0xfefefefe, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x01010101,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x01010101,
+ 0xffffffff, 0xffffffff, 0x01010101, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x01010101, 0x00000000,
+ 0x01010101, 0xffffffff, 0xfefefefe, 0xfefefefe,
+ 0x01010101, 0xffffffff, 0xfefefefe, 0xfefefefe
+ },
+ {
+ 0x02020202, 0x00000000, 0x02020202, 0xffffffff,
+ 0x02020202, 0x00000000, 0x02020202, 0xffffffff,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x02020202, 0xfdfdfdfd,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x02020202, 0xfdfdfdfd,
+ 0x02020202, 0xfdfdfdfd, 0x02020202, 0x02020202,
+ 0x02020202, 0xfdfdfdfd, 0x02020202, 0x02020202,
+ 0xfdfdfdfd, 0x02020202, 0xfdfdfdfd, 0x00000000,
+ 0xfdfdfdfd, 0x02020202, 0xfdfdfdfd, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x02020202,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x02020202,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xfdfdfdfd,
+ 0x00000000, 0x00000000, 0x00000000, 0xfdfdfdfd,
+ 0xfdfdfdfd, 0xffffffff, 0x00000000, 0x00000000,
+ 0xfdfdfdfd, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xfdfdfdfd, 0x00000000, 0xfdfdfdfd, 0x00000000,
+ 0xfdfdfdfd, 0x00000000, 0xfdfdfdfd, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x02020202,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x02020202,
+ 0xffffffff, 0xffffffff, 0x02020202, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x02020202, 0x00000000,
+ 0x02020202, 0xffffffff, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x02020202, 0xffffffff, 0xfdfdfdfd, 0xfdfdfdfd
+ },
+ {
+ 0x04040404, 0x00000000, 0x04040404, 0xffffffff,
+ 0x04040404, 0x00000000, 0x04040404, 0xffffffff,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x04040404, 0xfbfbfbfb,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x04040404, 0xfbfbfbfb,
+ 0x04040404, 0xfbfbfbfb, 0x04040404, 0x04040404,
+ 0x04040404, 0xfbfbfbfb, 0x04040404, 0x04040404,
+ 0xfbfbfbfb, 0x04040404, 0xfbfbfbfb, 0x00000000,
+ 0xfbfbfbfb, 0x04040404, 0xfbfbfbfb, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x04040404,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x04040404,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xfbfbfbfb,
+ 0x00000000, 0x00000000, 0x00000000, 0xfbfbfbfb,
+ 0xfbfbfbfb, 0xffffffff, 0x00000000, 0x00000000,
+ 0xfbfbfbfb, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xfbfbfbfb, 0x00000000, 0xfbfbfbfb, 0x00000000,
+ 0xfbfbfbfb, 0x00000000, 0xfbfbfbfb, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x04040404,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x04040404,
+ 0xffffffff, 0xffffffff, 0x04040404, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x04040404, 0x00000000,
+ 0x04040404, 0xffffffff, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x04040404, 0xffffffff, 0xfbfbfbfb, 0xfbfbfbfb
+ },
+ {
+ 0x08080808, 0x00000000, 0x08080808, 0xffffffff,
+ 0x08080808, 0x00000000, 0x08080808, 0xffffffff,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x08080808, 0xf7f7f7f7,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x08080808, 0xf7f7f7f7,
+ 0x08080808, 0xf7f7f7f7, 0x08080808, 0x08080808,
+ 0x08080808, 0xf7f7f7f7, 0x08080808, 0x08080808,
+ 0xf7f7f7f7, 0x08080808, 0xf7f7f7f7, 0x00000000,
+ 0xf7f7f7f7, 0x08080808, 0xf7f7f7f7, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x08080808,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x08080808,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xf7f7f7f7,
+ 0x00000000, 0x00000000, 0x00000000, 0xf7f7f7f7,
+ 0xf7f7f7f7, 0xffffffff, 0x00000000, 0x00000000,
+ 0xf7f7f7f7, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xf7f7f7f7, 0x00000000, 0xf7f7f7f7, 0x00000000,
+ 0xf7f7f7f7, 0x00000000, 0xf7f7f7f7, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x08080808,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x08080808,
+ 0xffffffff, 0xffffffff, 0x08080808, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x08080808, 0x00000000,
+ 0x08080808, 0xffffffff, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x08080808, 0xffffffff, 0xf7f7f7f7, 0xf7f7f7f7
+ },
+ {
+ 0x10101010, 0x00000000, 0x10101010, 0xffffffff,
+ 0x10101010, 0x00000000, 0x10101010, 0xffffffff,
+ 0xefefefef, 0xefefefef, 0x10101010, 0xefefefef,
+ 0xefefefef, 0xefefefef, 0x10101010, 0xefefefef,
+ 0x10101010, 0xefefefef, 0x10101010, 0x10101010,
+ 0x10101010, 0xefefefef, 0x10101010, 0x10101010,
+ 0xefefefef, 0x10101010, 0xefefefef, 0x00000000,
+ 0xefefefef, 0x10101010, 0xefefefef, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x10101010,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x10101010,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xefefefef,
+ 0x00000000, 0x00000000, 0x00000000, 0xefefefef,
+ 0xefefefef, 0xffffffff, 0x00000000, 0x00000000,
+ 0xefefefef, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xefefefef, 0x00000000, 0xefefefef, 0x00000000,
+ 0xefefefef, 0x00000000, 0xefefefef, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x10101010,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x10101010,
+ 0xffffffff, 0xffffffff, 0x10101010, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x10101010, 0x00000000,
+ 0x10101010, 0xffffffff, 0xefefefef, 0xefefefef,
+ 0x10101010, 0xffffffff, 0xefefefef, 0xefefefef
+ },
+ {
+ 0x20202020, 0x00000000, 0x20202020, 0xffffffff,
+ 0x20202020, 0x00000000, 0x20202020, 0xffffffff,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x20202020, 0xdfdfdfdf,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x20202020, 0xdfdfdfdf,
+ 0x20202020, 0xdfdfdfdf, 0x20202020, 0x20202020,
+ 0x20202020, 0xdfdfdfdf, 0x20202020, 0x20202020,
+ 0xdfdfdfdf, 0x20202020, 0xdfdfdfdf, 0x00000000,
+ 0xdfdfdfdf, 0x20202020, 0xdfdfdfdf, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x20202020,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x20202020,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xdfdfdfdf,
+ 0x00000000, 0x00000000, 0x00000000, 0xdfdfdfdf,
+ 0xdfdfdfdf, 0xffffffff, 0x00000000, 0x00000000,
+ 0xdfdfdfdf, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xdfdfdfdf, 0x00000000, 0xdfdfdfdf, 0x00000000,
+ 0xdfdfdfdf, 0x00000000, 0xdfdfdfdf, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x20202020,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x20202020,
+ 0xffffffff, 0xffffffff, 0x20202020, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x20202020, 0x00000000,
+ 0x20202020, 0xffffffff, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x20202020, 0xffffffff, 0xdfdfdfdf, 0xdfdfdfdf
+ },
+ {
+ 0x40404040, 0x00000000, 0x40404040, 0xffffffff,
+ 0x40404040, 0x00000000, 0x40404040, 0xffffffff,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x40404040, 0xbfbfbfbf,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x40404040, 0xbfbfbfbf,
+ 0x40404040, 0xbfbfbfbf, 0x40404040, 0x40404040,
+ 0x40404040, 0xbfbfbfbf, 0x40404040, 0x40404040,
+ 0xbfbfbfbf, 0x40404040, 0xbfbfbfbf, 0x00000000,
+ 0xbfbfbfbf, 0x40404040, 0xbfbfbfbf, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x40404040,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x40404040,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0xbfbfbfbf,
+ 0x00000000, 0x00000000, 0x00000000, 0xbfbfbfbf,
+ 0xbfbfbfbf, 0xffffffff, 0x00000000, 0x00000000,
+ 0xbfbfbfbf, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xbfbfbfbf, 0x00000000, 0xbfbfbfbf, 0x00000000,
+ 0xbfbfbfbf, 0x00000000, 0xbfbfbfbf, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x40404040,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x40404040,
+ 0xffffffff, 0xffffffff, 0x40404040, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x40404040, 0x00000000,
+ 0x40404040, 0xffffffff, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x40404040, 0xffffffff, 0xbfbfbfbf, 0xbfbfbfbf
+ },
+ {
+ 0x80808080, 0x00000000, 0x80808080, 0xffffffff,
+ 0x80808080, 0x00000000, 0x80808080, 0xffffffff,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x80808080, 0x7f7f7f7f,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x80808080, 0x7f7f7f7f,
+ 0x80808080, 0x7f7f7f7f, 0x80808080, 0x80808080,
+ 0x80808080, 0x7f7f7f7f, 0x80808080, 0x80808080,
+ 0x7f7f7f7f, 0x80808080, 0x7f7f7f7f, 0x00000000,
+ 0x7f7f7f7f, 0x80808080, 0x7f7f7f7f, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x80808080,
+ 0xffffffff, 0x00000000, 0xffffffff, 0x80808080,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x7f7f7f7f,
+ 0x00000000, 0x00000000, 0x00000000, 0x7f7f7f7f,
+ 0x7f7f7f7f, 0xffffffff, 0x00000000, 0x00000000,
+ 0x7f7f7f7f, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x00000000,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
+ 0x7f7f7f7f, 0x00000000, 0x7f7f7f7f, 0x00000000,
+ 0x7f7f7f7f, 0x00000000, 0x7f7f7f7f, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x80808080,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x80808080,
+ 0xffffffff, 0xffffffff, 0x80808080, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x80808080, 0x00000000,
+ 0x80808080, 0xffffffff, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x80808080, 0xffffffff, 0x7f7f7f7f, 0x7f7f7f7f
+ }
+};
+
+u32 killer_pattern_64b[DQ_NUM][LEN_KILLER_PATTERN] __aligned(32) = {
+ {
+ 0x01010101, 0x01010101, 0x00000000, 0x00000000,
+ 0x01010101, 0x01010101, 0xffffffff, 0xffffffff,
+ 0xfefefefe, 0xfefefefe, 0xfefefefe, 0xfefefefe,
+ 0x01010101, 0x01010101, 0xfefefefe, 0xfefefefe,
+ 0x01010101, 0x01010101, 0xfefefefe, 0xfefefefe,
+ 0x01010101, 0x01010101, 0x01010101, 0x01010101,
+ 0xfefefefe, 0xfefefefe, 0x01010101, 0x01010101,
+ 0xfefefefe, 0xfefefefe, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x01010101, 0x01010101,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xfefefefe, 0xfefefefe,
+ 0xfefefefe, 0xfefefefe, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xfefefefe, 0xfefefefe, 0x00000000, 0x00000000,
+ 0xfefefefe, 0xfefefefe, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x01010101, 0x01010101,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x01010101, 0x01010101, 0x00000000, 0x00000000,
+ 0x01010101, 0x01010101, 0xffffffff, 0xffffffff,
+ 0xfefefefe, 0xfefefefe, 0xfefefefe, 0xfefefefe
+ },
+ {
+ 0x02020202, 0x02020202, 0x00000000, 0x00000000,
+ 0x02020202, 0x02020202, 0xffffffff, 0xffffffff,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x02020202, 0x02020202, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x02020202, 0x02020202, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x02020202, 0x02020202, 0x02020202, 0x02020202,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x02020202, 0x02020202,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x02020202, 0x02020202,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x00000000, 0x00000000,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x02020202, 0x02020202,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x02020202, 0x02020202, 0x00000000, 0x00000000,
+ 0x02020202, 0x02020202, 0xffffffff, 0xffffffff,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd
+ },
+ {
+ 0x04040404, 0x04040404, 0x00000000, 0x00000000,
+ 0x04040404, 0x04040404, 0xffffffff, 0xffffffff,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x04040404, 0x04040404, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x04040404, 0x04040404, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x04040404, 0x04040404, 0x04040404, 0x04040404,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x04040404, 0x04040404,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x04040404, 0x04040404,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x00000000, 0x00000000,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x04040404, 0x04040404,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x04040404, 0x04040404, 0x00000000, 0x00000000,
+ 0x04040404, 0x04040404, 0xffffffff, 0xffffffff,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0xfbfbfbfb, 0xfbfbfbfb
+ },
+ {
+ 0x08080808, 0x08080808, 0x00000000, 0x00000000,
+ 0x08080808, 0x08080808, 0xffffffff, 0xffffffff,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x08080808, 0x08080808, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x08080808, 0x08080808, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x08080808, 0x08080808, 0x08080808, 0x08080808,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x08080808, 0x08080808,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x08080808, 0x08080808,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x00000000, 0x00000000,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x08080808, 0x08080808,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x08080808, 0x08080808, 0x00000000, 0x00000000,
+ 0x08080808, 0x08080808, 0xffffffff, 0xffffffff,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0xf7f7f7f7, 0xf7f7f7f7
+ },
+ {
+ 0x10101010, 0x10101010, 0x00000000, 0x00000000,
+ 0x10101010, 0x10101010, 0xffffffff, 0xffffffff,
+ 0xefefefef, 0xefefefef, 0xefefefef, 0xefefefef,
+ 0x10101010, 0x10101010, 0xefefefef, 0xefefefef,
+ 0x10101010, 0x10101010, 0xefefefef, 0xefefefef,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0xefefefef, 0xefefefef, 0x10101010, 0x10101010,
+ 0xefefefef, 0xefefefef, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x10101010, 0x10101010,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xefefefef, 0xefefefef,
+ 0xefefefef, 0xefefefef, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xefefefef, 0xefefefef, 0x00000000, 0x00000000,
+ 0xefefefef, 0xefefefef, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x10101010, 0x10101010,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x10101010, 0x10101010, 0x00000000, 0x00000000,
+ 0x10101010, 0x10101010, 0xffffffff, 0xffffffff,
+ 0xefefefef, 0xefefefef, 0xefefefef, 0xefefefef
+ },
+ {
+ 0x20202020, 0x20202020, 0x00000000, 0x00000000,
+ 0x20202020, 0x20202020, 0xffffffff, 0xffffffff,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x20202020, 0x20202020, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x20202020, 0x20202020, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x20202020, 0x20202020, 0x20202020, 0x20202020,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x20202020, 0x20202020,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x20202020, 0x20202020,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x00000000, 0x00000000,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x20202020, 0x20202020,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x20202020, 0x20202020, 0x00000000, 0x00000000,
+ 0x20202020, 0x20202020, 0xffffffff, 0xffffffff,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0xdfdfdfdf, 0xdfdfdfdf
+ },
+ {
+ 0x40404040, 0x40404040, 0x00000000, 0x00000000,
+ 0x40404040, 0x40404040, 0xffffffff, 0xffffffff,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x40404040, 0x40404040, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x40404040, 0x40404040, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x40404040, 0x40404040, 0x40404040, 0x40404040,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x40404040, 0x40404040,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x40404040, 0x40404040,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x00000000, 0x00000000,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x40404040, 0x40404040,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x40404040, 0x40404040, 0x00000000, 0x00000000,
+ 0x40404040, 0x40404040, 0xffffffff, 0xffffffff,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0xbfbfbfbf, 0xbfbfbfbf
+ },
+ {
+ 0x80808080, 0x80808080, 0x00000000, 0x00000000,
+ 0x80808080, 0x80808080, 0xffffffff, 0xffffffff,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x80808080, 0x80808080, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x80808080, 0x80808080, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x80808080, 0x80808080, 0x80808080, 0x80808080,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x80808080, 0x80808080,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x80808080, 0x80808080,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x00000000, 0x00000000,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x80808080, 0x80808080,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x80808080, 0x80808080, 0x00000000, 0x00000000,
+ 0x80808080, 0x80808080, 0xffffffff, 0xffffffff,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f
+ }
+};
+
+u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN] __aligned(32) = {
+ {
+ 0x00000000, 0x00000000, 0x01010101, 0x01010101,
+ 0xffffffff, 0xffffffff, 0xfefefefe, 0xfefefefe,
+ 0xfefefefe, 0xfefefefe, 0x01010101, 0x01010101,
+ 0xfefefefe, 0xfefefefe, 0x01010101, 0x01010101,
+ 0xfefefefe, 0xfefefefe, 0x01010101, 0x01010101,
+ 0x01010101, 0x01010101, 0xfefefefe, 0xfefefefe,
+ 0x01010101, 0x01010101, 0xfefefefe, 0xfefefefe,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x01010101, 0x01010101, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xfefefefe, 0xfefefefe, 0xfefefefe, 0xfefefefe,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xfefefefe, 0xfefefefe,
+ 0x00000000, 0x00000000, 0xfefefefe, 0xfefefefe,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x01010101, 0x01010101, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x01010101, 0x01010101,
+ 0x00000000, 0x00000000, 0x01010101, 0x01010101,
+ 0xffffffff, 0xffffffff, 0xfefefefe, 0xfefefefe,
+ 0xfefefefe, 0xfefefefe, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x02020202, 0x02020202,
+ 0xffffffff, 0xffffffff, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x02020202, 0x02020202,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x02020202, 0x02020202,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x02020202, 0x02020202,
+ 0x02020202, 0x02020202, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x02020202, 0x02020202, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x02020202, 0x02020202, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x00000000, 0x00000000, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x02020202, 0x02020202, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x02020202, 0x02020202,
+ 0x00000000, 0x00000000, 0x02020202, 0x02020202,
+ 0xffffffff, 0xffffffff, 0xfdfdfdfd, 0xfdfdfdfd,
+ 0xfdfdfdfd, 0xfdfdfdfd, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x04040404, 0x04040404,
+ 0xffffffff, 0xffffffff, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x04040404, 0x04040404,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x04040404, 0x04040404,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x04040404, 0x04040404,
+ 0x04040404, 0x04040404, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x04040404, 0x04040404, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x04040404, 0x04040404, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x00000000, 0x00000000, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x04040404, 0x04040404, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x04040404, 0x04040404,
+ 0x00000000, 0x00000000, 0x04040404, 0x04040404,
+ 0xffffffff, 0xffffffff, 0xfbfbfbfb, 0xfbfbfbfb,
+ 0xfbfbfbfb, 0xfbfbfbfb, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x08080808, 0x08080808,
+ 0xffffffff, 0xffffffff, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x08080808, 0x08080808,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x08080808, 0x08080808,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x08080808, 0x08080808,
+ 0x08080808, 0x08080808, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x08080808, 0x08080808, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x08080808, 0x08080808, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x00000000, 0x00000000, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x08080808, 0x08080808, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x08080808, 0x08080808,
+ 0x00000000, 0x00000000, 0x08080808, 0x08080808,
+ 0xffffffff, 0xffffffff, 0xf7f7f7f7, 0xf7f7f7f7,
+ 0xf7f7f7f7, 0xf7f7f7f7, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x10101010, 0x10101010,
+ 0xffffffff, 0xffffffff, 0xefefefef, 0xefefefef,
+ 0xefefefef, 0xefefefef, 0x10101010, 0x10101010,
+ 0xefefefef, 0xefefefef, 0x10101010, 0x10101010,
+ 0xefefefef, 0xefefefef, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0xefefefef, 0xefefefef,
+ 0x10101010, 0x10101010, 0xefefefef, 0xefefefef,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x10101010, 0x10101010, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xefefefef, 0xefefefef, 0xefefefef, 0xefefefef,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xefefefef, 0xefefefef,
+ 0x00000000, 0x00000000, 0xefefefef, 0xefefefef,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x10101010, 0x10101010, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x10101010, 0x10101010,
+ 0x00000000, 0x00000000, 0x10101010, 0x10101010,
+ 0xffffffff, 0xffffffff, 0xefefefef, 0xefefefef,
+ 0xefefefef, 0xefefefef, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x20202020, 0x20202020,
+ 0xffffffff, 0xffffffff, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x20202020, 0x20202020,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x20202020, 0x20202020,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x20202020, 0x20202020,
+ 0x20202020, 0x20202020, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x20202020, 0x20202020, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x20202020, 0x20202020, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x00000000, 0x00000000, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x20202020, 0x20202020, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x20202020, 0x20202020,
+ 0x00000000, 0x00000000, 0x20202020, 0x20202020,
+ 0xffffffff, 0xffffffff, 0xdfdfdfdf, 0xdfdfdfdf,
+ 0xdfdfdfdf, 0xdfdfdfdf, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x40404040, 0x40404040,
+ 0xffffffff, 0xffffffff, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x40404040, 0x40404040,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x40404040, 0x40404040,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x40404040, 0x40404040,
+ 0x40404040, 0x40404040, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x40404040, 0x40404040, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x40404040, 0x40404040, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x00000000, 0x00000000, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x40404040, 0x40404040, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x40404040, 0x40404040,
+ 0x00000000, 0x00000000, 0x40404040, 0x40404040,
+ 0xffffffff, 0xffffffff, 0xbfbfbfbf, 0xbfbfbfbf,
+ 0xbfbfbfbf, 0xbfbfbfbf, 0x00000000, 0x00000000
+ },
+ {
+ 0x00000000, 0x00000000, 0x80808080, 0x80808080,
+ 0xffffffff, 0xffffffff, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x80808080, 0x80808080,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x80808080, 0x80808080,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x80808080, 0x80808080,
+ 0x80808080, 0x80808080, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x80808080, 0x80808080, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0x80808080, 0x80808080, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x00000000, 0x00000000, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x80808080, 0x80808080, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0x80808080, 0x80808080,
+ 0x00000000, 0x00000000, 0x80808080, 0x80808080,
+ 0xffffffff, 0xffffffff, 0x7f7f7f7f, 0x7f7f7f7f,
+ 0x7f7f7f7f, 0x7f7f7f7f, 0x00000000, 0x00000000
+ }
+};
+
+/* Fabric ratios table */
+u32 fabric_ratio[FAB_OPT] = {
+ 0x04010204,
+ 0x04020202,
+ 0x08020306,
+ 0x08020303,
+ 0x04020303,
+ 0x04020204,
+ 0x04010202,
+ 0x08030606,
+ 0x08030505,
+ 0x04020306,
+ 0x0804050a,
+ 0x04030606,
+ 0x04020404,
+ 0x04030306,
+ 0x04020505,
+ 0x08020505,
+ 0x04010303,
+ 0x08050a0a,
+ 0x04030408,
+ 0x04010102,
+ 0x08030306
+};
+
+u32 pbs_dq_mapping[PUP_NUM_64BIT + 1][DQ_NUM] = {
+ {3, 2, 5, 7, 1, 0, 6, 4},
+ {2, 3, 6, 7, 1, 0, 4, 5},
+ {1, 3, 5, 6, 0, 2, 4, 7},
+ {0, 2, 4, 7, 1, 3, 5, 6},
+ {3, 0, 4, 6, 1, 2, 5, 7},
+ {0, 3, 5, 7, 1, 2, 4, 6},
+ {2, 3, 5, 7, 1, 0, 4, 6},
+ {0, 2, 5, 4, 1, 3, 6, 7},
+ {2, 3, 4, 7, 0, 1, 5, 6}
+};
+
+#endif /* __DDR3_PATTERNS_64_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training.c
new file mode 100644
index 000000000..2512b58cb
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training.c
@@ -0,0 +1,2898 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_common.h"
+#include "mv_ddr_training_db.h"
+#include "mv_ddr_regs.h"
+
+#define GET_CS_FROM_MASK(mask) (cs_mask2_num[mask])
+#define CS_CBE_VALUE(cs_num) (cs_cbe_reg[cs_num])
+
+u32 window_mem_addr = 0;
+u32 phy_reg0_val = 0;
+u32 phy_reg1_val = 8;
+u32 phy_reg2_val = 0;
+u32 phy_reg3_val = PARAM_UNDEFINED;
+enum mv_ddr_freq low_freq = MV_DDR_FREQ_LOW_FREQ;
+enum mv_ddr_freq medium_freq;
+u32 debug_dunit = 0;
+u32 odt_additional = 1;
+u32 *dq_map_table = NULL;
+
+/* in case of ddr4 do not run ddr3_tip_write_additional_odt_setting function - mc odt always 'on'
+ * in ddr4 case the terminations are rttWR and rttPARK and the odt must be always 'on' 0x1498 = 0xf
+ */
+u32 odt_config = 1;
+
+u32 nominal_avs;
+u32 extension_avs;
+
+u32 is_pll_before_init = 0, is_adll_calib_before_init = 1, is_dfs_in_init = 0;
+u32 dfs_low_freq;
+
+u32 g_rtt_nom_cs0, g_rtt_nom_cs1;
+u8 calibration_update_control; /* 2 external only, 1 is internal only */
+
+enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM];
+enum auto_tune_stage training_stage = INIT_CONTROLLER;
+u32 finger_test = 0, p_finger_start = 11, p_finger_end = 64,
+ n_finger_start = 11, n_finger_end = 64,
+ p_finger_step = 3, n_finger_step = 3;
+u32 clamp_tbl[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
+
+/* Initiate to 0xff, this variable is define by user in debug mode */
+u32 mode_2t = 0xff;
+u32 xsb_validate_type = 0;
+u32 xsb_validation_base_address = 0xf000;
+u32 first_active_if = 0;
+u32 dfs_low_phy1 = 0x1f;
+u32 multicast_id = 0;
+int use_broadcast = 0;
+struct hws_tip_freq_config_info *freq_info_table = NULL;
+u8 is_cbe_required = 0;
+u32 debug_mode = 0;
+u32 delay_enable = 0;
+int rl_mid_freq_wa = 0;
+
+u32 effective_cs = 0;
+
+u32 vref_init_val = 0x4;
+u32 ck_delay = PARAM_UNDEFINED;
+
+/* Design guidelines parameters */
+u32 g_zpri_data = PARAM_UNDEFINED; /* controller data - P drive strength */
+u32 g_znri_data = PARAM_UNDEFINED; /* controller data - N drive strength */
+u32 g_zpri_ctrl = PARAM_UNDEFINED; /* controller C/A - P drive strength */
+u32 g_znri_ctrl = PARAM_UNDEFINED; /* controller C/A - N drive strength */
+
+u32 g_zpodt_data = PARAM_UNDEFINED; /* controller data - P ODT */
+u32 g_znodt_data = PARAM_UNDEFINED; /* controller data - N ODT */
+u32 g_zpodt_ctrl = PARAM_UNDEFINED; /* controller data - P ODT */
+u32 g_znodt_ctrl = PARAM_UNDEFINED; /* controller data - N ODT */
+
+u32 g_odt_config = PARAM_UNDEFINED;
+u32 g_rtt_nom = PARAM_UNDEFINED;
+u32 g_rtt_wr = PARAM_UNDEFINED;
+u32 g_dic = PARAM_UNDEFINED;
+u32 g_rtt_park = PARAM_UNDEFINED;
+
+u32 mask_tune_func = (SET_MEDIUM_FREQ_MASK_BIT |
+ WRITE_LEVELING_MASK_BIT |
+ LOAD_PATTERN_2_MASK_BIT |
+ READ_LEVELING_MASK_BIT |
+ SET_TARGET_FREQ_MASK_BIT |
+ WRITE_LEVELING_TF_MASK_BIT |
+ READ_LEVELING_TF_MASK_BIT |
+ CENTRALIZATION_RX_MASK_BIT |
+ CENTRALIZATION_TX_MASK_BIT);
+
+static int ddr3_tip_ddr3_training_main_flow(u32 dev_num);
+static int ddr3_tip_write_odt(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, u32 cl_value, u32 cwl_value);
+static int ddr3_tip_ddr3_auto_tune(u32 dev_num);
+
+#ifdef ODT_TEST_SUPPORT
+static int odt_test(u32 dev_num, enum hws_algo_type algo_type);
+#endif
+
+int adll_calibration(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency);
+static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency);
+
+static u8 mem_size_config[MV_DDR_DIE_CAP_LAST] = {
+ 0x2, /* 512Mbit */
+ 0x3, /* 1Gbit */
+ 0x0, /* 2Gbit */
+ 0x4, /* 4Gbit */
+ 0x5, /* 8Gbit */
+ 0x0, /* TODO: placeholder for 16-Mbit die capacity */
+ 0x0, /* TODO: placeholder for 32-Mbit die capacity */
+ 0x0, /* TODO: placeholder for 12-Mbit die capacity */
+ 0x0 /* TODO: placeholder for 24-Mbit die capacity */
+};
+
+static u8 cs_mask2_num[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
+
+static struct reg_data odpg_default_value[] = {
+ {0x1034, 0x38000, MASK_ALL_BITS},
+ {0x1038, 0x0, MASK_ALL_BITS},
+ {0x10b0, 0x0, MASK_ALL_BITS},
+ {0x10b8, 0x0, MASK_ALL_BITS},
+ {0x10c0, 0x0, MASK_ALL_BITS},
+ {0x10f0, 0x0, MASK_ALL_BITS},
+ {0x10f4, 0x0, MASK_ALL_BITS},
+ {0x10f8, 0xff, MASK_ALL_BITS},
+ {0x10fc, 0xffff, MASK_ALL_BITS},
+ {0x1130, 0x0, MASK_ALL_BITS},
+ {0x1830, 0x2000000, MASK_ALL_BITS},
+ {0x14d0, 0x0, MASK_ALL_BITS},
+ {0x14d4, 0x0, MASK_ALL_BITS},
+ {0x14d8, 0x0, MASK_ALL_BITS},
+ {0x14dc, 0x0, MASK_ALL_BITS},
+ {0x1454, 0x0, MASK_ALL_BITS},
+ {0x1594, 0x0, MASK_ALL_BITS},
+ {0x1598, 0x0, MASK_ALL_BITS},
+ {0x159c, 0x0, MASK_ALL_BITS},
+ {0x15a0, 0x0, MASK_ALL_BITS},
+ {0x15a4, 0x0, MASK_ALL_BITS},
+ {0x15a8, 0x0, MASK_ALL_BITS},
+ {0x15ac, 0x0, MASK_ALL_BITS},
+ {0x1600, 0x0, MASK_ALL_BITS},
+ {0x1604, 0x0, MASK_ALL_BITS},
+ {0x1608, 0x0, MASK_ALL_BITS},
+ {0x160c, 0x0, MASK_ALL_BITS},
+ {0x1610, 0x0, MASK_ALL_BITS},
+ {0x1614, 0x0, MASK_ALL_BITS},
+ {0x1618, 0x0, MASK_ALL_BITS},
+ {0x1624, 0x0, MASK_ALL_BITS},
+ {0x1690, 0x0, MASK_ALL_BITS},
+ {0x1694, 0x0, MASK_ALL_BITS},
+ {0x1698, 0x0, MASK_ALL_BITS},
+ {0x169c, 0x0, MASK_ALL_BITS},
+ {0x14b8, 0x6f67, MASK_ALL_BITS},
+ {0x1630, 0x0, MASK_ALL_BITS},
+ {0x1634, 0x0, MASK_ALL_BITS},
+ {0x1638, 0x0, MASK_ALL_BITS},
+ {0x163c, 0x0, MASK_ALL_BITS},
+ {0x16b0, 0x0, MASK_ALL_BITS},
+ {0x16b4, 0x0, MASK_ALL_BITS},
+ {0x16b8, 0x0, MASK_ALL_BITS},
+ {0x16bc, 0x0, MASK_ALL_BITS},
+ {0x16c0, 0x0, MASK_ALL_BITS},
+ {0x16c4, 0x0, MASK_ALL_BITS},
+ {0x16c8, 0x0, MASK_ALL_BITS},
+ {0x16cc, 0x1, MASK_ALL_BITS},
+ {0x16f0, 0x1, MASK_ALL_BITS},
+ {0x16f4, 0x0, MASK_ALL_BITS},
+ {0x16f8, 0x0, MASK_ALL_BITS},
+ {0x16fc, 0x0, MASK_ALL_BITS}
+};
+
+/* MR cmd and addr definitions */
+struct mv_ddr_mr_data mr_data[] = {
+ {MRS0_CMD, MR0_REG},
+ {MRS1_CMD, MR1_REG},
+ {MRS2_CMD, MR2_REG},
+ {MRS3_CMD, MR3_REG}
+};
+
+/* inverse pads */
+static int ddr3_tip_pad_inv(void)
+{
+ u32 sphy, data;
+ u32 sphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ u32 ck_swap_ctrl_sphy;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ for (sphy = 0; sphy < sphy_max; sphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sphy);
+ if (tm->interface_params[0].
+ as_bus_params[sphy].is_dqs_swap == 1) {
+ data = (INVERT_PAD << INV_PAD4_OFFS |
+ INVERT_PAD << INV_PAD5_OFFS);
+ /* dqs swap */
+ ddr3_tip_bus_read_modify_write(0, ACCESS_TYPE_UNICAST,
+ 0, sphy,
+ DDR_PHY_DATA,
+ PHY_CTRL_PHY_REG,
+ data, data);
+ }
+
+ if (tm->interface_params[0].as_bus_params[sphy].
+ is_ck_swap == 1 && sphy == 0) {
+/* TODO: move this code to per platform one */
+ /* clock swap for both cs0 and cs1 */
+ data = (INVERT_PAD << INV_PAD2_OFFS |
+ INVERT_PAD << INV_PAD6_OFFS |
+ INVERT_PAD << INV_PAD4_OFFS |
+ INVERT_PAD << INV_PAD5_OFFS);
+ ck_swap_ctrl_sphy = CK_SWAP_CTRL_PHY_NUM;
+ ddr3_tip_bus_read_modify_write(0, ACCESS_TYPE_UNICAST,
+ 0, ck_swap_ctrl_sphy,
+ DDR_PHY_CONTROL,
+ PHY_CTRL_PHY_REG,
+ data, data);
+ }
+ }
+
+ return MV_OK;
+}
+
+static int ddr3_tip_rank_control(u32 dev_num, u32 if_id);
+
+/*
+ * Update global training parameters by data from user
+ */
+int ddr3_tip_tune_training_params(u32 dev_num,
+ struct tune_train_params *params)
+{
+ if (params->ck_delay != PARAM_UNDEFINED)
+ ck_delay = params->ck_delay;
+ if (params->phy_reg3_val != PARAM_UNDEFINED)
+ phy_reg3_val = params->phy_reg3_val;
+ if (params->g_rtt_nom != PARAM_UNDEFINED)
+ g_rtt_nom = params->g_rtt_nom;
+ if (params->g_rtt_wr != PARAM_UNDEFINED)
+ g_rtt_wr = params->g_rtt_wr;
+ if (params->g_dic != PARAM_UNDEFINED)
+ g_dic = params->g_dic;
+ if (params->g_odt_config != PARAM_UNDEFINED)
+ g_odt_config = params->g_odt_config;
+ if (params->g_zpri_data != PARAM_UNDEFINED)
+ g_zpri_data = params->g_zpri_data;
+ if (params->g_znri_data != PARAM_UNDEFINED)
+ g_znri_data = params->g_znri_data;
+ if (params->g_zpri_ctrl != PARAM_UNDEFINED)
+ g_zpri_ctrl = params->g_zpri_ctrl;
+ if (params->g_znri_ctrl != PARAM_UNDEFINED)
+ g_znri_ctrl = params->g_znri_ctrl;
+ if (params->g_zpodt_data != PARAM_UNDEFINED)
+ g_zpodt_data = params->g_zpodt_data;
+ if (params->g_znodt_data != PARAM_UNDEFINED)
+ g_znodt_data = params->g_znodt_data;
+ if (params->g_zpodt_ctrl != PARAM_UNDEFINED)
+ g_zpodt_ctrl = params->g_zpodt_ctrl;
+ if (params->g_znodt_ctrl != PARAM_UNDEFINED)
+ g_znodt_ctrl = params->g_znodt_ctrl;
+ if (params->g_rtt_park != PARAM_UNDEFINED)
+ g_rtt_park = params->g_rtt_park;
+
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("DGL parameters: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",
+ g_zpri_data, g_znri_data, g_zpri_ctrl, g_znri_ctrl, g_zpodt_data, g_znodt_data,
+ g_zpodt_ctrl, g_znodt_ctrl, g_rtt_nom, g_dic, g_odt_config, g_rtt_wr));
+
+ return MV_OK;
+}
+
+/*
+ * Configure CS
+ */
+int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable)
+{
+ u32 data, addr_hi, data_high;
+ u32 mem_index;
+ u32 clk_enable;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (tm->clk_enable & (1 << cs_num))
+ clk_enable = 1;
+ else
+ clk_enable = enable;
+
+ if (enable == 1) {
+ data = (tm->interface_params[if_id].bus_width ==
+ MV_DDR_DEV_WIDTH_8BIT) ? 0 : 1;
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ SDRAM_ADDR_CTRL_REG, (data << (cs_num * 4)),
+ 0x3 << (cs_num * 4)));
+ mem_index = tm->interface_params[if_id].memory_size;
+
+ addr_hi = mem_size_config[mem_index] & 0x3;
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ SDRAM_ADDR_CTRL_REG,
+ (addr_hi << (2 + cs_num * 4)),
+ 0x3 << (2 + cs_num * 4)));
+
+ data_high = (mem_size_config[mem_index] & 0x4) >> 2;
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ SDRAM_ADDR_CTRL_REG,
+ data_high << (20 + cs_num), 1 << (20 + cs_num)));
+
+ /* Enable Address Select Mode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ SDRAM_ADDR_CTRL_REG, 1 << (16 + cs_num),
+ 1 << (16 + cs_num)));
+ }
+ switch (cs_num) {
+ case 0:
+ case 1:
+ case 2:
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUNIT_CTRL_LOW_REG, (clk_enable << (cs_num + 11)),
+ 1 << (cs_num + 11)));
+ break;
+ case 3:
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUNIT_CTRL_LOW_REG, (clk_enable << 15), 1 << 15));
+ break;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Init Controller Flow
+ */
+int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_prm)
+{
+ u32 if_id;
+ u32 cs_num;
+ u32 t_ckclk = 0, t_wr = 0, t2t = 0;
+ u32 data_value = 0, cs_cnt = 0,
+ mem_mask = 0, bus_index = 0;
+ enum mv_ddr_speed_bin speed_bin_index = SPEED_BIN_DDR_2133N;
+ u32 cs_mask = 0;
+ u32 cl_value = 0, cwl_val = 0;
+ u32 bus_cnt = 0, adll_tap = 0;
+ enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
+ u32 data_read[MAX_INTERFACE_NUM];
+ 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();
+ enum mv_ddr_timing timing;
+ enum mv_ddr_freq freq = tm->interface_params[0].memory_freq;
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("Init_controller, do_mrs_phy=%d, is_ctrl64_bit=%d\n",
+ init_cntr_prm->do_mrs_phy,
+ init_cntr_prm->is_ctrl64_bit));
+
+ if (init_cntr_prm->init_phy == 1) {
+ CHECK_STATUS(ddr3_tip_configure_phy(dev_num));
+ }
+
+ if (generic_init_controller == 1) {
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("active IF %d\n", if_id));
+ mem_mask = 0;
+ for (bus_index = 0;
+ bus_index < octets_per_if_num;
+ bus_index++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index);
+ mem_mask |=
+ tm->interface_params[if_id].
+ as_bus_params[bus_index].mirror_enable_bitmask;
+ }
+
+ if (mem_mask != 0) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, DUAL_DUNIT_CFG_REG, 0,
+ 0x8));
+ }
+
+ speed_bin_index =
+ tm->interface_params[if_id].
+ speed_bin_index;
+
+ /* t_ckclk is external clock */
+ t_ckclk = (MEGA / mv_ddr_freq_get(freq));
+
+ if (MV_DDR_IS_HALF_BUS_DRAM_MODE(tm->bus_act_mask, octets_per_if_num))
+ data_value = (0x4000 | 0 | 0x1000000) & ~(1 << 26);
+ else
+ data_value = (0x4000 | 0x8000 | 0x1000000) & ~(1 << 26);
+
+ /* Interface Bus Width */
+ /* SRMode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_CFG_REG, data_value,
+ 0x100c000));
+
+ /* Interleave first command pre-charge enable (TBD) */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_OPEN_PAGES_CTRL_REG, (1 << 10),
+ (1 << 10)));
+
+ /* Reset divider_b assert -> de-assert */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_CFG_REG,
+ 0x0 << PUP_RST_DIVIDER_OFFS,
+ PUP_RST_DIVIDER_MASK << PUP_RST_DIVIDER_OFFS));
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_CFG_REG,
+ 0x1 << PUP_RST_DIVIDER_OFFS,
+ PUP_RST_DIVIDER_MASK << PUP_RST_DIVIDER_OFFS));
+
+ /* PHY configuration */
+ /*
+ * Postamble Length = 1.5cc, Addresscntl to clk skew
+ * \BD, Preamble length normal, parralal ADLL enable
+ */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DRAM_PHY_CFG_REG, 0x28, 0x3e));
+ if (init_cntr_prm->is_ctrl64_bit) {
+ /* positive edge */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DRAM_PHY_CFG_REG, 0x0,
+ 0xff80));
+ }
+
+ /* calibration block disable */
+ /* Xbar Read buffer select (for Internal access) */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MAIN_PADS_CAL_MACH_CTRL_REG, 0x1200c,
+ 0x7dffe01c));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MAIN_PADS_CAL_MACH_CTRL_REG,
+ calibration_update_control << 3, 0x3 << 3));
+
+ /* Pad calibration control - enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MAIN_PADS_CAL_MACH_CTRL_REG, 0x1, 0x1));
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) {
+ /* DDR3 rank ctrl \96 part of the generic code */
+ /* CS1 mirroring enable + w/a for JIRA DUNIT-14581 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DDR3_RANK_CTRL_REG, 0x27, MASK_ALL_BITS));
+ }
+
+ cs_mask = 0;
+ data_value = 0x7;
+ /*
+ * Address ctrl \96 Part of the Generic code
+ * The next configuration is done:
+ * 1) Memory Size
+ * 2) Bus_width
+ * 3) CS#
+ * 4) Page Number
+ * Per Dunit get from the Map_topology the parameters:
+ * Bus_width
+ */
+
+ data_value =
+ (tm->interface_params[if_id].
+ bus_width == MV_DDR_DEV_WIDTH_8BIT) ? 0 : 1;
+
+ /* create merge cs mask for all cs available in dunit */
+ for (bus_cnt = 0;
+ bus_cnt < octets_per_if_num;
+ bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ cs_mask |=
+ tm->interface_params[if_id].
+ as_bus_params[bus_cnt].cs_bitmask;
+ }
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("Init_controller IF %d cs_mask %d\n",
+ if_id, cs_mask));
+ /*
+ * Configure the next upon the Map Topology \96 If the
+ * Dunit is CS0 Configure CS0 if it is multi CS
+ * configure them both: The Bust_width it\92s the
+ * Memory Bus width \96 x8 or x16
+ */
+ for (cs_cnt = 0; cs_cnt < MAX_CS_NUM; cs_cnt++) {
+ ddr3_tip_configure_cs(dev_num, if_id, cs_cnt,
+ ((cs_mask & (1 << cs_cnt)) ? 1
+ : 0));
+ }
+
+ if (init_cntr_prm->do_mrs_phy) {
+ /*
+ * MR0 \96 Part of the Generic code
+ * The next configuration is done:
+ * 1) Burst Length
+ * 2) CAS Latency
+ * get for each dunit what is it Speed_bin &
+ * Target Frequency. From those both parameters
+ * get the appropriate Cas_l from the CL table
+ */
+ cl_value =
+ tm->interface_params[if_id].
+ cas_l;
+ cwl_val =
+ tm->interface_params[if_id].
+ cas_wl;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("cl_value 0x%x cwl_val 0x%x\n",
+ cl_value, cwl_val));
+
+ t_wr = time_to_nclk(mv_ddr_speed_bin_timing_get
+ (speed_bin_index,
+ SPEED_BIN_TWR), t_ckclk);
+
+ data_value =
+ ((cl_mask_table[cl_value] & 0x1) << 2) |
+ ((cl_mask_table[cl_value] & 0xe) << 3);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MR0_REG, data_value,
+ (0x7 << 4) | (1 << 2)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MR0_REG, twr_mask_table[t_wr] << 9,
+ 0x7 << 9));
+
+ /*
+ * MR1: Set RTT and DIC Design GL values
+ * configured by user
+ */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, MR1_REG,
+ g_dic | g_rtt_nom, 0x266));
+
+ /* MR2 - Part of the Generic code */
+ /*
+ * The next configuration is done:
+ * 1) SRT
+ * 2) CAS Write Latency
+ */
+ data_value = (cwl_mask_table[cwl_val] << 3);
+ data_value |=
+ ((tm->interface_params[if_id].
+ interface_temp ==
+ MV_DDR_TEMP_HIGH) ? (1 << 7) : 0);
+ data_value |= g_rtt_wr;
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MR2_REG, data_value,
+ (0x7 << 3) | (0x1 << 7) | (0x3 <<
+ 9)));
+ }
+
+ ddr3_tip_write_odt(dev_num, access_type, if_id,
+ cl_value, cwl_val);
+ ddr3_tip_set_timing(dev_num, access_type, if_id, freq);
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DUNIT_CTRL_HIGH_REG, 0x1000119,
+ 0x100017F));
+ } else {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DUNIT_CTRL_HIGH_REG, 0x600177 |
+ (init_cntr_prm->is_ctrl64_bit ?
+ CPU_INTERJECTION_ENA_SPLIT_ENA << CPU_INTERJECTION_ENA_OFFS :
+ CPU_INTERJECTION_ENA_SPLIT_DIS << CPU_INTERJECTION_ENA_OFFS),
+ 0x1600177 | CPU_INTERJECTION_ENA_MASK <<
+ CPU_INTERJECTION_ENA_OFFS));
+ }
+
+ /* reset bit 7 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DUNIT_CTRL_HIGH_REG,
+ (init_cntr_prm->msys_init << 7), (1 << 7)));
+
+ timing = tm->interface_params[if_id].timing;
+
+ if (mode_2t != 0xff) {
+ t2t = mode_2t;
+ } else if (timing != MV_DDR_TIM_DEFAULT) {
+ t2t = (timing == MV_DDR_TIM_2T) ? 1 : 0;
+ } else {
+ /* calculate number of CS (per interface) */
+ cs_num = mv_ddr_cs_num_get();
+ t2t = (cs_num == 1) ? 0 : 1;
+ }
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DUNIT_CTRL_LOW_REG, t2t << 3,
+ 0x3 << 3));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DDR_TIMING_REG, 0x28 << 9, 0x3f << 9));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DDR_TIMING_REG, 0xa << 21, 0xff << 21));
+
+ /* move the block to ddr3_tip_set_timing - end */
+ /* AUTO_ZQC_TIMING */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ ZQC_CFG_REG, (AUTO_ZQC_TIMING | (2 << 20)),
+ 0x3fffff));
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, access_type, if_id,
+ DRAM_PHY_CFG_REG, data_read, 0x30));
+ data_value =
+ (data_read[if_id] == 0) ? (1 << 11) : 0;
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DUNIT_CTRL_HIGH_REG, data_value,
+ (1 << 11)));
+
+ /* Set Active control for ODT write transactions */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, 0x1494, g_odt_config,
+ MASK_ALL_BITS));
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) == MV_TIP_REV_3) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x14a8, 0x900, 0x900));
+ /* wa: controls control sub-phy outputs floating during self-refresh */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x16d0, 0, 0x8000));
+ }
+ }
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ CHECK_STATUS(ddr3_tip_rank_control(dev_num, if_id));
+
+ if (init_cntr_prm->do_mrs_phy)
+ ddr3_tip_pad_inv();
+
+ /* Pad calibration control - disable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MAIN_PADS_CAL_MACH_CTRL_REG, 0x0, 0x1));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ MAIN_PADS_CAL_MACH_CTRL_REG,
+ calibration_update_control << 3, 0x3 << 3));
+ }
+
+
+ if (delay_enable != 0) {
+ adll_tap = MEGA / (mv_ddr_freq_get(freq) * 64);
+ ddr3_tip_cmd_addr_init_delay(dev_num, adll_tap);
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Rank Control Flow
+ */
+static int ddr3_tip_rev2_rank_control(u32 dev_num, u32 if_id)
+{
+ u32 data_value = 0, bus_cnt = 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();
+
+ for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ data_value |= tm->interface_params[if_id].as_bus_params[bus_cnt].
+ cs_bitmask;
+
+ if (tm->interface_params[if_id].as_bus_params[bus_cnt].
+ mirror_enable_bitmask == 1) {
+ /*
+ * Check mirror_enable_bitmask
+ * If it is enabled, CS + 4 bit in a word to be '1'
+ */
+ if ((tm->interface_params[if_id].as_bus_params[bus_cnt].
+ cs_bitmask & 0x1) != 0) {
+ data_value |= tm->interface_params[if_id].
+ as_bus_params[bus_cnt].
+ mirror_enable_bitmask << 4;
+ }
+
+ if ((tm->interface_params[if_id].as_bus_params[bus_cnt].
+ cs_bitmask & 0x2) != 0) {
+ data_value |= tm->interface_params[if_id].
+ as_bus_params[bus_cnt].
+ mirror_enable_bitmask << 5;
+ }
+
+ if ((tm->interface_params[if_id].as_bus_params[bus_cnt].
+ cs_bitmask & 0x4) != 0) {
+ data_value |= tm->interface_params[if_id].
+ as_bus_params[bus_cnt].
+ mirror_enable_bitmask << 6;
+ }
+
+ if ((tm->interface_params[if_id].as_bus_params[bus_cnt].
+ cs_bitmask & 0x8) != 0) {
+ data_value |= tm->interface_params[if_id].
+ as_bus_params[bus_cnt].
+ mirror_enable_bitmask << 7;
+ }
+ }
+ }
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, DDR3_RANK_CTRL_REG,
+ data_value, 0xff));
+
+ return MV_OK;
+}
+
+static int ddr3_tip_rev3_rank_control(u32 dev_num, u32 if_id)
+{
+ u32 data_value = 0, bus_cnt;
+ 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 (bus_cnt = 1; bus_cnt < octets_per_if_num; bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ if ((tm->interface_params[if_id].
+ as_bus_params[0].cs_bitmask !=
+ tm->interface_params[if_id].
+ as_bus_params[bus_cnt].cs_bitmask) ||
+ (tm->interface_params[if_id].
+ as_bus_params[0].mirror_enable_bitmask !=
+ tm->interface_params[if_id].
+ as_bus_params[bus_cnt].mirror_enable_bitmask))
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("WARNING:Wrong configuration for pup #%d CS mask and CS mirroring for all pups should be the same\n",
+ bus_cnt));
+ }
+
+ data_value |= tm->interface_params[if_id].
+ as_bus_params[0].cs_bitmask;
+ data_value |= tm->interface_params[if_id].
+ as_bus_params[0].mirror_enable_bitmask << 4;
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, DDR3_RANK_CTRL_REG,
+ data_value, 0xff));
+
+ return MV_OK;
+}
+
+static int ddr3_tip_rank_control(u32 dev_num, u32 if_id)
+{
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) == MV_TIP_REV_2)
+ return ddr3_tip_rev2_rank_control(dev_num, if_id);
+ else
+ return ddr3_tip_rev3_rank_control(dev_num, if_id);
+}
+
+/*
+ * Algorithm Parameters Validation
+ */
+int ddr3_tip_validate_algo_var(u32 value, u32 fail_value, char *var_name)
+{
+ if (value == fail_value) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Error: %s is not initialized (Algo Components Validation)\n",
+ var_name));
+ return 0;
+ }
+
+ return 1;
+}
+
+int ddr3_tip_validate_algo_ptr(void *ptr, void *fail_value, char *ptr_name)
+{
+ if (ptr == fail_value) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Error: %s is not initialized (Algo Components Validation)\n",
+ ptr_name));
+ return 0;
+ }
+
+ return 1;
+}
+
+int ddr3_tip_validate_algo_components(u8 dev_num)
+{
+ int status = 1;
+
+ /* Check DGL parameters*/
+ status &= ddr3_tip_validate_algo_var(ck_delay, PARAM_UNDEFINED, "ck_delay");
+ status &= ddr3_tip_validate_algo_var(phy_reg3_val, PARAM_UNDEFINED, "phy_reg3_val");
+ status &= ddr3_tip_validate_algo_var(g_rtt_nom, PARAM_UNDEFINED, "g_rtt_nom");
+ status &= ddr3_tip_validate_algo_var(g_dic, PARAM_UNDEFINED, "g_dic");
+ status &= ddr3_tip_validate_algo_var(odt_config, PARAM_UNDEFINED, "odt_config");
+ status &= ddr3_tip_validate_algo_var(g_zpri_data, PARAM_UNDEFINED, "g_zpri_data");
+ status &= ddr3_tip_validate_algo_var(g_znri_data, PARAM_UNDEFINED, "g_znri_data");
+ status &= ddr3_tip_validate_algo_var(g_zpri_ctrl, PARAM_UNDEFINED, "g_zpri_ctrl");
+ status &= ddr3_tip_validate_algo_var(g_znri_ctrl, PARAM_UNDEFINED, "g_znri_ctrl");
+ status &= ddr3_tip_validate_algo_var(g_zpodt_data, PARAM_UNDEFINED, "g_zpodt_data");
+ status &= ddr3_tip_validate_algo_var(g_znodt_data, PARAM_UNDEFINED, "g_znodt_data");
+ status &= ddr3_tip_validate_algo_var(g_zpodt_ctrl, PARAM_UNDEFINED, "g_zpodt_ctrl");
+ status &= ddr3_tip_validate_algo_var(g_znodt_ctrl, PARAM_UNDEFINED, "g_znodt_ctrl");
+
+ /* Check functions pointers */
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_dunit_mux_select_func,
+ NULL, "tip_dunit_mux_select_func");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_dunit_write,
+ NULL, "mv_ddr_dunit_write");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_dunit_read,
+ NULL, "mv_ddr_dunit_read");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_phy_write,
+ NULL, "mv_ddr_phy_write");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_phy_read,
+ NULL, "mv_ddr_phy_read");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_get_freq_config_info_func,
+ NULL, "tip_get_freq_config_info_func");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_set_freq_divider_func,
+ NULL, "tip_set_freq_divider_func");
+ status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_get_clock_ratio,
+ NULL, "tip_get_clock_ratio");
+
+ status &= ddr3_tip_validate_algo_ptr(dq_map_table, NULL, "dq_map_table");
+ status &= ddr3_tip_validate_algo_var(dfs_low_freq, 0, "dfs_low_freq");
+
+ return (status == 1) ? MV_OK : MV_NOT_INITIALIZED;
+}
+
+
+int ddr3_pre_algo_config(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /* Set Bus3 ECC training mode */
+ if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) {
+ /* Set Bus3 ECC MUX */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ DRAM_PINS_MUX_REG, 0x100, 0x100));
+ }
+
+ /* Set regular ECC training mode (bus4 and bus 3) */
+ if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) ||
+ (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) ||
+ (DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))) {
+ /* Enable ECC Write MUX */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x100, 0x100));
+ /* General ECC enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, 0x40000, 0x40000));
+ /* Disable Read Data ECC MUX */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x0, 0x2));
+ }
+
+ return MV_OK;
+}
+
+int ddr3_post_algo_config(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ int status;
+
+ status = ddr3_post_run_alg();
+ if (MV_OK != status) {
+ printf("DDR3 Post Run Alg - FAILED 0x%x\n", status);
+ return status;
+ }
+
+ /* Un_set ECC training mode */
+ if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) ||
+ (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) ||
+ (DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))) {
+ /* Disable ECC Write MUX */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x0, 0x100));
+ /* General ECC and Bus3 ECC MUX remains enabled */
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Run Training Flow
+ */
+int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type)
+{
+ int status = MV_OK;
+
+ status = ddr3_pre_algo_config();
+ if (MV_OK != status) {
+ printf("DDR3 Pre Algo Config - FAILED 0x%x\n", status);
+ return status;
+ }
+
+#ifdef ODT_TEST_SUPPORT
+ if (finger_test == 1)
+ return odt_test(dev_num, algo_type);
+#endif
+
+ if (algo_type == ALGO_TYPE_DYNAMIC) {
+ status = ddr3_tip_ddr3_auto_tune(dev_num);
+ }
+
+ if (status != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("******** DRAM initialization Failed (res 0x%x) ********\n",
+ status));
+ return status;
+ }
+
+ status = ddr3_post_algo_config();
+ if (MV_OK != status) {
+ printf("DDR3 Post Algo Config - FAILED 0x%x\n", status);
+ return status;
+ }
+
+ return status;
+}
+
+#ifdef ODT_TEST_SUPPORT
+/*
+ * ODT Test
+ */
+static int odt_test(u32 dev_num, enum hws_algo_type algo_type)
+{
+ int ret = MV_OK, ret_tune = MV_OK;
+ int pfinger_val = 0, nfinger_val;
+
+ for (pfinger_val = p_finger_start; pfinger_val <= p_finger_end;
+ pfinger_val += p_finger_step) {
+ for (nfinger_val = n_finger_start; nfinger_val <= n_finger_end;
+ nfinger_val += n_finger_step) {
+ if (finger_test != 0) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("pfinger_val %d nfinger_val %d\n",
+ pfinger_val, nfinger_val));
+ /*
+ * TODO: need to check the correctness
+ * of the following two lines.
+ */
+ g_zpodt_data = pfinger_val;
+ g_znodt_data = nfinger_val;
+ }
+
+ if (algo_type == ALGO_TYPE_DYNAMIC) {
+ ret = ddr3_tip_ddr3_auto_tune(dev_num);
+ }
+ }
+ }
+
+ if (ret_tune != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Run_alg: tuning failed %d\n", ret_tune));
+ ret = (ret == MV_OK) ? ret_tune : ret;
+ }
+
+ return ret;
+}
+#endif
+
+/*
+ * Select Controller
+ */
+int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable)
+{
+ return config_func_info[dev_num].
+ tip_dunit_mux_select_func((u8)dev_num, enable);
+}
+
+/*
+ * Dunit Register Write
+ */
+int ddr3_tip_if_write(u32 dev_num, enum hws_access_type interface_access,
+ u32 if_id, u32 reg_addr, u32 data_value, u32 mask)
+{
+ config_func_info[dev_num].mv_ddr_dunit_write(reg_addr, mask, data_value);
+
+ return MV_OK;
+}
+
+/*
+ * Dunit Register Read
+ */
+int ddr3_tip_if_read(u32 dev_num, enum hws_access_type interface_access,
+ u32 if_id, u32 reg_addr, u32 *data, u32 mask)
+{
+ config_func_info[dev_num].mv_ddr_dunit_read(reg_addr, mask, data);
+
+ return MV_OK;
+}
+
+/*
+ * Dunit Register Polling
+ */
+int ddr3_tip_if_polling(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, u32 exp_value, u32 mask, u32 offset,
+ u32 poll_tries)
+{
+ u32 poll_cnt = 0, interface_num = 0, start_if, end_if;
+ u32 read_data[MAX_INTERFACE_NUM];
+ int ret;
+ int is_fail = 0, is_if_fail;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (access_type == ACCESS_TYPE_MULTICAST) {
+ start_if = 0;
+ end_if = MAX_INTERFACE_NUM - 1;
+ } else {
+ start_if = if_id;
+ end_if = if_id;
+ }
+
+ for (interface_num = start_if; interface_num <= end_if; interface_num++) {
+ /* polling bit 3 for n times */
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num);
+
+ is_if_fail = 0;
+ for (poll_cnt = 0; poll_cnt < poll_tries; poll_cnt++) {
+ ret =
+ ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST,
+ interface_num, offset, read_data,
+ mask);
+ if (ret != MV_OK)
+ return ret;
+
+ if (read_data[interface_num] == exp_value)
+ break;
+ }
+
+ if (poll_cnt >= poll_tries) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("max poll IF #%d\n", interface_num));
+ is_fail = 1;
+ is_if_fail = 1;
+ }
+
+ training_result[training_stage][interface_num] =
+ (is_if_fail == 1) ? TEST_FAILED : TEST_SUCCESS;
+ }
+
+ return (is_fail == 0) ? MV_OK : MV_FAIL;
+}
+
+/*
+ * Bus read access
+ */
+int ddr3_tip_bus_read(u32 dev_num, u32 if_id,
+ enum hws_access_type phy_access, u32 phy_id,
+ enum hws_ddr_phy phy_type, u32 reg_addr, u32 *data)
+{
+ return config_func_info[dev_num].
+ mv_ddr_phy_read(phy_access, phy_id, phy_type, reg_addr, data);
+}
+
+/*
+ * Bus write access
+ */
+int ddr3_tip_bus_write(u32 dev_num, enum hws_access_type interface_access,
+ u32 if_id, enum hws_access_type phy_access,
+ u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr,
+ u32 data_value)
+{
+ return config_func_info[dev_num].
+ mv_ddr_phy_write(phy_access, phy_id, phy_type, reg_addr, data_value, OPERATION_WRITE);
+}
+
+
+/*
+ * Phy read-modify-write
+ */
+int ddr3_tip_bus_read_modify_write(u32 dev_num, enum hws_access_type access_type,
+ u32 interface_id, u32 phy_id,
+ enum hws_ddr_phy phy_type, u32 reg_addr,
+ u32 data_value, u32 reg_mask)
+{
+ u32 data_val = 0, if_id, start_if, end_if;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (access_type == ACCESS_TYPE_MULTICAST) {
+ start_if = 0;
+ end_if = MAX_INTERFACE_NUM - 1;
+ } else {
+ start_if = interface_id;
+ end_if = interface_id;
+ }
+
+ for (if_id = start_if; if_id <= end_if; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST, phy_id,
+ phy_type, reg_addr, &data_val));
+ data_value = (data_val & (~reg_mask)) | (data_value & reg_mask);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, phy_type, reg_addr,
+ data_value));
+ }
+
+ return MV_OK;
+}
+
+/*
+ * ADLL Calibration
+ */
+int adll_calibration(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency)
+{
+ struct hws_tip_freq_config_info freq_config_info;
+ u32 bus_cnt = 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();
+
+ /* Reset Diver_b assert -> de-assert */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, SDRAM_CFG_REG,
+ 0, 0x10000000));
+ mdelay(10);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, SDRAM_CFG_REG,
+ 0x10000000, 0x10000000));
+
+ CHECK_STATUS(config_func_info[dev_num].
+ tip_get_freq_config_info_func((u8)dev_num, frequency,
+ &freq_config_info));
+
+ for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, access_type, if_id, bus_cnt,
+ DDR_PHY_DATA, ADLL_CFG0_PHY_REG,
+ freq_config_info.bw_per_freq << 8, 0x700));
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, access_type, if_id, bus_cnt,
+ DDR_PHY_DATA, ADLL_CFG2_PHY_REG,
+ freq_config_info.rate_per_freq, 0x7));
+ }
+
+ for (bus_cnt = 0; bus_cnt < DDR_IF_CTRL_SUBPHYS_NUM; bus_cnt++) {
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt,
+ DDR_PHY_CONTROL, ADLL_CFG0_PHY_REG,
+ freq_config_info.bw_per_freq << 8, 0x700));
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt,
+ DDR_PHY_CONTROL, ADLL_CFG2_PHY_REG,
+ freq_config_info.rate_per_freq, 0x7));
+ }
+
+ /* DUnit to Phy drive post edge, ADLL reset assert de-assert */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DRAM_PHY_CFG_REG,
+ 0, (0x80000000 | 0x40000000)));
+ mdelay(100 / (mv_ddr_freq_get(frequency)) / mv_ddr_freq_get(MV_DDR_FREQ_LOW_FREQ));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DRAM_PHY_CFG_REG,
+ (0x80000000 | 0x40000000), (0x80000000 | 0x40000000)));
+
+ /* polling for ADLL Done */
+ if (ddr3_tip_if_polling(dev_num, access_type, if_id,
+ 0x3ff03ff, 0x3ff03ff, PHY_LOCK_STATUS_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Freq_set: DDR3 poll failed(1)"));
+ }
+
+ /* pup data_pup reset assert-> deassert */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, SDRAM_CFG_REG,
+ 0, 0x60000000));
+ mdelay(10);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, SDRAM_CFG_REG,
+ 0x60000000, 0x60000000));
+
+ return MV_OK;
+}
+
+int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency)
+{
+ u32 cl_value = 0, cwl_value = 0, mem_mask = 0, val = 0,
+ bus_cnt = 0, t_wr = 0, t_ckclk = 0,
+ cnt_id;
+ u32 end_if, start_if;
+ u32 bus_index = 0;
+ int is_dll_off = 0;
+ enum mv_ddr_speed_bin speed_bin_index = 0;
+ struct hws_tip_freq_config_info freq_config_info;
+ enum hws_result *flow_result = training_result[training_stage];
+ u32 adll_tap = 0;
+ u32 cs_num;
+ u32 t2t;
+ u32 cs_mask[MAX_INTERFACE_NUM];
+ 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();
+ unsigned int tclk;
+ enum mv_ddr_timing timing = tm->interface_params[if_id].timing;
+ u32 freq = mv_ddr_freq_get(frequency);
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("dev %d access %d IF %d freq %d\n", dev_num,
+ access_type, if_id, frequency));
+
+ if (frequency == MV_DDR_FREQ_LOW_FREQ)
+ is_dll_off = 1;
+ if (access_type == ACCESS_TYPE_MULTICAST) {
+ start_if = 0;
+ end_if = MAX_INTERFACE_NUM - 1;
+ } else {
+ start_if = if_id;
+ end_if = if_id;
+ }
+
+ /* calculate interface cs mask - Oferb 4/11 */
+ /* speed bin can be different for each interface */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ /* cs enable is active low */
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ cs_mask[if_id] = CS_BIT_MASK;
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+ ddr3_tip_calc_cs_mask(dev_num, if_id, effective_cs,
+ &cs_mask[if_id]);
+ }
+
+ /* speed bin can be different for each interface */
+ /*
+ * moti b - need to remove the loop for multicas access functions
+ * and loop the unicast access functions
+ */
+ for (if_id = start_if; if_id <= end_if; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ flow_result[if_id] = TEST_SUCCESS;
+ speed_bin_index =
+ tm->interface_params[if_id].speed_bin_index;
+ if (tm->interface_params[if_id].memory_freq ==
+ frequency) {
+ cl_value =
+ tm->interface_params[if_id].cas_l;
+ cwl_value =
+ tm->interface_params[if_id].cas_wl;
+ } else if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ tclk = 1000000 / freq;
+ cl_value = mv_ddr_cl_calc(tm->timing_data[MV_DDR_TAA_MIN], tclk);
+ if (cl_value == 0) {
+ printf("mv_ddr: unsupported cas latency value found\n");
+ return MV_FAIL;
+ }
+ cwl_value = mv_ddr_cwl_calc(tclk);
+ if (cwl_value == 0) {
+ printf("mv_ddr: unsupported cas write latency value found\n");
+ return MV_FAIL;
+ }
+ } else {
+ cl_value = mv_ddr_cl_val_get(speed_bin_index, frequency);
+ cwl_value = mv_ddr_cwl_val_get(speed_bin_index, frequency);
+ }
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("Freq_set dev 0x%x access 0x%x if 0x%x freq 0x%x speed %d:\n\t",
+ dev_num, access_type, if_id,
+ frequency, speed_bin_index));
+
+ for (cnt_id = 0; cnt_id < MV_DDR_FREQ_LAST; cnt_id++) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
+ ("%d ", mv_ddr_cl_val_get(speed_bin_index, cnt_id)));
+ }
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("\n"));
+ mem_mask = 0;
+ for (bus_index = 0; bus_index < octets_per_if_num;
+ bus_index++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index);
+ mem_mask |=
+ tm->interface_params[if_id].
+ as_bus_params[bus_index].mirror_enable_bitmask;
+ }
+
+ if (mem_mask != 0) {
+ /* motib redundent in KW28 */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type,
+ if_id,
+ DUAL_DUNIT_CFG_REG, 0, 0x8));
+ }
+
+ /* dll state after exiting SR */
+ if (is_dll_off == 1) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DFS_REG, 0x1, 0x1));
+ } else {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DFS_REG, 0, 0x1));
+ }
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DUNIT_MMASK_REG, 0, 0x1));
+ /* DFS - block transactions */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DFS_REG, 0x2, 0x2));
+
+ /* disable ODT in case of dll off */
+ if (is_dll_off == 1) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1874, 0, 0x244));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1884, 0, 0x244));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1894, 0, 0x244));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x18a4, 0, 0x244));
+ }
+
+ /* DFS - Enter Self-Refresh */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DFS_REG, 0x4,
+ 0x4));
+ /* polling on self refresh entry */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST,
+ if_id, 0x8, 0x8, DFS_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Freq_set: DDR3 poll failed on SR entry\n"));
+ }
+
+ /* Calculate 2T mode */
+ if (mode_2t != 0xff) {
+ t2t = mode_2t;
+ } else if (timing != MV_DDR_TIM_DEFAULT) {
+ t2t = (timing == MV_DDR_TIM_2T) ? 1 : 0;
+ } else {
+ /* Calculate number of CS per interface */
+ cs_num = mv_ddr_cs_num_get();
+ t2t = (cs_num == 1) ? 0 : 1;
+ }
+
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_INTERLEAVE_WA) == 1) {
+ /* Use 1T mode if 1:1 ratio configured */
+ if (config_func_info[dev_num].tip_get_clock_ratio(frequency) == 1) {
+ /* Low freq*/
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_OPEN_PAGES_CTRL_REG, 0x0, 0x3C0));
+ t2t = 0;
+ } else {
+ /* Middle or target freq */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_OPEN_PAGES_CTRL_REG, 0x3C0, 0x3C0));
+ }
+ }
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DUNIT_CTRL_LOW_REG, t2t << 3, 0x3 << 3));
+
+ /* PLL configuration */
+ config_func_info[dev_num].tip_set_freq_divider_func(dev_num, if_id,
+ frequency);
+
+ /* DFS - CL/CWL/WR parameters after exiting SR */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DFS_REG,
+ (cl_mask_table[cl_value] << 8), 0xf00));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DFS_REG,
+ (cwl_mask_table[cwl_value] << 12), 0x7000));
+
+ t_ckclk = (MEGA / freq);
+ t_wr = time_to_nclk(mv_ddr_speed_bin_timing_get
+ (speed_bin_index,
+ SPEED_BIN_TWR), t_ckclk);
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DFS_REG,
+ (twr_mask_table[t_wr] << 16), 0x70000));
+
+ /* Restore original RTT values if returning from DLL OFF mode */
+ if (is_dll_off == 1) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, 0x1874,
+ g_dic | g_rtt_nom, 0x266));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, 0x1884,
+ g_dic | g_rtt_nom, 0x266));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, 0x1894,
+ g_dic | g_rtt_nom, 0x266));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, 0x18a4,
+ g_dic | g_rtt_nom, 0x266));
+ }
+
+ /* Reset divider_b assert -> de-assert */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_CFG_REG, 0, 0x10000000));
+ mdelay(10);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_CFG_REG, 0x10000000, 0x10000000));
+
+ /* ADLL configuration function of process and frequency */
+ CHECK_STATUS(config_func_info[dev_num].
+ tip_get_freq_config_info_func(dev_num, frequency,
+ &freq_config_info));
+
+ /* TBD check milo5 using device ID ? */
+ for (bus_cnt = 0; bus_cnt < octets_per_if_num;
+ bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, bus_cnt, DDR_PHY_DATA,
+ 0x92,
+ freq_config_info.
+ bw_per_freq << 8
+ /*freq_mask[dev_num][frequency] << 8 */
+ , 0x700));
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ bus_cnt, DDR_PHY_DATA, 0x94,
+ freq_config_info.rate_per_freq, 0x7));
+ }
+
+ /* Dunit to PHY drive post edge, ADLL reset assert -> de-assert */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DRAM_PHY_CFG_REG, 0,
+ (0x80000000 | 0x40000000)));
+ mdelay(100 / (freq / mv_ddr_freq_get(MV_DDR_FREQ_LOW_FREQ)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ DRAM_PHY_CFG_REG, (0x80000000 | 0x40000000),
+ (0x80000000 | 0x40000000)));
+
+ /* polling for ADLL Done */
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x3ff03ff,
+ 0x3ff03ff, PHY_LOCK_STATUS_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Freq_set: DDR3 poll failed(1)\n"));
+ }
+
+ /* pup data_pup reset assert-> deassert */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_CFG_REG, 0, 0x60000000));
+ mdelay(10);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_CFG_REG, 0x60000000, 0x60000000));
+
+ /* Set proper timing params before existing Self-Refresh */
+ ddr3_tip_set_timing(dev_num, access_type, if_id, frequency);
+ if (delay_enable != 0) {
+ adll_tap = (is_dll_off == 1) ? 1000 : (MEGA / (freq * 64));
+ ddr3_tip_cmd_addr_init_delay(dev_num, adll_tap);
+ }
+
+ /* Exit SR */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DFS_REG, 0,
+ 0x4));
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x8, DFS_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Freq_set: DDR3 poll failed(2)"));
+ }
+
+ /* Refresh Command */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ SDRAM_OP_REG, 0x2, 0xf1f));
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f,
+ SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Freq_set: DDR3 poll failed(3)"));
+ }
+
+ /* Release DFS Block */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DFS_REG, 0,
+ 0x2));
+ /* Controller to MBUS Retry - normal */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, DUNIT_MMASK_REG,
+ 0x1, 0x1));
+
+ /* MRO: Burst Length 8, CL , Auto_precharge 0x16cc */
+ val =
+ ((cl_mask_table[cl_value] & 0x1) << 2) |
+ ((cl_mask_table[cl_value] & 0xe) << 3);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id, MR0_REG,
+ val, (0x7 << 4) | (1 << 2)));
+ /* MR2: CWL = 10 , Auto Self-Refresh - disable */
+ val = (cwl_mask_table[cwl_value] << 3) | g_rtt_wr;
+ /*
+ * nklein 24.10.13 - should not be here - leave value as set in
+ * the init configuration val |= (1 << 9);
+ * val |= ((tm->interface_params[if_id].
+ * interface_temp == MV_DDR_TEMP_HIGH) ? (1 << 7) : 0);
+ */
+ /* nklein 24.10.13 - see above comment */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type,
+ if_id, MR2_REG,
+ val, (0x7 << 3) | (0x3 << 9)));
+
+ /* ODT TIMING */
+ val = ((cl_value - cwl_value + 1) << 4) |
+ ((cl_value - cwl_value + 6) << 8) |
+ ((cl_value - 1) << 12) | ((cl_value + 6) << 16);
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type,
+ if_id, DDR_ODT_TIMING_LOW_REG,
+ val, 0xffff0));
+ val = 0x91 | ((cwl_value - 1) << 8) | ((cwl_value + 5) << 12);
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type,
+ if_id, DDR_ODT_TIMING_HIGH_REG,
+ val, 0xffff));
+
+ /* in case of ddr4 need to set the receiver to odt always 'on' (odt_config = '0')
+ * in case of ddr3 configure the odt through the timing
+ */
+ if (odt_config != 0) {
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DUNIT_ODT_CTRL_REG, 0xf, 0xf));
+ }
+ else {
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DUNIT_ODT_CTRL_REG,
+ 0x30f, 0x30f));
+ }
+
+ /* re-write CL */
+ val = ((cl_mask_table[cl_value] & 0x1) << 2) |
+ ((cl_mask_table[cl_value] & 0xe) << 3);
+
+ cs_mask[0] = 0xc;
+
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MR_CMD0,
+ val, (0x7 << 4) | (0x1 << 2)));
+
+ /* re-write CWL */
+ val = (cwl_mask_table[cwl_value] << 3) | g_rtt_wr;
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MR_CMD2,
+ val, (0x7 << 3) | (0x3 << 9)));
+
+ if (mem_mask != 0) {
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type,
+ if_id,
+ DUAL_DUNIT_CFG_REG,
+ 1 << 3, 0x8));
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Set ODT values
+ */
+static int ddr3_tip_write_odt(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, u32 cl_value, u32 cwl_value)
+{
+ /* ODT TIMING */
+ u32 val = (cl_value - cwl_value + 6);
+
+ val = ((cl_value - cwl_value + 1) << 4) | ((val & 0xf) << 8) |
+ (((cl_value - 1) & 0xf) << 12) |
+ (((cl_value + 6) & 0xf) << 16) | (((val & 0x10) >> 4) << 21);
+ val |= (((cl_value - 1) >> 4) << 22) | (((cl_value + 6) >> 4) << 23);
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DDR_ODT_TIMING_LOW_REG, val, 0xffff0));
+ val = 0x91 | ((cwl_value - 1) << 8) | ((cwl_value + 5) << 12);
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DDR_ODT_TIMING_HIGH_REG, val, 0xffff));
+ if (odt_additional == 1) {
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type,
+ if_id,
+ SDRAM_ODT_CTRL_HIGH_REG,
+ 0xf, 0xf));
+ }
+
+ /* ODT Active */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DUNIT_ODT_CTRL_REG, 0xf, 0xf));
+
+ return MV_OK;
+}
+
+/*
+ * Set Timing values for training
+ */
+static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency)
+{
+ u32 t_ckclk = 0, t_ras = 0;
+ u32 t_rcd = 0, t_rp = 0, t_wr = 0, t_wtr = 0, t_rrd = 0, t_rtp = 0,
+ t_rfc = 0, t_mod = 0, t_r2r = 0x3, t_r2r_high = 0,
+ t_r2w_w2r = 0x3, t_r2w_w2r_high = 0x1, t_w2w = 0x3;
+ u32 refresh_interval_cnt, t_hclk, t_refi, t_faw, t_pd, t_xpdll;
+ u32 val = 0, page_size = 0, mask = 0;
+ enum mv_ddr_speed_bin speed_bin_index;
+ enum mv_ddr_die_capacity memory_size = MV_DDR_DIE_CAP_2GBIT;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 freq = mv_ddr_freq_get(frequency);
+
+ speed_bin_index = tm->interface_params[if_id].speed_bin_index;
+ memory_size = tm->interface_params[if_id].memory_size;
+ page_size = mv_ddr_page_size_get(tm->interface_params[if_id].bus_width, memory_size);
+ t_ckclk = (MEGA / freq);
+ /* HCLK in[ps] */
+ t_hclk = MEGA / (freq / config_func_info[dev_num].tip_get_clock_ratio(frequency));
+
+ t_refi = (tm->interface_params[if_id].interface_temp == MV_DDR_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW;
+ t_refi *= 1000; /* psec */
+ refresh_interval_cnt = t_refi / t_hclk; /* no units */
+
+ if (page_size == 1) {
+ t_faw = mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TFAW1K);
+ t_faw = time_to_nclk(t_faw, t_ckclk);
+ t_faw = GET_MAX_VALUE(20, t_faw);
+ } else { /* page size =2, we do not support page size 0.5k */
+ t_faw = mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TFAW2K);
+ t_faw = time_to_nclk(t_faw, t_ckclk);
+ t_faw = GET_MAX_VALUE(28, t_faw);
+ }
+
+ t_pd = GET_MAX_VALUE(t_ckclk * 3, mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TPD));
+ t_pd = time_to_nclk(t_pd, t_ckclk);
+
+ t_xpdll = GET_MAX_VALUE(t_ckclk * 10, mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TXPDLL));
+ t_xpdll = time_to_nclk(t_xpdll, t_ckclk);
+
+ t_rrd = (page_size == 1) ? mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TRRD1K) :
+ mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TRRD2K);
+ t_rrd = GET_MAX_VALUE(t_ckclk * 4, t_rrd);
+ t_rtp = GET_MAX_VALUE(t_ckclk * 4, mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TRTP));
+ t_mod = GET_MAX_VALUE(t_ckclk * 12, 15000);
+ t_wtr = GET_MAX_VALUE(t_ckclk * 4, mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TWTR));
+ t_ras = time_to_nclk(mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TRAS),
+ t_ckclk);
+ t_rcd = time_to_nclk(mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TRCD),
+ t_ckclk);
+ t_rp = time_to_nclk(mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TRP),
+ t_ckclk);
+ t_wr = time_to_nclk(mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TWR),
+ t_ckclk);
+ t_wtr = time_to_nclk(t_wtr, t_ckclk);
+ t_rrd = time_to_nclk(t_rrd, t_ckclk);
+ t_rtp = time_to_nclk(t_rtp, t_ckclk);
+ t_rfc = time_to_nclk(mv_ddr_rfc_get(memory_size) * 1000, t_ckclk);
+ t_mod = time_to_nclk(t_mod, t_ckclk);
+
+ /* SDRAM Timing Low */
+ val = (((t_ras - 1) & SDRAM_TIMING_LOW_TRAS_MASK) << SDRAM_TIMING_LOW_TRAS_OFFS) |
+ (((t_rcd - 1) & SDRAM_TIMING_LOW_TRCD_MASK) << SDRAM_TIMING_LOW_TRCD_OFFS) |
+ (((t_rcd - 1) >> SDRAM_TIMING_LOW_TRCD_OFFS & SDRAM_TIMING_HIGH_TRCD_MASK)
+ << SDRAM_TIMING_HIGH_TRCD_OFFS) |
+ (((t_rp - 1) & SDRAM_TIMING_LOW_TRP_MASK) << SDRAM_TIMING_LOW_TRP_OFFS) |
+ (((t_rp - 1) >> SDRAM_TIMING_LOW_TRP_MASK & SDRAM_TIMING_HIGH_TRP_MASK)
+ << SDRAM_TIMING_HIGH_TRP_OFFS) |
+ (((t_wr - 1) & SDRAM_TIMING_LOW_TWR_MASK) << SDRAM_TIMING_LOW_TWR_OFFS) |
+ (((t_wtr - 1) & SDRAM_TIMING_LOW_TWTR_MASK) << SDRAM_TIMING_LOW_TWTR_OFFS) |
+ ((((t_ras - 1) >> 4) & SDRAM_TIMING_LOW_TRAS_HIGH_MASK) << SDRAM_TIMING_LOW_TRAS_HIGH_OFFS) |
+ (((t_rrd - 1) & SDRAM_TIMING_LOW_TRRD_MASK) << SDRAM_TIMING_LOW_TRRD_OFFS) |
+ (((t_rtp - 1) & SDRAM_TIMING_LOW_TRTP_MASK) << SDRAM_TIMING_LOW_TRTP_OFFS);
+
+ mask = (SDRAM_TIMING_LOW_TRAS_MASK << SDRAM_TIMING_LOW_TRAS_OFFS) |
+ (SDRAM_TIMING_LOW_TRCD_MASK << SDRAM_TIMING_LOW_TRCD_OFFS) |
+ (SDRAM_TIMING_HIGH_TRCD_MASK << SDRAM_TIMING_HIGH_TRCD_OFFS) |
+ (SDRAM_TIMING_LOW_TRP_MASK << SDRAM_TIMING_LOW_TRP_OFFS) |
+ (SDRAM_TIMING_HIGH_TRP_MASK << SDRAM_TIMING_HIGH_TRP_OFFS) |
+ (SDRAM_TIMING_LOW_TWR_MASK << SDRAM_TIMING_LOW_TWR_OFFS) |
+ (SDRAM_TIMING_LOW_TWTR_MASK << SDRAM_TIMING_LOW_TWTR_OFFS) |
+ (SDRAM_TIMING_LOW_TRAS_HIGH_MASK << SDRAM_TIMING_LOW_TRAS_HIGH_OFFS) |
+ (SDRAM_TIMING_LOW_TRRD_MASK << SDRAM_TIMING_LOW_TRRD_OFFS) |
+ (SDRAM_TIMING_LOW_TRTP_MASK << SDRAM_TIMING_LOW_TRTP_OFFS);
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_TIMING_LOW_REG, val, mask));
+
+ /* SDRAM Timing High */
+ val = 0;
+ mask = 0;
+
+ val = (((t_rfc - 1) & SDRAM_TIMING_HIGH_TRFC_MASK) << SDRAM_TIMING_HIGH_TRFC_OFFS) |
+ ((t_r2r & SDRAM_TIMING_HIGH_TR2R_MASK) << SDRAM_TIMING_HIGH_TR2R_OFFS) |
+ ((t_r2w_w2r & SDRAM_TIMING_HIGH_TR2W_W2R_MASK) << SDRAM_TIMING_HIGH_TR2W_W2R_OFFS) |
+ ((t_w2w & SDRAM_TIMING_HIGH_TW2W_MASK) << SDRAM_TIMING_HIGH_TW2W_OFFS) |
+ ((((t_rfc - 1) >> 7) & SDRAM_TIMING_HIGH_TRFC_HIGH_MASK) << SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS) |
+ ((t_r2r_high & SDRAM_TIMING_HIGH_TR2R_HIGH_MASK) << SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS) |
+ ((t_r2w_w2r_high & SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK) << SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS) |
+ (((t_mod - 1) & SDRAM_TIMING_HIGH_TMOD_MASK) << SDRAM_TIMING_HIGH_TMOD_OFFS) |
+ ((((t_mod - 1) >> 4) & SDRAM_TIMING_HIGH_TMOD_HIGH_MASK) << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS);
+
+ mask = (SDRAM_TIMING_HIGH_TRFC_MASK << SDRAM_TIMING_HIGH_TRFC_OFFS) |
+ (SDRAM_TIMING_HIGH_TR2R_MASK << SDRAM_TIMING_HIGH_TR2R_OFFS) |
+ (SDRAM_TIMING_HIGH_TR2W_W2R_MASK << SDRAM_TIMING_HIGH_TR2W_W2R_OFFS) |
+ (SDRAM_TIMING_HIGH_TW2W_MASK << SDRAM_TIMING_HIGH_TW2W_OFFS) |
+ (SDRAM_TIMING_HIGH_TRFC_HIGH_MASK << SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS) |
+ (SDRAM_TIMING_HIGH_TR2R_HIGH_MASK << SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS) |
+ (SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK << SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS) |
+ (SDRAM_TIMING_HIGH_TMOD_MASK << SDRAM_TIMING_HIGH_TMOD_OFFS) |
+ (SDRAM_TIMING_HIGH_TMOD_HIGH_MASK << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS);
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_TIMING_HIGH_REG, val, mask));
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_CFG_REG,
+ refresh_interval_cnt << REFRESH_OFFS,
+ REFRESH_MASK << REFRESH_OFFS));
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_ADDR_CTRL_REG, (t_faw - 1) << T_FAW_OFFS,
+ T_FAW_MASK << T_FAW_OFFS));
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DDR_TIMING_REG,
+ (t_pd - 1) << DDR_TIMING_TPD_OFFS |
+ (t_xpdll - 1) << DDR_TIMING_TXPDLL_OFFS,
+ DDR_TIMING_TPD_MASK << DDR_TIMING_TPD_OFFS |
+ DDR_TIMING_TXPDLL_MASK << DDR_TIMING_TXPDLL_OFFS));
+
+
+ return MV_OK;
+}
+
+
+/*
+ * Write CS Result
+ */
+int ddr3_tip_write_cs_result(u32 dev_num, u32 offset)
+{
+ u32 if_id, bus_num, cs_bitmask, data_val, cs_num;
+ 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_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_num = 0; bus_num < octets_per_if_num;
+ bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num);
+ cs_bitmask =
+ tm->interface_params[if_id].
+ as_bus_params[bus_num].cs_bitmask;
+ if (cs_bitmask != effective_cs) {
+ cs_num = GET_CS_FROM_MASK(cs_bitmask);
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_num,
+ DDR_PHY_DATA,
+ offset +
+ (effective_cs * 0x4),
+ &data_val);
+ ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_num, DDR_PHY_DATA,
+ offset +
+ (cs_num * 0x4),
+ data_val);
+ }
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Write MRS
+ */
+int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, enum mr_number mr_num, u32 data, u32 mask)
+{
+ u32 if_id;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, mr_data[mr_num].reg_addr, data, mask));
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; 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_OP_REG,
+ (cs_mask_arr[if_id] << 8) | mr_data[mr_num].cmd, 0xf1f));
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0,
+ 0x1f, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("write_mrs_cmd: Poll cmd fail"));
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Reset XSB Read FIFO
+ */
+int ddr3_tip_reset_fifo_ptr(u32 dev_num)
+{
+ u32 if_id = 0;
+
+ /* Configure PHY reset value to 0 in order to "clean" the FIFO */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, 0x15c8, 0, 0xff000000));
+ /*
+ * Move PHY to RL mode (only in RL mode the PHY overrides FIFO values
+ * during FIFO reset)
+ */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, TRAINING_SW_2_REG,
+ 0x1, 0x9));
+ /* In order that above configuration will influence the PHY */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, 0x15b0,
+ 0x80000000, 0x80000000));
+ /* Reset read fifo assertion */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, 0x1400, 0, 0x40000000));
+ /* Reset read fifo deassertion */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, 0x1400,
+ 0x40000000, 0x40000000));
+ /* Move PHY back to functional mode */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, TRAINING_SW_2_REG,
+ 0x8, 0x9));
+ /* Stop training machine */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, 0x15b4, 0x10000, 0x10000));
+
+ return MV_OK;
+}
+
+/*
+ * Reset Phy registers
+ */
+int ddr3_tip_ddr3_reset_phy_regs(u32 dev_num)
+{
+ u32 if_id, phy_id, cs;
+ 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_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (phy_id = 0; phy_id < octets_per_if_num;
+ phy_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST,
+ phy_id, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs),
+ phy_reg0_val));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ RL_PHY_REG(effective_cs),
+ phy_reg2_val));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ CRX_PHY_REG(effective_cs), phy_reg3_val));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs), phy_reg1_val));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_TX_BCAST_PHY_REG(effective_cs), 0x0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_RX_BCAST_PHY_REG(effective_cs), 0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(effective_cs, DQSP_PAD), 0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, DQSP_PAD), 0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(effective_cs, DQSN_PAD), 0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, DQSN_PAD), 0));
+ }
+ }
+
+ /* Set Receiver Calibration value */
+ for (cs = 0; cs < MAX_CS_NUM; cs++) {
+ /* PHY register 0xdb bits[5:0] - configure to 63 */
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR_PHY_DATA, VREF_BCAST_PHY_REG(cs), 63));
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Restore Dunit registers
+ */
+int ddr3_tip_restore_dunit_regs(u32 dev_num)
+{
+ u32 index_cnt;
+
+ mv_ddr_set_calib_controller();
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ 0x1, 0x1));
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ calibration_update_control << 3,
+ 0x3 << 3));
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ ODPG_WR_RD_MODE_ENA_REG,
+ 0xffff, MASK_ALL_BITS));
+
+ for (index_cnt = 0; index_cnt < ARRAY_SIZE(odpg_default_value);
+ index_cnt++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ odpg_default_value[index_cnt].reg_addr,
+ odpg_default_value[index_cnt].reg_data,
+ odpg_default_value[index_cnt].reg_mask));
+ }
+
+ return MV_OK;
+}
+
+int ddr3_tip_adll_regs_bypass(u32 dev_num, u32 reg_val1, u32 reg_val2)
+{
+ u32 if_id, phy_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();
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (phy_id = 0; phy_id < octets_per_if_num; phy_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs), reg_val1));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA,
+ PBS_TX_BCAST_PHY_REG(effective_cs), reg_val2));
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Auto tune main flow
+ */
+static int ddr3_tip_ddr3_training_main_flow(u32 dev_num)
+{
+/* TODO: enable this functionality for other platforms */
+ struct init_cntr_param init_cntr_prm;
+ int ret = MV_OK;
+ int adll_bypass_flag = 0;
+ u32 if_id;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum mv_ddr_freq freq = tm->interface_params[0].memory_freq;
+ unsigned int *freq_tbl = mv_ddr_freq_tbl_get();
+
+#ifdef DDR_VIEWER_TOOL
+ if (debug_training == DEBUG_LEVEL_TRACE) {
+ CHECK_STATUS(print_device_info((u8)dev_num));
+ }
+#endif
+
+ ddr3_tip_validate_algo_components(dev_num);
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ CHECK_STATUS(ddr3_tip_ddr3_reset_phy_regs(dev_num));
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ freq_tbl[MV_DDR_FREQ_LOW_FREQ] = dfs_low_freq;
+
+ if (is_pll_before_init != 0) {
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ config_func_info[dev_num].tip_set_freq_divider_func(
+ (u8)dev_num, if_id, freq);
+ }
+ }
+
+/* TODO: enable this functionality for other platforms */
+ if (is_adll_calib_before_init != 0) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("with adll calib before init\n"));
+ adll_calibration(dev_num, ACCESS_TYPE_MULTICAST, 0, freq);
+ }
+
+ if (is_reg_dump != 0) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("Dump before init controller\n"));
+ ddr3_tip_reg_dump(dev_num);
+ }
+
+ if (mask_tune_func & INIT_CONTROLLER_MASK_BIT) {
+ training_stage = INIT_CONTROLLER;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("INIT_CONTROLLER_MASK_BIT\n"));
+ init_cntr_prm.do_mrs_phy = 1;
+ init_cntr_prm.is_ctrl64_bit = 0;
+ init_cntr_prm.init_phy = 1;
+ init_cntr_prm.msys_init = 0;
+ ret = hws_ddr3_tip_init_controller(dev_num, &init_cntr_prm);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("hws_ddr3_tip_init_controller failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ ret = adll_calibration(dev_num, ACCESS_TYPE_MULTICAST, 0, freq);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("adll_calibration failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+
+ if (mask_tune_func & SET_LOW_FREQ_MASK_BIT) {
+ training_stage = SET_LOW_FREQ;
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ ddr3_tip_adll_regs_bypass(dev_num, 0, 0x1f);
+ adll_bypass_flag = 1;
+ }
+ effective_cs = 0;
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("SET_LOW_FREQ_MASK_BIT %d\n",
+ freq_tbl[low_freq]));
+ ret = ddr3_tip_freq_set(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, low_freq);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_freq_set failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & WRITE_LEVELING_LF_MASK_BIT) {
+ training_stage = WRITE_LEVELING_LF;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("WRITE_LEVELING_LF_MASK_BIT\n"));
+ ret = ddr3_tip_dynamic_write_leveling(dev_num, 1);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_write_leveling LF failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & LOAD_PATTERN_MASK_BIT) {
+ training_stage = LOAD_PATTERN;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("LOAD_PATTERN_MASK_BIT #%d\n",
+ effective_cs));
+ ret = ddr3_tip_load_all_pattern_to_mem(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_load_all_pattern_to_mem failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+
+ if (adll_bypass_flag == 1) {
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ ddr3_tip_adll_regs_bypass(dev_num, phy_reg1_val, 0);
+ adll_bypass_flag = 0;
+ }
+ }
+
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ if (mask_tune_func & SET_MEDIUM_FREQ_MASK_BIT) {
+ training_stage = SET_MEDIUM_FREQ;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("SET_MEDIUM_FREQ_MASK_BIT %d\n",
+ freq_tbl[medium_freq]));
+ ret =
+ ddr3_tip_freq_set(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, medium_freq);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_freq_set failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & WRITE_LEVELING_MASK_BIT) {
+ training_stage = WRITE_LEVELING;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("WRITE_LEVELING_MASK_BIT\n"));
+ if ((rl_mid_freq_wa == 0) || (freq_tbl[medium_freq] == 533)) {
+ ret = ddr3_tip_dynamic_write_leveling(dev_num, 0);
+ } else {
+ /* Use old WL */
+ ret = ddr3_tip_legacy_dynamic_write_leveling(dev_num);
+ }
+
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_write_leveling failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & LOAD_PATTERN_2_MASK_BIT) {
+ training_stage = LOAD_PATTERN_2;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("LOAD_PATTERN_2_MASK_BIT CS #%d\n",
+ effective_cs));
+ ret = ddr3_tip_load_all_pattern_to_mem(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_load_all_pattern_to_mem failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ if (mask_tune_func & READ_LEVELING_MASK_BIT) {
+ training_stage = READ_LEVELING;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("READ_LEVELING_MASK_BIT\n"));
+ if ((rl_mid_freq_wa == 0) || (freq_tbl[medium_freq] == 533)) {
+ ret = ddr3_tip_dynamic_read_leveling(dev_num, medium_freq);
+ } else {
+ /* Use old RL */
+ ret = ddr3_tip_legacy_dynamic_read_leveling(dev_num);
+ }
+
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_read_leveling failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & WRITE_LEVELING_SUPP_MASK_BIT) {
+ training_stage = WRITE_LEVELING_SUPP;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("WRITE_LEVELING_SUPP_MASK_BIT\n"));
+ ret = ddr3_tip_dynamic_write_leveling_supp(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_write_leveling_supp failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & PBS_RX_MASK_BIT) {
+ training_stage = PBS_RX;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("PBS_RX_MASK_BIT CS #%d\n",
+ effective_cs));
+ ret = ddr3_tip_pbs_rx(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_pbs_rx failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & PBS_TX_MASK_BIT) {
+ training_stage = PBS_TX;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("PBS_TX_MASK_BIT CS #%d\n",
+ effective_cs));
+ ret = ddr3_tip_pbs_tx(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_pbs_tx failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ if (mask_tune_func & SET_TARGET_FREQ_MASK_BIT) {
+ training_stage = SET_TARGET_FREQ;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("SET_TARGET_FREQ_MASK_BIT %d\n",
+ freq_tbl[tm->
+ interface_params[first_active_if].
+ memory_freq]));
+ ret = ddr3_tip_freq_set(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ tm->interface_params[first_active_if].
+ memory_freq);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_freq_set failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & WRITE_LEVELING_TF_MASK_BIT) {
+ training_stage = WRITE_LEVELING_TF;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("WRITE_LEVELING_TF_MASK_BIT\n"));
+ ret = ddr3_tip_dynamic_write_leveling(dev_num, 0);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_write_leveling TF failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & LOAD_PATTERN_HIGH_MASK_BIT) {
+ training_stage = LOAD_PATTERN_HIGH;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("LOAD_PATTERN_HIGH\n"));
+ ret = ddr3_tip_load_all_pattern_to_mem(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_load_all_pattern_to_mem failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & READ_LEVELING_TF_MASK_BIT) {
+ training_stage = READ_LEVELING_TF;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("READ_LEVELING_TF_MASK_BIT\n"));
+ ret = ddr3_tip_dynamic_read_leveling(dev_num, tm->
+ interface_params[first_active_if].
+ memory_freq);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_read_leveling TF failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & RL_DQS_BURST_MASK_BIT) {
+ training_stage = READ_LEVELING_TF;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("RL_DQS_BURST_MASK_BIT\n"));
+ ret = mv_ddr_rl_dqs_burst(0, 0, tm->interface_params[0].memory_freq);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr_rl_dqs_burst TF failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ if (mask_tune_func & DM_PBS_TX_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DM_PBS_TX_MASK_BIT\n"));
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & VREF_CALIBRATION_MASK_BIT) {
+ training_stage = VREF_CALIBRATION;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("VREF\n"));
+ ret = ddr3_tip_vref(dev_num);
+ if (is_reg_dump != 0) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("VREF Dump\n"));
+ ddr3_tip_reg_dump(dev_num);
+ }
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_vref failure\n"));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & CENTRALIZATION_RX_MASK_BIT) {
+ training_stage = CENTRALIZATION_RX;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("CENTRALIZATION_RX_MASK_BIT CS #%d\n",
+ effective_cs));
+ ret = ddr3_tip_centralization_rx(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_centralization_rx failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & WRITE_LEVELING_SUPP_TF_MASK_BIT) {
+ training_stage = WRITE_LEVELING_SUPP_TF;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("WRITE_LEVELING_SUPP_TF_MASK_BIT CS #%d\n",
+ effective_cs));
+ ret = ddr3_tip_dynamic_write_leveling_supp(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_dynamic_write_leveling_supp TF failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ if (mask_tune_func & CENTRALIZATION_TX_MASK_BIT) {
+ training_stage = CENTRALIZATION_TX;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("CENTRALIZATION_TX_MASK_BIT CS #%d\n",
+ effective_cs));
+ ret = ddr3_tip_centralization_tx(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (ret != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_centralization_tx failure CS #%d\n",
+ effective_cs));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("restore registers to default\n"));
+ /* restore register values */
+ CHECK_STATUS(ddr3_tip_restore_dunit_regs(dev_num));
+
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+
+ return MV_OK;
+}
+
+/*
+ * DDR3 Dynamic training flow
+ */
+static int ddr3_tip_ddr3_auto_tune(u32 dev_num)
+{
+ int status;
+ u32 if_id, stage;
+ int is_if_fail = 0, is_auto_tune_fail = 0;
+
+ training_stage = INIT_CONTROLLER;
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ for (stage = 0; stage < MAX_STAGE_LIMIT; stage++)
+ training_result[stage][if_id] = NO_TEST_DONE;
+ }
+
+ status = ddr3_tip_ddr3_training_main_flow(dev_num);
+
+ /* activate XSB test */
+ if (xsb_validate_type != 0) {
+ run_xsb_test(dev_num, xsb_validation_base_address, 1, 1,
+ 0x1024);
+ }
+
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+
+ /* print log */
+ CHECK_STATUS(ddr3_tip_print_log(dev_num, window_mem_addr));
+
+#ifndef EXCLUDE_DEBUG_PRINTS
+ if (status != MV_OK) {
+ CHECK_STATUS(ddr3_tip_print_stability_log(dev_num));
+ }
+#endif /* EXCLUDE_DEBUG_PRINTS */
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ is_if_fail = 0;
+ for (stage = 0; stage < MAX_STAGE_LIMIT; stage++) {
+ if (training_result[stage][if_id] == TEST_FAILED)
+ is_if_fail = 1;
+ }
+ if (is_if_fail == 1) {
+ is_auto_tune_fail = 1;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("Auto Tune failed for IF %d\n",
+ if_id));
+ }
+ }
+
+ if (((status == MV_FAIL) && (is_auto_tune_fail == 0)) ||
+ ((status == MV_OK) && (is_auto_tune_fail == 1))) {
+ /*
+ * If MainFlow result and trainingResult DB not in sync,
+ * issue warning (caused by no update of trainingResult DB
+ * when failed)
+ */
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("Warning: Algorithm return value and Result DB"
+ "are not synced (status 0x%x result DB %d)\n",
+ status, is_auto_tune_fail));
+ }
+
+ if ((status != MV_OK) || (is_auto_tune_fail == 1))
+ return MV_FAIL;
+ else
+ return MV_OK;
+}
+
+/*
+ * Enable init sequence
+ */
+int ddr3_tip_enable_init_sequence(u32 dev_num)
+{
+ int is_fail = 0;
+ u32 if_id = 0, mem_mask = 0, bus_index = 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();
+
+ /* Enable init sequence */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, 0,
+ SDRAM_INIT_CTRL_REG, 0x1, 0x1));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1,
+ SDRAM_INIT_CTRL_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("polling failed IF %d\n",
+ if_id));
+ is_fail = 1;
+ continue;
+ }
+
+ mem_mask = 0;
+ for (bus_index = 0; bus_index < octets_per_if_num;
+ bus_index++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index);
+ mem_mask |=
+ tm->interface_params[if_id].
+ as_bus_params[bus_index].mirror_enable_bitmask;
+ }
+
+ if (mem_mask != 0) {
+ /* Disable Multi CS */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ if_id, DUAL_DUNIT_CFG_REG, 1 << 3,
+ 1 << 3));
+ }
+ }
+
+ return (is_fail == 0) ? MV_OK : MV_FAIL;
+}
+
+int ddr3_tip_register_dq_table(u32 dev_num, u32 *table)
+{
+ dq_map_table = table;
+
+ return MV_OK;
+}
+
+/*
+ * Check if pup search is locked
+ */
+int ddr3_tip_is_pup_lock(u32 *pup_buf, enum hws_training_result read_mode)
+{
+ u32 bit_start = 0, bit_end = 0, bit_id;
+
+ if (read_mode == RESULT_PER_BIT) {
+ bit_start = 0;
+ bit_end = BUS_WIDTH_IN_BITS - 1;
+ } else {
+ bit_start = 0;
+ bit_end = 0;
+ }
+
+ for (bit_id = bit_start; bit_id <= bit_end; bit_id++) {
+ if (GET_LOCK_RESULT(pup_buf[bit_id]) == 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Get minimum buffer value
+ */
+u8 ddr3_tip_get_buf_min(u8 *buf_ptr)
+{
+ u8 min_val = 0xff;
+ u8 cnt = 0;
+
+ for (cnt = 0; cnt < BUS_WIDTH_IN_BITS; cnt++) {
+ if (buf_ptr[cnt] < min_val)
+ min_val = buf_ptr[cnt];
+ }
+
+ return min_val;
+}
+
+/*
+ * Get maximum buffer value
+ */
+u8 ddr3_tip_get_buf_max(u8 *buf_ptr)
+{
+ u8 max_val = 0;
+ u8 cnt = 0;
+
+ for (cnt = 0; cnt < BUS_WIDTH_IN_BITS; cnt++) {
+ if (buf_ptr[cnt] > max_val)
+ max_val = buf_ptr[cnt];
+ }
+
+ return max_val;
+}
+
+/*
+ * The following functions return memory parameters:
+ * bus and device width, device size
+ */
+
+u32 hws_ddr3_get_bus_width(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ return (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) ==
+ 1) ? 16 : 32;
+}
+
+u32 hws_ddr3_get_device_width(u32 if_id)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ return (tm->interface_params[if_id].bus_width ==
+ MV_DDR_DEV_WIDTH_8BIT) ? 8 : 16;
+}
+
+u32 hws_ddr3_get_device_size(u32 if_id)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (tm->interface_params[if_id].memory_size >=
+ MV_DDR_DIE_CAP_LAST) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Error: Wrong device size of Cs: %d",
+ tm->interface_params[if_id].memory_size));
+ return 0;
+ } else {
+ return 1 << tm->interface_params[if_id].memory_size;
+ }
+}
+
+int hws_ddr3_calc_mem_cs_size(u32 if_id, u32 cs, u32 *cs_size)
+{
+ u32 cs_mem_size, dev_size;
+
+ dev_size = hws_ddr3_get_device_size(if_id);
+ if (dev_size != 0) {
+ cs_mem_size = ((hws_ddr3_get_bus_width() /
+ hws_ddr3_get_device_width(if_id)) * dev_size);
+
+ /* the calculated result in Gbytex16 to avoid float using */
+
+ if (cs_mem_size == 2) {
+ *cs_size = _128M;
+ } else if (cs_mem_size == 4) {
+ *cs_size = _256M;
+ } else if (cs_mem_size == 8) {
+ *cs_size = _512M;
+ } else if (cs_mem_size == 16) {
+ *cs_size = _1G;
+ } else if (cs_mem_size == 32) {
+ *cs_size = _2G;
+ } else {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Error: Wrong Memory size of Cs: %d", cs));
+ return MV_FAIL;
+ }
+ return MV_OK;
+ } else {
+ return MV_FAIL;
+ }
+}
+
+int hws_ddr3_cs_base_adr_calc(u32 if_id, u32 cs, u32 *cs_base_addr)
+{
+ u32 cs_mem_size = 0;
+#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE
+ u32 physical_mem_size;
+ u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE;
+#endif
+
+ if (hws_ddr3_calc_mem_cs_size(if_id, cs, &cs_mem_size) != MV_OK)
+ return MV_FAIL;
+
+#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ /*
+ * if number of address pins doesn't allow to use max mem size that
+ * is defined in topology mem size is defined by
+ * DEVICE_MAX_DRAM_ADDRESS_SIZE
+ */
+ physical_mem_size = mem_size[tm->interface_params[0].memory_size];
+
+ if (hws_ddr3_get_device_width(cs) == 16) {
+ /*
+ * 16bit mem device can be twice more - no need in less
+ * significant pin
+ */
+ max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2;
+ }
+
+ if (physical_mem_size > max_mem_size) {
+ cs_mem_size = max_mem_size *
+ (hws_ddr3_get_bus_width() /
+ hws_ddr3_get_device_width(if_id));
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("Updated Physical Mem size is from 0x%x to %x\n",
+ physical_mem_size,
+ DEVICE_MAX_DRAM_ADDRESS_SIZE));
+ }
+#endif
+
+ /* calculate CS base addr */
+ *cs_base_addr = ((cs_mem_size) * cs) & 0xffff0000;
+
+ return MV_OK;
+}
+
+/* TODO: consider to move to misl phy driver */
+enum {
+ MISL_PHY_DRV_OHM_30 = 0xf,
+ MISL_PHY_DRV_OHM_48 = 0xa,
+ MISL_PHY_DRV_OHM_80 = 0x6,
+ MISL_PHY_DRV_OHM_120 = 0x4
+};
+
+enum {
+ MISL_PHY_ODT_OHM_60 = 0x8,
+ MISL_PHY_ODT_OHM_80 = 0x6,
+ MISL_PHY_ODT_OHM_120 = 0x4,
+ MISL_PHY_ODT_OHM_240 = 0x2
+};
+
+static unsigned int mv_ddr_misl_phy_drv_calc(unsigned int cfg)
+{
+ unsigned int val;
+
+ switch (cfg) {
+ case MV_DDR_OHM_30:
+ val = MISL_PHY_DRV_OHM_30;
+ break;
+ case MV_DDR_OHM_48:
+ val = MISL_PHY_DRV_OHM_48;
+ break;
+ case MV_DDR_OHM_80:
+ val = MISL_PHY_DRV_OHM_80;
+ break;
+ case MV_DDR_OHM_120:
+ val = MISL_PHY_DRV_OHM_120;
+ break;
+ default:
+ val = PARAM_UNDEFINED;
+ }
+
+ return val;
+}
+
+static unsigned int mv_ddr_misl_phy_odt_calc(unsigned int cfg)
+{
+ unsigned int val;
+
+ switch (cfg) {
+ case MV_DDR_OHM_60:
+ val = MISL_PHY_ODT_OHM_60;
+ break;
+ case MV_DDR_OHM_80:
+ val = MISL_PHY_ODT_OHM_80;
+ break;
+ case MV_DDR_OHM_120:
+ val = MISL_PHY_ODT_OHM_120;
+ break;
+ case MV_DDR_OHM_240:
+ val = MISL_PHY_ODT_OHM_240;
+ break;
+ default:
+ val = PARAM_UNDEFINED;
+ }
+
+ return val;
+}
+
+unsigned int mv_ddr_misl_phy_drv_data_p_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int drv_data_p = mv_ddr_misl_phy_drv_calc(tm->edata.phy_edata.drv_data_p);
+
+ if (drv_data_p == PARAM_UNDEFINED)
+ printf("error: %s: unsupported drv_data_p parameter found\n", __func__);
+
+ return drv_data_p;
+}
+
+unsigned int mv_ddr_misl_phy_drv_data_n_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int drv_data_n = mv_ddr_misl_phy_drv_calc(tm->edata.phy_edata.drv_data_n);
+
+ if (drv_data_n == PARAM_UNDEFINED)
+ printf("error: %s: unsupported drv_data_n parameter found\n", __func__);
+
+ return drv_data_n;
+}
+
+unsigned int mv_ddr_misl_phy_drv_ctrl_p_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int drv_ctrl_p = mv_ddr_misl_phy_drv_calc(tm->edata.phy_edata.drv_ctrl_p);
+
+ if (drv_ctrl_p == PARAM_UNDEFINED)
+ printf("error: %s: unsupported drv_ctrl_p parameter found\n", __func__);
+
+ return drv_ctrl_p;
+}
+
+unsigned int mv_ddr_misl_phy_drv_ctrl_n_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int drv_ctrl_n = mv_ddr_misl_phy_drv_calc(tm->edata.phy_edata.drv_ctrl_n);
+
+ if (drv_ctrl_n == PARAM_UNDEFINED)
+ printf("error: %s: unsupported drv_ctrl_n parameter found\n", __func__);
+
+ return drv_ctrl_n;
+}
+
+unsigned int mv_ddr_misl_phy_odt_p_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int cs_num = mv_ddr_cs_num_get();
+ unsigned int odt_p = PARAM_UNDEFINED;
+
+ if (cs_num > 0 && cs_num <= MAX_CS_NUM)
+ odt_p = mv_ddr_misl_phy_odt_calc(tm->edata.phy_edata.odt_p[cs_num - 1]);
+
+ if (odt_p == PARAM_UNDEFINED)
+ printf("error: %s: unsupported odt_p parameter found\n", __func__);
+
+ return odt_p;
+}
+
+unsigned int mv_ddr_misl_phy_odt_n_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int cs_num = mv_ddr_cs_num_get();
+ unsigned int odt_n = PARAM_UNDEFINED;
+
+ if (cs_num > 0 && cs_num <= MAX_CS_NUM)
+ odt_n = mv_ddr_misl_phy_odt_calc(tm->edata.phy_edata.odt_n[cs_num - 1]);
+
+ if (odt_n == PARAM_UNDEFINED)
+ printf("error: %s: unsupported odt_n parameter found\n", __func__);
+
+ return odt_n;
+}
+
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_bist.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_bist.c
new file mode 100644
index 000000000..d388a1729
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_bist.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_regs.h"
+
+static u32 bist_offset = 32;
+enum hws_pattern sweep_pattern = PATTERN_KILLER_DQ0;
+
+static int ddr3_tip_bist_operation(u32 dev_num,
+ enum hws_access_type access_type,
+ u32 if_id,
+ enum hws_bist_operation oper_type);
+
+/*
+ * BIST activate
+ */
+int ddr3_tip_bist_activate(u32 dev_num, enum hws_pattern pattern,
+ enum hws_access_type access_type, u32 if_num,
+ enum hws_dir dir,
+ enum hws_stress_jump addr_stress_jump,
+ enum hws_pattern_duration duration,
+ enum hws_bist_operation oper_type,
+ u32 offset, u32 cs_num, u32 pattern_addr_length)
+{
+ u32 tx_burst_size;
+ u32 delay_between_burst;
+ u32 rd_mode;
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+
+ /* odpg bist write enable */
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG,
+ (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS),
+ (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS));
+
+ /* odpg bist read enable/disable */
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG,
+ (dir == OPER_READ) ? (ODPG_WRBUF_RD_CTRL_ENA << ODPG_WRBUF_RD_CTRL_OFFS) :
+ (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS),
+ (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS));
+
+ ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset);
+
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_SIZE_REG, pattern_addr_length, MASK_ALL_BITS);
+ tx_burst_size = (dir == OPER_WRITE) ?
+ pattern_table[pattern].tx_burst_size : 0;
+ delay_between_burst = (dir == OPER_WRITE) ? 2 : 0;
+ rd_mode = (dir == OPER_WRITE) ? 1 : 0;
+ ddr3_tip_configure_odpg(0, access_type, 0, dir,
+ pattern_table[pattern].num_of_phases_tx, tx_burst_size,
+ pattern_table[pattern].num_of_phases_rx,
+ delay_between_burst,
+ rd_mode, cs_num, addr_stress_jump, duration);
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_OFFS_REG, offset, MASK_ALL_BITS);
+
+ if (oper_type == BIST_STOP) {
+ ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP);
+ } else {
+ ddr3_tip_bist_operation(0, access_type, 0, BIST_START);
+ if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK)
+ return MV_FAIL;
+ ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP);
+ }
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+
+ return MV_OK;
+}
+
+/*
+ * BIST read result
+ */
+int ddr3_tip_bist_read_result(u32 dev_num, u32 if_id,
+ struct bist_result *pst_bist_result)
+{
+ int ret;
+ u32 read_data[MAX_INTERFACE_NUM];
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (IS_IF_ACTIVE(tm->if_act_mask, if_id) == 0)
+ return MV_NOT_SUPPORTED;
+ DEBUG_TRAINING_BIST_ENGINE(DEBUG_LEVEL_TRACE,
+ ("ddr3_tip_bist_read_result if_id %d\n",
+ if_id));
+ ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ODPG_DATA_RX_WORD_ERR_DATA_HIGH_REG, read_data,
+ MASK_ALL_BITS);
+ if (ret != MV_OK)
+ return ret;
+ pst_bist_result->bist_fail_high = read_data[if_id];
+ ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ODPG_DATA_RX_WORD_ERR_DATA_LOW_REG, read_data,
+ MASK_ALL_BITS);
+ if (ret != MV_OK)
+ return ret;
+ pst_bist_result->bist_fail_low = read_data[if_id];
+
+ ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ODPG_DATA_RX_WORD_ERR_ADDR_REG, read_data,
+ MASK_ALL_BITS);
+ if (ret != MV_OK)
+ return ret;
+ pst_bist_result->bist_last_fail_addr = read_data[if_id];
+ ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ODPG_DATA_RX_WORD_ERR_CNTR_REG, read_data,
+ MASK_ALL_BITS);
+ if (ret != MV_OK)
+ return ret;
+ pst_bist_result->bist_error_cnt = read_data[if_id];
+
+ return MV_OK;
+}
+
+/*
+ * BIST flow - Activate & read result
+ */
+int hws_ddr3_run_bist(u32 dev_num, enum hws_pattern pattern, u32 *result,
+ u32 cs_num)
+{
+ int ret;
+ u32 i = 0;
+ u32 win_base;
+ struct bist_result st_bist_result;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ for (i = 0; i < MAX_INTERFACE_NUM; i++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, i);
+ hws_ddr3_cs_base_adr_calc(i, cs_num, &win_base);
+ ret = ddr3_tip_bist_activate(dev_num, pattern,
+ ACCESS_TYPE_UNICAST,
+ i, OPER_WRITE, STRESS_NONE,
+ DURATION_SINGLE, BIST_START,
+ bist_offset + win_base,
+ cs_num, 15);
+ if (ret != MV_OK) {
+ printf("ddr3_tip_bist_activate failed (0x%x)\n", ret);
+ return ret;
+ }
+
+ ret = ddr3_tip_bist_activate(dev_num, pattern,
+ ACCESS_TYPE_UNICAST,
+ i, OPER_READ, STRESS_NONE,
+ DURATION_SINGLE, BIST_START,
+ bist_offset + win_base,
+ cs_num, 15);
+ if (ret != MV_OK) {
+ printf("ddr3_tip_bist_activate failed (0x%x)\n", ret);
+ return ret;
+ }
+
+ ret = ddr3_tip_bist_read_result(dev_num, i, &st_bist_result);
+ if (ret != MV_OK) {
+ printf("ddr3_tip_bist_read_result failed\n");
+ return ret;
+ }
+ result[i] = st_bist_result.bist_error_cnt;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Set BIST Operation
+ */
+
+static int ddr3_tip_bist_operation(u32 dev_num,
+ enum hws_access_type access_type,
+ u32 if_id, enum hws_bist_operation oper_type)
+{
+ if (oper_type == BIST_STOP)
+ mv_ddr_odpg_disable();
+ else
+ mv_ddr_odpg_enable();
+
+ return MV_OK;
+}
+
+/*
+ * Print BIST result
+ */
+void ddr3_tip_print_bist_res(void)
+{
+ u32 dev_num = 0;
+ u32 i;
+ struct bist_result st_bist_result[MAX_INTERFACE_NUM];
+ int res;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ for (i = 0; i < MAX_INTERFACE_NUM; i++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, i);
+
+ res = ddr3_tip_bist_read_result(dev_num, i, &st_bist_result[i]);
+ if (res != MV_OK) {
+ DEBUG_TRAINING_BIST_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_bist_read_result failed\n"));
+ return;
+ }
+ }
+
+ DEBUG_TRAINING_BIST_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("interface | error_cnt | fail_low | fail_high | fail_addr\n"));
+
+ for (i = 0; i < MAX_INTERFACE_NUM; i++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, i);
+
+ DEBUG_TRAINING_BIST_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("%d | 0x%08x | 0x%08x | 0x%08x | 0x%08x\n",
+ i, st_bist_result[i].bist_error_cnt,
+ st_bist_result[i].bist_fail_low,
+ st_bist_result[i].bist_fail_high,
+ st_bist_result[i].bist_last_fail_addr));
+ }
+}
+
+enum {
+ PASS,
+ FAIL
+};
+#define TIP_ITERATION_NUM 31
+static int mv_ddr_tip_bist(enum hws_dir dir, u32 val, enum hws_pattern pattern, u32 cs, u32 *result)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum hws_training_ip_stat training_result;
+ u16 *reg_map = ddr3_tip_get_mask_results_pup_reg_map();
+ u32 max_subphy = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ u32 subphy, read_data;
+
+ ddr3_tip_ip_training(0, ACCESS_TYPE_MULTICAST, 0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ RESULT_PER_BYTE, HWS_CONTROL_ELEMENT_ADLL, HWS_LOW2HIGH, dir, tm->if_act_mask, val,
+ TIP_ITERATION_NUM, pattern, EDGE_FP, CS_SINGLE, cs, &training_result);
+
+ for (subphy = 0; subphy < max_subphy; subphy++) {
+ ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, reg_map[subphy], &read_data, MASK_ALL_BITS);
+ if (((read_data >> BLOCK_STATUS_OFFS) & BLOCK_STATUS_MASK) == BLOCK_STATUS_NOT_LOCKED)
+ *result |= (FAIL << subphy);
+ }
+
+ return MV_OK;
+}
+
+struct interval {
+ u8 *vector;
+ u8 lendpnt; /* interval's left endpoint */
+ u8 rendpnt; /* interval's right endpoint */
+ u8 size; /* interval's size */
+ u8 lmarker; /* left marker */
+ u8 rmarker; /* right marker */
+ u8 pass_lendpnt; /* left endpoint of internal pass interval */
+ u8 pass_rendpnt; /* right endpoint of internal pass interval */
+};
+
+static int interval_init(u8 *vector, u8 lendpnt, u8 rendpnt,
+ u8 lmarker, u8 rmarker, struct interval *intrvl)
+{
+ if (intrvl == NULL) {
+ printf("%s: NULL intrvl pointer found\n", __func__);
+ return MV_FAIL;
+ }
+
+ if (vector == NULL) {
+ printf("%s: NULL vector pointer found\n", __func__);
+ return MV_FAIL;
+ }
+ intrvl->vector = vector;
+
+ if (lendpnt >= rendpnt) {
+ printf("%s: incorrect lendpnt and/or rendpnt parameters found\n", __func__);
+ return MV_FAIL;
+ }
+ intrvl->lendpnt = lendpnt;
+ intrvl->rendpnt = rendpnt;
+ intrvl->size = rendpnt - lendpnt + 1;
+
+ if ((lmarker < lendpnt) || (lmarker > rendpnt)) {
+ printf("%s: incorrect lmarker parameter found\n", __func__);
+ return MV_FAIL;
+ }
+ intrvl->lmarker = lmarker;
+
+ if ((rmarker < lmarker) || (rmarker > (intrvl->rendpnt + intrvl->size))) {
+ printf("%s: incorrect rmarker parameter found\n", __func__);
+ return MV_FAIL;
+ }
+ intrvl->rmarker = rmarker;
+
+ return MV_OK;
+}
+static int interval_set(u8 pass_lendpnt, u8 pass_rendpnt, struct interval *intrvl)
+{
+ if (intrvl == NULL) {
+ printf("%s: NULL intrvl pointer found\n", __func__);
+ return MV_FAIL;
+ }
+
+ intrvl->pass_lendpnt = pass_lendpnt;
+ intrvl->pass_rendpnt = pass_rendpnt;
+
+ return MV_OK;
+}
+
+static int interval_proc(struct interval *intrvl)
+{
+ int curr;
+ int pass_lendpnt, pass_rendpnt;
+ int lmt;
+ int fcnt = 0, pcnt = 0;
+
+ if (intrvl == NULL) {
+ printf("%s: NULL intrvl pointer found\n", __func__);
+ return MV_FAIL;
+ }
+
+ /* count fails and passes */
+ curr = intrvl->lendpnt;
+ while (curr <= intrvl->rendpnt) {
+ if (intrvl->vector[curr] == PASS)
+ pcnt++;
+ else
+ fcnt++;
+ curr++;
+ }
+
+ /* check for all fail */
+ if (fcnt == intrvl->size) {
+ printf("%s: no pass found\n", __func__);
+ return MV_FAIL;
+ }
+
+ /* check for all pass */
+ if (pcnt == intrvl->size) {
+ if (interval_set(intrvl->lendpnt, intrvl->rendpnt, intrvl) != MV_OK)
+ return MV_FAIL;
+ return MV_OK;
+ }
+
+ /* proceed with rmarker */
+ curr = intrvl->rmarker;
+ if (intrvl->vector[curr % intrvl->size] == PASS) { /* pass at rmarker */
+ /* search for fail on right */
+ if (intrvl->rmarker > intrvl->rendpnt)
+ lmt = intrvl->rendpnt + intrvl->size;
+ else
+ lmt = intrvl->rmarker + intrvl->size - 1;
+ while ((curr <= lmt) &&
+ (intrvl->vector[curr % intrvl->size] == PASS))
+ curr++;
+ if (curr > lmt) { /* fail not found */
+ printf("%s: rmarker: fail following pass not found\n", __func__);
+ return MV_FAIL;
+ }
+ /* fail found */
+ pass_rendpnt = curr - 1;
+ } else { /* fail at rmarker */
+ /* search for pass on left */
+ if (intrvl->rmarker > intrvl->rendpnt)
+ lmt = intrvl->rmarker - intrvl->size + 1;
+ else
+ lmt = intrvl->lendpnt;
+ while ((curr >= lmt) &&
+ (intrvl->vector[curr % intrvl->size] == FAIL))
+ curr--;
+ if (curr < lmt) { /* pass not found */
+ printf("%s: rmarker: pass preceding fail not found\n", __func__);
+ return MV_FAIL;
+ }
+ /* pass found */
+ pass_rendpnt = curr;
+ }
+
+ /* search for fail on left */
+ curr = pass_rendpnt;
+ if (pass_rendpnt > intrvl->rendpnt)
+ lmt = pass_rendpnt - intrvl->size + 1;
+ else
+ lmt = intrvl->lendpnt;
+ while ((curr >= lmt) &&
+ (intrvl->vector[curr % intrvl->size] == PASS))
+ curr--;
+ if (curr < lmt) { /* fail not found */
+ printf("%s: rmarker: fail preceding pass not found\n", __func__);
+ return MV_FAIL;
+ }
+ /* fail found */
+ pass_lendpnt = curr + 1;
+ if (interval_set(pass_lendpnt, pass_rendpnt, intrvl) != MV_OK)
+ return MV_FAIL;
+
+ return MV_OK;
+}
+
+#define ADLL_TAPS_PER_PERIOD 64
+int mv_ddr_dm_to_dq_diff_get(u8 vw_sphy_hi_lmt, u8 vw_sphy_lo_lmt, u8 *vw_vector,
+ int *vw_sphy_hi_diff, int *vw_sphy_lo_diff)
+{
+ struct interval intrvl;
+
+ /* init interval structure */
+ if (interval_init(vw_vector, 0, ADLL_TAPS_PER_PERIOD - 1,
+ vw_sphy_lo_lmt, vw_sphy_hi_lmt, &intrvl) != MV_OK)
+ return MV_FAIL;
+
+ /* find pass sub-interval */
+ if (interval_proc(&intrvl) != MV_OK)
+ return MV_FAIL;
+
+ /* check for all pass */
+ if ((intrvl.pass_rendpnt == intrvl.rendpnt) &&
+ (intrvl.pass_lendpnt == intrvl.lendpnt)) {
+ printf("%s: no fail found\n", __func__);
+ return MV_FAIL;
+ }
+
+ *vw_sphy_hi_diff = intrvl.pass_rendpnt - vw_sphy_hi_lmt;
+ *vw_sphy_lo_diff = vw_sphy_lo_lmt - intrvl.pass_lendpnt;
+
+ return MV_OK;
+}
+
+static int mv_ddr_bist_tx(enum hws_access_type access_type)
+{
+ mv_ddr_odpg_done_clr();
+
+ ddr3_tip_bist_operation(0, access_type, 0, BIST_START);
+
+ if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK)
+ return MV_FAIL;
+
+ ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP);
+
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+
+ return MV_OK;
+}
+
+/* prepare odpg for bist operation */
+#define WR_OP_ODPG_DATA_CMD_BURST_DLY 2
+static int mv_ddr_odpg_bist_prepare(enum hws_pattern pattern, enum hws_access_type access_type,
+ enum hws_dir dir, enum hws_stress_jump stress_jump_addr,
+ enum hws_pattern_duration duration, u32 offset, u32 cs,
+ u32 pattern_addr_len, enum dm_direction dm_dir)
+{
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+ u32 tx_burst_size;
+ u32 burst_delay;
+ u32 rd_mode;
+
+ /* odpg bist write enable */
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG,
+ (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS),
+ (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS));
+
+ /* odpg bist read enable/disable */
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG,
+ (dir == OPER_READ) ? (ODPG_WRBUF_RD_CTRL_ENA << ODPG_WRBUF_RD_CTRL_OFFS) :
+ (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS),
+ (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS));
+
+ if (pattern == PATTERN_00 || pattern == PATTERN_FF)
+ ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset);
+ else
+ mv_ddr_load_dm_pattern_to_odpg(access_type, pattern, dm_dir);
+
+ ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_SIZE_REG, pattern_addr_len, MASK_ALL_BITS);
+ if (dir == OPER_WRITE) {
+ tx_burst_size = pattern_table[pattern].tx_burst_size;
+ burst_delay = WR_OP_ODPG_DATA_CMD_BURST_DLY;
+ rd_mode = ODPG_MODE_TX;
+ } else {
+ tx_burst_size = 0;
+ burst_delay = 0;
+ rd_mode = ODPG_MODE_RX;
+ }
+ ddr3_tip_configure_odpg(0, access_type, 0, dir, pattern_table[pattern].num_of_phases_tx,
+ tx_burst_size, pattern_table[pattern].num_of_phases_rx, burst_delay,
+ rd_mode, cs, stress_jump_addr, duration);
+
+ return MV_OK;
+}
+
+#define BYTES_PER_BURST_64BIT 0x20
+#define BYTES_PER_BURST_32BIT 0x10
+int mv_ddr_dm_vw_get(enum hws_pattern pattern, u32 cs, u8 *vw_vector)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+ u32 adll_tap;
+ u32 wr_ctrl_adll[MAX_BUS_NUM] = {0};
+ u32 rd_ctrl_adll[MAX_BUS_NUM] = {0};
+ u32 subphy;
+ u32 subphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ u32 odpg_addr = 0x0;
+ u32 result;
+ u32 idx;
+ /* burst length in bytes */
+ u32 burst_len = (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ?
+ BYTES_PER_BURST_64BIT : BYTES_PER_BURST_32BIT);
+
+ /* save dqs values to restore after algorithm's run */
+ ddr3_tip_read_adll_value(0, wr_ctrl_adll, CTX_PHY_REG(cs), MASK_ALL_BITS);
+ ddr3_tip_read_adll_value(0, rd_ctrl_adll, CRX_PHY_REG(cs), MASK_ALL_BITS);
+
+ /* fill memory with base pattern */
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+ mv_ddr_odpg_bist_prepare(pattern, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE,
+ bist_offset, cs, pattern_table[pattern].num_of_phases_tx,
+ (pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE);
+
+ for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) {
+ /* change target odpg address */
+ odpg_addr = adll_tap * burst_len;
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_BUFFER_OFFS_REG,
+ odpg_addr, MASK_ALL_BITS);
+
+ ddr3_tip_configure_odpg(0, ACCESS_TYPE_UNICAST, 0, OPER_WRITE,
+ pattern_table[pattern].num_of_phases_tx,
+ pattern_table[pattern].tx_burst_size,
+ pattern_table[pattern].num_of_phases_rx,
+ WR_OP_ODPG_DATA_CMD_BURST_DLY,
+ ODPG_MODE_TX, cs, STRESS_NONE, DURATION_SINGLE);
+
+ /* odpg bist write enable */
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG,
+ (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS),
+ (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS));
+
+ /* odpg bist read disable */
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG,
+ (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS),
+ (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS));
+
+ /* trigger odpg */
+ mv_ddr_bist_tx(ACCESS_TYPE_MULTICAST);
+ }
+
+ /* fill memory with vref pattern to increment addr using odpg bist */
+ mv_ddr_odpg_bist_prepare(PATTERN_VREF, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE,
+ bist_offset, cs, pattern_table[pattern].num_of_phases_tx,
+ (pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE);
+
+ for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) {
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, 0,
+ DDR_PHY_DATA, CTX_PHY_REG(cs), adll_tap);
+ /* change target odpg address */
+ odpg_addr = adll_tap * burst_len;
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_BUFFER_OFFS_REG,
+ odpg_addr, MASK_ALL_BITS);
+ ddr3_tip_configure_odpg(0, ACCESS_TYPE_UNICAST, 0, OPER_WRITE,
+ pattern_table[pattern].num_of_phases_tx,
+ pattern_table[pattern].tx_burst_size,
+ pattern_table[pattern].num_of_phases_rx,
+ WR_OP_ODPG_DATA_CMD_BURST_DLY,
+ ODPG_MODE_TX, cs, STRESS_NONE, DURATION_SINGLE);
+
+ /* odpg bist write enable */
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG,
+ (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS),
+ (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS));
+
+ /* odpg bist read disable */
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG,
+ (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS),
+ (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS));
+
+ /* trigger odpg */
+ mv_ddr_bist_tx(ACCESS_TYPE_MULTICAST);
+ }
+
+ /* restore subphy's tx adll_tap to its position */
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA, CTX_PHY_REG(cs),
+ wr_ctrl_adll[subphy]);
+ }
+
+ /* read and validate bist (comparing with the base pattern) */
+ for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) {
+ result = 0;
+ odpg_addr = adll_tap * burst_len;
+ /* change addr to fit write */
+ mv_ddr_pattern_start_addr_set(pattern_table, pattern, odpg_addr);
+ mv_ddr_tip_bist(OPER_READ, 0, pattern, 0, &result);
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ idx = ADLL_TAPS_PER_PERIOD * subphy + adll_tap;
+ vw_vector[idx] |= ((result >> subphy) & 0x1);
+ }
+ }
+
+ /* restore subphy's rx adll_tap to its position */
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA, CRX_PHY_REG(cs),
+ rd_ctrl_adll[subphy]);
+ }
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_centralization.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
new file mode 100644
index 000000000..648b37ef6
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
@@ -0,0 +1,716 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_regs.h"
+
+#define VALIDATE_WIN_LENGTH(e1, e2, maxsize) \
+ (((e2) + 1 > (e1) + (u8)MIN_WINDOW_SIZE) && \
+ ((e2) + 1 < (e1) + (u8)maxsize))
+#define IS_WINDOW_OUT_BOUNDARY(e1, e2, maxsize) \
+ (((e1) == 0 && (e2) != 0) || \
+ ((e1) != (maxsize - 1) && (e2) == (maxsize - 1)))
+#define CENTRAL_TX 0
+#define CENTRAL_RX 1
+#define NUM_OF_CENTRAL_TYPES 2
+
+u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7;
+
+u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1);
+u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 bus_start_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 centralization_state[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+static u8 ddr3_tip_special_rx_run_once_flag;
+
+static int ddr3_tip_centralization(u32 dev_num, u32 mode);
+
+/*
+ * Centralization RX Flow
+ */
+int ddr3_tip_centralization_rx(u32 dev_num)
+{
+ CHECK_STATUS(ddr3_tip_special_rx(dev_num));
+ CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_RX));
+
+ return MV_OK;
+}
+
+/*
+ * Centralization TX Flow
+ */
+int ddr3_tip_centralization_tx(u32 dev_num)
+{
+ CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_TX));
+
+ return MV_OK;
+}
+
+/*
+ * Centralization Flow
+ */
+static int ddr3_tip_centralization(u32 dev_num, u32 mode)
+{
+ enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
+ u32 if_id, pattern_id, bit_id;
+ u8 bus_id;
+ u8 cur_start_win[BUS_WIDTH_IN_BITS];
+ u8 centralization_result[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
+ u8 cur_end_win[BUS_WIDTH_IN_BITS];
+ u8 current_window[BUS_WIDTH_IN_BITS];
+ u8 opt_window, waste_window, start_window_skew, end_window_skew;
+ u8 final_pup_window[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
+ 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();
+ enum hws_training_result result_type = RESULT_PER_BIT;
+ enum hws_dir direction;
+ u32 *result[HWS_SEARCH_DIR_LIMIT];
+ u32 reg_phy_off, reg;
+ u8 max_win_size;
+ int lock_success = 1;
+ u8 cur_end_win_min, cur_start_win_max;
+ u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
+ int is_if_fail = 0;
+ enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
+ u32 pup_win_length = 0;
+ enum hws_search_dir search_dir_id;
+ u8 cons_tap = (mode == CENTRAL_TX) ? (64) : (0);
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* save current cs enable reg val */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS));
+ /* enable single cs */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
+ }
+
+ if (mode == CENTRAL_TX) {
+ max_win_size = MAX_WINDOW_SIZE_TX;
+ reg_phy_off = CTX_PHY_REG(effective_cs);
+ direction = OPER_WRITE;
+ } else {
+ max_win_size = MAX_WINDOW_SIZE_RX;
+ reg_phy_off = CRX_PHY_REG(effective_cs);
+ direction = OPER_READ;
+ }
+
+ /* DB initialization */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0;
+ bus_id < octets_per_if_num; bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ centralization_state[if_id][bus_id] = 0;
+ bus_end_window[mode][if_id][bus_id] =
+ (max_win_size - 1) + cons_tap;
+ bus_start_window[mode][if_id][bus_id] = 0;
+ centralization_result[if_id][bus_id] = 0;
+ }
+ }
+
+ /* start flow */
+ for (pattern_id = start_pattern; pattern_id <= end_pattern;
+ pattern_id++) {
+ ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, result_type,
+ HWS_CONTROL_ELEMENT_ADLL,
+ PARAM_NOT_CARE, direction,
+ tm->
+ if_act_mask, 0x0,
+ max_win_size - 1,
+ max_win_size - 1,
+ pattern_id, EDGE_FPF, CS_SINGLE,
+ PARAM_NOT_CARE, training_result);
+
+ for (if_id = start_if; if_id <= end_if; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0;
+ bus_id <= octets_per_if_num - 1;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+
+ for (search_dir_id = HWS_LOW2HIGH;
+ search_dir_id <= HWS_HIGH2LOW;
+ search_dir_id++) {
+ CHECK_STATUS
+ (ddr3_tip_read_training_result
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ ALL_BITS_PER_PUP,
+ search_dir_id,
+ direction, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD,
+ CS_SINGLE,
+ &result[search_dir_id],
+ 1, 0, 0));
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("%s pat %d IF %d pup %d Regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ ((mode ==
+ CENTRAL_TX) ? "TX" : "RX"),
+ pattern_id, if_id, bus_id,
+ result[search_dir_id][0],
+ result[search_dir_id][1],
+ result[search_dir_id][2],
+ result[search_dir_id][3],
+ result[search_dir_id][4],
+ result[search_dir_id][5],
+ result[search_dir_id][6],
+ result[search_dir_id][7]));
+ }
+
+ for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
+ bit_id++) {
+ /* check if this code is valid for 2 edge, probably not :( */
+ cur_start_win[bit_id] =
+ GET_TAP_RESULT(result
+ [HWS_LOW2HIGH]
+ [bit_id],
+ EDGE_1);
+ cur_end_win[bit_id] =
+ GET_TAP_RESULT(result
+ [HWS_HIGH2LOW]
+ [bit_id],
+ EDGE_1);
+ /* window length */
+ current_window[bit_id] =
+ cur_end_win[bit_id] -
+ cur_start_win[bit_id] + 1;
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_TRACE,
+ ("cs %x patern %d IF %d pup %d cur_start_win %d cur_end_win %d current_window %d\n",
+ effective_cs, pattern_id,
+ if_id, bus_id,
+ cur_start_win[bit_id],
+ cur_end_win[bit_id],
+ current_window[bit_id]));
+ }
+
+ if ((ddr3_tip_is_pup_lock
+ (result[HWS_LOW2HIGH], result_type)) &&
+ (ddr3_tip_is_pup_lock
+ (result[HWS_HIGH2LOW], result_type))) {
+ /* read result success */
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("Pup locked, pat %d IF %d pup %d\n",
+ pattern_id, if_id, bus_id));
+ } else {
+ /* read result failure */
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("fail Lock, pat %d IF %d pup %d\n",
+ pattern_id, if_id, bus_id));
+ if (centralization_state[if_id][bus_id]
+ == 1) {
+ /* continue with next pup */
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_TRACE,
+ ("continue to next pup %d %d\n",
+ if_id, bus_id));
+ continue;
+ }
+
+ for (bit_id = 0;
+ bit_id < BUS_WIDTH_IN_BITS;
+ bit_id++) {
+ /*
+ * the next check is relevant
+ * only when using search
+ * machine 2 edges
+ */
+ if (cur_start_win[bit_id] > 0 &&
+ cur_end_win[bit_id] == 0) {
+ cur_end_win
+ [bit_id] =
+ max_win_size - 1;
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_TRACE,
+ ("fail, IF %d pup %d bit %d fail #1\n",
+ if_id, bus_id,
+ bit_id));
+ /* the next bit */
+ continue;
+ } else {
+ centralization_state
+ [if_id][bus_id] = 1;
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_TRACE,
+ ("fail, IF %d pup %d bit %d fail #2\n",
+ if_id, bus_id,
+ bit_id));
+ }
+ }
+
+ if (centralization_state[if_id][bus_id]
+ == 1) {
+ /* going to next pup */
+ continue;
+ }
+ } /*bit */
+
+ opt_window =
+ ddr3_tip_get_buf_min(current_window);
+ /* final pup window length */
+ final_pup_window[if_id][bus_id] =
+ ddr3_tip_get_buf_min(cur_end_win) -
+ ddr3_tip_get_buf_max(cur_start_win) +
+ 1;
+ waste_window =
+ opt_window -
+ final_pup_window[if_id][bus_id];
+ start_window_skew =
+ ddr3_tip_get_buf_max(cur_start_win) -
+ ddr3_tip_get_buf_min(
+ cur_start_win);
+ end_window_skew =
+ ddr3_tip_get_buf_max(
+ cur_end_win) -
+ ddr3_tip_get_buf_min(
+ cur_end_win);
+ /* min/max updated with pattern change */
+ cur_end_win_min =
+ ddr3_tip_get_buf_min(
+ cur_end_win);
+ cur_start_win_max =
+ ddr3_tip_get_buf_max(
+ cur_start_win);
+ bus_end_window[mode][if_id][bus_id] =
+ GET_MIN(bus_end_window[mode][if_id]
+ [bus_id],
+ cur_end_win_min);
+ bus_start_window[mode][if_id][bus_id] =
+ GET_MAX(bus_start_window[mode][if_id]
+ [bus_id],
+ cur_start_win_max);
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("pat %d IF %d pup %d opt_win %d final_win %d waste_win %d st_win_skew %d end_win_skew %d cur_st_win_max %d cur_end_win_min %d bus_st_win %d bus_end_win %d\n",
+ pattern_id, if_id, bus_id, opt_window,
+ final_pup_window[if_id][bus_id],
+ waste_window, start_window_skew,
+ end_window_skew,
+ cur_start_win_max,
+ cur_end_win_min,
+ bus_start_window[mode][if_id][bus_id],
+ bus_end_window[mode][if_id][bus_id]));
+
+ /* check if window is valid */
+ if (ddr3_tip_centr_skip_min_win_check == 0) {
+ if ((VALIDATE_WIN_LENGTH
+ (bus_start_window[mode][if_id]
+ [bus_id],
+ bus_end_window[mode][if_id]
+ [bus_id],
+ max_win_size) == 1) ||
+ (IS_WINDOW_OUT_BOUNDARY
+ (bus_start_window[mode][if_id]
+ [bus_id],
+ bus_end_window[mode][if_id]
+ [bus_id],
+ max_win_size) == 1)) {
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("win valid, pat %d IF %d pup %d\n",
+ pattern_id, if_id,
+ bus_id));
+ /* window is valid */
+ } else {
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("fail win, pat %d IF %d pup %d bus_st_win %d bus_end_win %d\n",
+ pattern_id, if_id, bus_id,
+ bus_start_window[mode]
+ [if_id][bus_id],
+ bus_end_window[mode]
+ [if_id][bus_id]));
+ centralization_state[if_id]
+ [bus_id] = 1;
+ if (debug_mode == 0) {
+ flow_result[if_id] = TEST_FAILED;
+ return MV_FAIL;
+ }
+ }
+ } /* ddr3_tip_centr_skip_min_win_check */
+ } /* pup */
+ } /* interface */
+ } /* pattern */
+
+ for (if_id = start_if; if_id <= end_if; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ is_if_fail = 0;
+ flow_result[if_id] = TEST_SUCCESS;
+
+ for (bus_id = 0;
+ bus_id <= (octets_per_if_num - 1); bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+
+ /* continue only if lock */
+ if (centralization_state[if_id][bus_id] != 1) {
+ if (ddr3_tip_centr_skip_min_win_check == 0) {
+ if ((bus_end_window
+ [mode][if_id][bus_id] ==
+ (max_win_size - 1)) &&
+ ((bus_end_window
+ [mode][if_id][bus_id] -
+ bus_start_window[mode][if_id]
+ [bus_id]) < MIN_WINDOW_SIZE) &&
+ ((bus_end_window[mode][if_id]
+ [bus_id] - bus_start_window
+ [mode][if_id][bus_id]) > 2)) {
+ /* prevent false lock */
+ /* TBD change to enum */
+ centralization_state
+ [if_id][bus_id] = 2;
+ }
+
+ if ((bus_end_window[mode][if_id][bus_id]
+ == 0) &&
+ ((bus_end_window[mode][if_id]
+ [bus_id] -
+ bus_start_window[mode][if_id]
+ [bus_id]) < MIN_WINDOW_SIZE) &&
+ ((bus_end_window[mode][if_id]
+ [bus_id] -
+ bus_start_window[mode][if_id]
+ [bus_id]) > 2))
+ /*prevent false lock */
+ centralization_state[if_id]
+ [bus_id] = 3;
+ }
+
+ if ((bus_end_window[mode][if_id][bus_id] >
+ (max_win_size - 1)) && direction ==
+ OPER_WRITE) {
+ DEBUG_CENTRALIZATION_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("Tx special pattern\n"));
+ cons_tap = 64;
+ }
+ }
+
+ /* check states */
+ if (centralization_state[if_id][bus_id] == 3) {
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("SSW - TBD IF %d pup %d\n",
+ if_id, bus_id));
+ lock_success = 1;
+ } else if (centralization_state[if_id][bus_id] == 2) {
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("SEW - TBD IF %d pup %d\n",
+ if_id, bus_id));
+ lock_success = 1;
+ } else if (centralization_state[if_id][bus_id] == 0) {
+ lock_success = 1;
+ } else {
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("fail, IF %d pup %d\n",
+ if_id, bus_id));
+ lock_success = 0;
+ }
+
+ if (lock_success == 1) {
+ centralization_result[if_id][bus_id] =
+ (bus_end_window[mode][if_id][bus_id] +
+ bus_start_window[mode][if_id][bus_id])
+ / 2 - cons_tap;
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_TRACE,
+ (" bus_id %d Res= %d\n", bus_id,
+ centralization_result[if_id][bus_id]));
+ /* copy results to registers */
+ pup_win_length =
+ bus_end_window[mode][if_id][bus_id] -
+ bus_start_window[mode][if_id][bus_id] +
+ 1;
+
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA,
+ RESULT_PHY_REG +
+ effective_cs, &reg);
+ reg = (reg & (~0x1f <<
+ ((mode == CENTRAL_TX) ?
+ (RESULT_PHY_TX_OFFS) :
+ (RESULT_PHY_RX_OFFS))))
+ | pup_win_length <<
+ ((mode == CENTRAL_TX) ?
+ (RESULT_PHY_TX_OFFS) :
+ (RESULT_PHY_RX_OFFS));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ RESULT_PHY_REG +
+ effective_cs, reg));
+
+ /* offset per CS is calculated earlier */
+ CHECK_STATUS(
+ ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id,
+ DDR_PHY_DATA,
+ reg_phy_off,
+ centralization_result
+ [if_id]
+ [bus_id]));
+ } else {
+ is_if_fail = 1;
+ }
+ }
+
+ if (is_if_fail == 1)
+ flow_result[if_id] = TEST_FAILED;
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ /* restore cs enable value */
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST,
+ if_id, DUAL_DUNIT_CFG_REG,
+ cs_enable_reg_val[if_id],
+ MASK_ALL_BITS));
+ }
+
+ return is_if_fail;
+}
+
+/*
+ * Centralization Flow
+ */
+int ddr3_tip_special_rx(u32 dev_num)
+{
+ enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
+ u32 if_id, pup_id, pattern_id, bit_id;
+ u8 cur_start_win[BUS_WIDTH_IN_BITS];
+ u8 cur_end_win[BUS_WIDTH_IN_BITS];
+ enum hws_training_result result_type = RESULT_PER_BIT;
+ enum hws_dir direction;
+ enum hws_search_dir search_dir_id;
+ u32 *result[HWS_SEARCH_DIR_LIMIT];
+ u32 max_win_size;
+ u8 cur_end_win_min, cur_start_win_max;
+ u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
+ u32 temp = 0;
+ int pad_num = 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 ((ddr3_tip_special_rx_run_once_flag & (1 << effective_cs)) == (1 << effective_cs))
+ return MV_OK;
+
+ ddr3_tip_special_rx_run_once_flag |= (1 << effective_cs);
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* save current cs enable reg val */
+ CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST,
+ if_id, DUAL_DUNIT_CFG_REG,
+ cs_enable_reg_val,
+ MASK_ALL_BITS));
+ /* enable single cs */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST,
+ if_id, DUAL_DUNIT_CFG_REG,
+ (1 << 3), (1 << 3)));
+ }
+
+ max_win_size = MAX_WINDOW_SIZE_RX;
+ direction = OPER_READ;
+ pattern_id = PATTERN_FULL_SSO1;
+
+ /* start flow */
+ ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, result_type,
+ HWS_CONTROL_ELEMENT_ADLL,
+ PARAM_NOT_CARE, direction,
+ tm->if_act_mask, 0x0,
+ max_win_size - 1, max_win_size - 1,
+ pattern_id, EDGE_FPF, CS_SINGLE,
+ PARAM_NOT_CARE, training_result);
+
+ for (if_id = start_if; if_id <= end_if; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup_id = 0;
+ pup_id <= octets_per_if_num; pup_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id);
+
+ for (search_dir_id = HWS_LOW2HIGH;
+ search_dir_id <= HWS_HIGH2LOW;
+ search_dir_id++) {
+ CHECK_STATUS(ddr3_tip_read_training_result
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup_id,
+ ALL_BITS_PER_PUP, search_dir_id,
+ direction, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD,
+ CS_SINGLE, &result[search_dir_id],
+ 1, 0, 0));
+ DEBUG_CENTRALIZATION_ENGINE(DEBUG_LEVEL_INFO,
+ ("Special: pat %d IF %d pup %d Regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ pattern_id, if_id,
+ pup_id,
+ result
+ [search_dir_id][0],
+ result
+ [search_dir_id][1],
+ result
+ [search_dir_id][2],
+ result
+ [search_dir_id][3],
+ result
+ [search_dir_id][4],
+ result
+ [search_dir_id][5],
+ result
+ [search_dir_id][6],
+ result
+ [search_dir_id]
+ [7]));
+ }
+
+ for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS; bit_id++) {
+ /*
+ * check if this code is valid for 2 edge,
+ * probably not :(
+ */
+ cur_start_win[bit_id] =
+ GET_TAP_RESULT(result[HWS_LOW2HIGH]
+ [bit_id], EDGE_1);
+ cur_end_win[bit_id] =
+ GET_TAP_RESULT(result[HWS_HIGH2LOW]
+ [bit_id], EDGE_1);
+ }
+ if (!((ddr3_tip_is_pup_lock
+ (result[HWS_LOW2HIGH], result_type)) &&
+ (ddr3_tip_is_pup_lock
+ (result[HWS_HIGH2LOW], result_type)))) {
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("Special: Pup lock fail, pat %d IF %d pup %d\n",
+ pattern_id, if_id, pup_id));
+ return MV_FAIL;
+ }
+
+ cur_end_win_min =
+ ddr3_tip_get_buf_min(cur_end_win);
+ cur_start_win_max =
+ ddr3_tip_get_buf_max(cur_start_win);
+
+ if (cur_start_win_max <= 1) { /* Align left */
+ for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
+ bit_id++) {
+ pad_num =
+ dq_map_table[bit_id +
+ pup_id *
+ BUS_WIDTH_IN_BITS +
+ if_id *
+ BUS_WIDTH_IN_BITS *
+ MAX_BUS_NUM];
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ pup_id, DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, pad_num),
+ &temp));
+ temp = (temp + 0xa > 31) ?
+ (31) : (temp + 0xa);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ pup_id, DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, pad_num),
+ temp));
+ }
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("Special: PBS:: I/F# %d , Bus# %d fix align to the Left\n",
+ if_id, pup_id));
+ }
+
+ if (cur_end_win_min > 30) { /* Align right */
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup_id,
+ DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, 4),
+ &temp));
+ temp += 0xa;
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST,
+ pup_id, DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, 4),
+ temp));
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup_id,
+ DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, 5),
+ &temp));
+ temp += 0xa;
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST,
+ pup_id, DDR_PHY_DATA,
+ PBS_RX_PHY_REG(effective_cs, 5),
+ temp));
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("Special: PBS:: I/F# %d , Bus# %d fix align to the right\n",
+ if_id, pup_id));
+ }
+
+ vref_window_size[if_id][pup_id] =
+ cur_end_win_min -
+ cur_start_win_max + 1;
+ DEBUG_CENTRALIZATION_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("Special: Winsize I/F# %d , Bus# %d is %d\n",
+ if_id, pup_id, vref_window_size
+ [if_id][pup_id]));
+ } /* pup */
+ } /* end of interface */
+
+ return MV_OK;
+}
+
+/*
+ * Print Centralization Result
+ */
+int ddr3_tip_print_centralization_result(u32 dev_num)
+{
+ u32 if_id = 0, bus_id = 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();
+
+ dev_num = dev_num;
+
+ printf("Centralization Results\n");
+ printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n");
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0; bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ printf("%d ,\n", centralization_state[if_id][bus_id]);
+ }
+ }
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_db.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_db.c
new file mode 100644
index 000000000..6aa7b6069
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_db.c
@@ -0,0 +1,874 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr_ml_wrapper.h"
+
+#include "ddr3_training_ip_flow.h"
+#include "mv_ddr_topology.h"
+#include "mv_ddr_training_db.h"
+#include "ddr3_training_ip_db.h"
+
+/* Device attributes structures */
+enum mv_ddr_dev_attribute ddr_dev_attributes[MV_ATTR_LAST];
+int ddr_dev_attr_init_done = 0;
+
+static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index);
+static inline u32 pattern_table_get_sso_word(u8 sso, u8 index);
+static inline u32 pattern_table_get_vref_word(u8 index);
+static inline u32 pattern_table_get_vref_word16(u8 index);
+static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index);
+static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index);
+static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index);
+static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index);
+static inline u32 pattern_table_get_isi_word(u8 index);
+static inline u32 pattern_table_get_isi_word16(u8 index);
+
+/* List of allowed frequency listed in order of enum mv_ddr_freq */
+static unsigned int freq_val[MV_DDR_FREQ_LAST] = {
+ 0, /*MV_DDR_FREQ_LOW_FREQ */
+ 400, /*MV_DDR_FREQ_400, */
+ 533, /*MV_DDR_FREQ_533, */
+ 666, /*MV_DDR_FREQ_667, */
+ 800, /*MV_DDR_FREQ_800, */
+ 933, /*MV_DDR_FREQ_933, */
+ 1066, /*MV_DDR_FREQ_1066, */
+ 311, /*MV_DDR_FREQ_311, */
+ 333, /*MV_DDR_FREQ_333, */
+ 467, /*MV_DDR_FREQ_467, */
+ 850, /*MV_DDR_FREQ_850, */
+ 600, /*MV_DDR_FREQ_600 */
+ 300, /*MV_DDR_FREQ_300 */
+ 900, /*MV_DDR_FREQ_900 */
+ 360, /*MV_DDR_FREQ_360 */
+ 1000 /*MV_DDR_FREQ_1000 */
+};
+
+unsigned int *mv_ddr_freq_tbl_get(void)
+{
+ return &freq_val[0];
+}
+
+u32 mv_ddr_freq_get(enum mv_ddr_freq freq)
+{
+ return freq_val[freq];
+}
+
+/* cas latency values per frequency for each speed bin index */
+static struct mv_ddr_cl_val_per_freq cl_table[] = {
+ /*
+ * 400M 667M 933M 311M 467M 600M 360
+ * 100M 533M 800M 1066M 333M 850M 900
+ * 1000 (the order is 100, 400, 533 etc.)
+ */
+ /* DDR3-800D */
+ { {6, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
+ /* DDR3-800E */
+ { {6, 6, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 6, 0, 6, 0} },
+ /* DDR3-1066E */
+ { {6, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 0, 5, 0, 5, 0} },
+ /* DDR3-1066F */
+ { {6, 6, 7, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6, 0, 6, 0} },
+ /* DDR3-1066G */
+ { {6, 6, 8, 0, 0, 0, 0, 6, 6, 8, 0, 0, 6, 0, 6, 0} },
+ /* DDR3-1333F* */
+ { {6, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1333G */
+ { {6, 5, 7, 8, 0, 0, 0, 5, 5, 7, 0, 8, 5, 0, 5, 0} },
+ /* DDR3-1333H */
+ { {6, 6, 8, 9, 0, 0, 0, 6, 6, 8, 0, 9, 6, 0, 6, 0} },
+ /* DDR3-1333J* */
+ { {6, 6, 8, 10, 0, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0}
+ /* DDR3-1600G* */},
+ { {6, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1600H */
+ { {6, 5, 6, 8, 9, 0, 0, 5, 5, 6, 0, 8, 5, 0, 5, 0} },
+ /* DDR3-1600J */
+ { {6, 5, 7, 9, 10, 0, 0, 5, 5, 7, 0, 9, 5, 0, 5, 0} },
+ /* DDR3-1600K */
+ { {6, 6, 8, 10, 11, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0 } },
+ /* DDR3-1866J* */
+ { {6, 5, 6, 8, 9, 11, 0, 5, 5, 6, 11, 8, 5, 0, 5, 0} },
+ /* DDR3-1866K */
+ { {6, 5, 7, 8, 10, 11, 0, 5, 5, 7, 11, 8, 5, 11, 5, 11} },
+ /* DDR3-1866L */
+ { {6, 6, 7, 9, 11, 12, 0, 6, 6, 7, 12, 9, 6, 12, 6, 12} },
+ /* DDR3-1866M* */
+ { {6, 6, 8, 10, 11, 13, 0, 6, 6, 8, 13, 10, 6, 13, 6, 13} },
+ /* DDR3-2133K* */
+ { {6, 5, 6, 7, 9, 10, 11, 5, 5, 6, 10, 7, 5, 11, 5, 11} },
+ /* DDR3-2133L */
+ { {6, 5, 6, 8, 9, 11, 12, 5, 5, 6, 11, 8, 5, 12, 5, 12} },
+ /* DDR3-2133M */
+ { {6, 5, 7, 9, 10, 12, 13, 5, 5, 7, 12, 9, 5, 13, 5, 13} },
+ /* DDR3-2133N* */
+ { {6, 6, 7, 9, 11, 13, 14, 6, 6, 7, 13, 9, 6, 14, 6, 14} },
+ /* DDR3-1333H-ext */
+ { {6, 6, 7, 9, 0, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
+ /* DDR3-1600K-ext */
+ { {6, 6, 7, 9, 11, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
+ /* DDR3-1866M-ext */
+ { {6, 6, 7, 9, 11, 13, 0, 6, 6, 7, 13, 9, 6, 13, 6, 13} },
+};
+
+u32 mv_ddr_cl_val_get(u32 index, u32 freq)
+{
+ return cl_table[index].cl_val[freq];
+}
+
+/* cas write latency values per frequency for each speed bin index */
+static struct mv_ddr_cl_val_per_freq cwl_table[] = {
+ /*
+ * 400M 667M 933M 311M 467M 600M 360
+ * 100M 533M 800M 1066M 333M 850M 900
+ * (the order is 100, 400, 533 etc.)
+ */
+ /* DDR3-800D */
+ { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
+ /* DDR3-800E */
+ { {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
+ /* DDR3-1066E */
+ { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1066F */
+ { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1066G */
+ { {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1333F* */
+ { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1333G */
+ { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1333H */
+ { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1333J* */
+ { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1600G* */
+ { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1600H */
+ { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1600J */
+ { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1600K */
+ { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1866J* */
+ { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
+ /* DDR3-1866K */
+ { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
+ /* DDR3-1866L */
+ { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
+ /* DDR3-1866M* */
+ { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
+ /* DDR3-2133K* */
+ { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
+ /* DDR3-2133L */
+ { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
+ /* DDR3-2133M */
+ { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
+ /* DDR3-2133N* */
+ { {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
+ /* DDR3-1333H-ext */
+ { {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1600K-ext */
+ { {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
+ /* DDR3-1866M-ext */
+ { {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
+};
+
+u32 mv_ddr_cwl_val_get(u32 index, u32 freq)
+{
+ return cwl_table[index].cl_val[freq];
+}
+
+u8 twr_mask_table[] = {
+ 10,
+ 10,
+ 10,
+ 10,
+ 10,
+ 1, /* 5 */
+ 2, /* 6 */
+ 3, /* 7 */
+ 4, /* 8 */
+ 10,
+ 5, /* 10 */
+ 10,
+ 6, /* 12 */
+ 10,
+ 7, /* 14 */
+ 10,
+ 0 /* 16 */
+};
+
+u8 cl_mask_table[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x2,
+ 0x4,
+ 0x6,
+ 0x8,
+ 0xa,
+ 0xc,
+ 0xe,
+ 0x1,
+ 0x3,
+ 0x5,
+ 0x5
+};
+
+u8 cwl_mask_table[] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0x1,
+ 0x2,
+ 0x3,
+ 0x4,
+ 0x5,
+ 0x6,
+ 0x7,
+ 0x8,
+ 0x9,
+ 0x9
+};
+
+/* RFC values (in ns) */
+static unsigned int rfc_table[] = {
+ 90, /* 512M */
+ 110, /* 1G */
+ 160, /* 2G */
+ 260, /* 4G */
+ 350, /* 8G */
+ 0, /* TODO: placeholder for 16-Mbit dev width */
+ 0, /* TODO: placeholder for 32-Mbit dev width */
+ 0, /* TODO: placeholder for 12-Mbit dev width */
+ 0 /* TODO: placeholder for 24-Mbit dev width */
+};
+
+u32 mv_ddr_rfc_get(u32 mem)
+{
+ return rfc_table[mem];
+}
+
+u32 speed_bin_table_t_rc[] = {
+ 50000,
+ 52500,
+ 48750,
+ 50625,
+ 52500,
+ 46500,
+ 48000,
+ 49500,
+ 51000,
+ 45000,
+ 46250,
+ 47500,
+ 48750,
+ 44700,
+ 45770,
+ 46840,
+ 47910,
+ 43285,
+ 44220,
+ 45155,
+ 46090
+};
+
+u32 speed_bin_table_t_rcd_t_rp[] = {
+ 12500,
+ 15000,
+ 11250,
+ 13125,
+ 15000,
+ 10500,
+ 12000,
+ 13500,
+ 15000,
+ 10000,
+ 11250,
+ 12500,
+ 13750,
+ 10700,
+ 11770,
+ 12840,
+ 13910,
+ 10285,
+ 11220,
+ 12155,
+ 13090,
+};
+
+enum {
+ PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
+ PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM
+};
+
+static u8 pattern_killer_pattern_table_map[KILLER_PATTERN_LENGTH * 2][2] = {
+ /*Aggressor / Victim */
+ {1, 0},
+ {0, 0},
+ {1, 0},
+ {1, 1},
+ {0, 1},
+ {0, 1},
+ {1, 0},
+ {0, 1},
+ {1, 0},
+ {0, 1},
+ {1, 0},
+ {1, 0},
+ {0, 1},
+ {1, 0},
+ {0, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 1},
+ {0, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1},
+ {0, 0},
+ {1, 1},
+ {0, 1},
+ {0, 0},
+ {0, 1},
+ {0, 1},
+ {0, 0},
+ {1, 1},
+ {1, 1},
+ {1, 0},
+ {1, 0},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+ {1, 1}
+};
+
+static u8 pattern_vref_pattern_table_map[] = {
+ /* 1 means 0xffffffff, 0 is 0x0 */
+ 0xb8,
+ 0x52,
+ 0x55,
+ 0x8a,
+ 0x33,
+ 0xa6,
+ 0x6d,
+ 0xfe
+};
+
+static struct mv_ddr_page_element page_tbl[] = {
+ /* 8-bit, 16-bit page size */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 512M */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 1G */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 2G */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 4G */
+ {MV_DDR_PAGE_SIZE_2K, MV_DDR_PAGE_SIZE_2K}, /* 8G */
+ {0, 0}, /* TODO: placeholder for 16-Mbit die capacity */
+ {0, 0}, /* TODO: placeholder for 32-Mbit die capacity */
+ {0, 0}, /* TODO: placeholder for 12-Mbit die capacity */
+ {0, 0} /* TODO: placeholder for 24-Mbit die capacity */
+};
+
+u32 mv_ddr_page_size_get(enum mv_ddr_dev_width bus_width, enum mv_ddr_die_capacity mem_size)
+{
+ if (bus_width == MV_DDR_DEV_WIDTH_8BIT)
+ return page_tbl[mem_size].page_size_8bit;
+ else
+ return page_tbl[mem_size].page_size_16bit;
+}
+
+/* Return speed Bin value for selected index and t* element */
+unsigned int mv_ddr_speed_bin_timing_get(enum mv_ddr_speed_bin index, enum mv_ddr_speed_bin_timing element)
+{
+ u32 result = 0;
+
+ switch (element) {
+ case SPEED_BIN_TRCD:
+ case SPEED_BIN_TRP:
+ result = speed_bin_table_t_rcd_t_rp[index];
+ break;
+ case SPEED_BIN_TRAS:
+ if (index <= SPEED_BIN_DDR_1066G)
+ result = 37500;
+ else if (index <= SPEED_BIN_DDR_1333J)
+ result = 36000;
+ else if (index <= SPEED_BIN_DDR_1600K)
+ result = 35000;
+ else if (index <= SPEED_BIN_DDR_1866M)
+ result = 34000;
+ else
+ result = 33000;
+ break;
+ case SPEED_BIN_TRC:
+ result = speed_bin_table_t_rc[index];
+ break;
+ case SPEED_BIN_TRRD1K:
+ if (index <= SPEED_BIN_DDR_800E)
+ result = 10000;
+ else if (index <= SPEED_BIN_DDR_1066G)
+ result = 7500;
+ else if (index <= SPEED_BIN_DDR_1600K)
+ result = 6000;
+ else
+ result = 5000;
+ break;
+ case SPEED_BIN_TRRD2K:
+ if (index <= SPEED_BIN_DDR_1066G)
+ result = 10000;
+ else if (index <= SPEED_BIN_DDR_1600K)
+ result = 7500;
+ else
+ result = 6000;
+ break;
+ case SPEED_BIN_TPD:
+ if (index < SPEED_BIN_DDR_800E)
+ result = 7500;
+ else if (index < SPEED_BIN_DDR_1333J)
+ result = 5625;
+ else
+ result = 5000;
+ break;
+ case SPEED_BIN_TFAW1K:
+ if (index <= SPEED_BIN_DDR_800E)
+ result = 40000;
+ else if (index <= SPEED_BIN_DDR_1066G)
+ result = 37500;
+ else if (index <= SPEED_BIN_DDR_1600K)
+ result = 30000;
+ else if (index <= SPEED_BIN_DDR_1866M)
+ result = 27000;
+ else
+ result = 25000;
+ break;
+ case SPEED_BIN_TFAW2K:
+ if (index <= SPEED_BIN_DDR_1066G)
+ result = 50000;
+ else if (index <= SPEED_BIN_DDR_1333J)
+ result = 45000;
+ else if (index <= SPEED_BIN_DDR_1600K)
+ result = 40000;
+ else
+ result = 35000;
+ break;
+ case SPEED_BIN_TWTR:
+ result = 7500;
+ break;
+ case SPEED_BIN_TRTP:
+ result = 7500;
+ break;
+ case SPEED_BIN_TWR:
+ result = 15000;
+ break;
+ case SPEED_BIN_TMOD:
+ result = 15000;
+ break;
+ case SPEED_BIN_TXPDLL:
+ result = 24000;
+ break;
+ case SPEED_BIN_TXSDLL:
+ result = 512;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static inline u32 pattern_table_get_killer_word(u8 dqs, u8 index)
+{
+ u8 i, byte = 0;
+ u8 role;
+
+ for (i = 0; i < 8; i++) {
+ role = (i == dqs) ?
+ (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
+ (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
+ byte |= pattern_killer_pattern_table_map[index][role] << i;
+ }
+
+ return byte | (byte << 8) | (byte << 16) | (byte << 24);
+}
+
+static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
+{
+ u8 i, byte0 = 0, byte1 = 0;
+ u8 role;
+
+ for (i = 0; i < 8; i++) {
+ role = (i == dqs) ?
+ (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
+ (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
+ byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i;
+ byte1 |= pattern_killer_pattern_table_map[index * 2 + 1][role] << i;
+ }
+
+ return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24);
+}
+
+static inline u32 pattern_table_get_sso_word(u8 sso, u8 index)
+{
+ u8 step = sso + 1;
+
+ if (0 == ((index / step) & 1))
+ return 0x0;
+ else
+ return 0xffffffff;
+}
+
+static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index)
+{
+ u8 byte = (1 << bit);
+
+ if ((index & 1) == 1)
+ byte = ~byte;
+
+ return byte | (byte << 8) | (byte << 16) | (byte << 24);
+
+}
+
+static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index)
+{
+ u8 byte = (1 << bit);
+
+ if ((index & 1) == 1)
+ byte = 0;
+
+ return byte | (byte << 8) | (byte << 16) | (byte << 24);
+}
+
+static inline u32 pattern_table_get_isi_word(u8 index)
+{
+ u8 i0 = index % 32;
+ u8 i1 = index % 8;
+ u32 word;
+
+ if (i0 > 15)
+ word = ((i1 == 5) | (i1 == 7)) ? 0xffffffff : 0x0;
+ else
+ word = (i1 == 6) ? 0xffffffff : 0x0;
+
+ word = ((i0 % 16) > 7) ? ~word : word;
+
+ return word;
+}
+
+static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index)
+{
+ u8 byte = (1 << bit);
+
+ if ((index & 1) == 1)
+ byte = ~byte;
+
+ return byte | (byte << 8) | ((~byte) << 16) | ((~byte) << 24);
+}
+
+static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index)
+{
+ u8 byte = (1 << bit);
+
+ if ((index & 1) == 0)
+ return (byte << 16) | (byte << 24);
+ else
+ return byte | (byte << 8);
+}
+
+static inline u32 pattern_table_get_isi_word16(u8 index)
+{
+ u8 i0 = index % 16;
+ u8 i1 = index % 4;
+ u32 word;
+
+ if (i0 > 7)
+ word = (i1 > 1) ? 0x0000ffff : 0x0;
+ else
+ word = (i1 == 3) ? 0xffff0000 : 0x0;
+
+ word = ((i0 % 8) > 3) ? ~word : word;
+
+ return word;
+}
+
+static inline u32 pattern_table_get_vref_word(u8 index)
+{
+ if (0 == ((pattern_vref_pattern_table_map[index / 8] >>
+ (index % 8)) & 1))
+ return 0x0;
+ else
+ return 0xffffffff;
+}
+
+static inline u32 pattern_table_get_vref_word16(u8 index)
+{
+ if (0 == pattern_killer_pattern_table_map
+ [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
+ 0 == pattern_killer_pattern_table_map
+ [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
+ return 0x00000000;
+ else if (1 == pattern_killer_pattern_table_map
+ [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
+ 0 == pattern_killer_pattern_table_map
+ [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
+ return 0xffff0000;
+ else if (0 == pattern_killer_pattern_table_map
+ [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
+ 1 == pattern_killer_pattern_table_map
+ [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
+ return 0x0000ffff;
+ else
+ return 0xffffffff;
+}
+
+static inline u32 pattern_table_get_static_pbs_word(u8 index)
+{
+ u16 temp;
+
+ temp = ((0x00ff << (index / 3)) & 0xff00) >> 8;
+
+ return temp | (temp << 8) | (temp << 16) | (temp << 24);
+}
+
+u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
+{
+ u32 pattern = 0;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) {
+ /* 32/64-bit patterns */
+ switch (type) {
+ case PATTERN_PBS1:
+ case PATTERN_PBS2:
+ if (index == 0 || index == 2 || index == 5 ||
+ index == 7)
+ pattern = PATTERN_55;
+ else
+ pattern = PATTERN_AA;
+ break;
+ case PATTERN_PBS3:
+ if (0 == (index & 1))
+ pattern = PATTERN_55;
+ else
+ pattern = PATTERN_AA;
+ break;
+ case PATTERN_RL:
+ if (index < 6)
+ pattern = PATTERN_00;
+ else
+ pattern = PATTERN_80;
+ break;
+ case PATTERN_STATIC_PBS:
+ pattern = pattern_table_get_static_pbs_word(index);
+ break;
+ case PATTERN_KILLER_DQ0:
+ case PATTERN_KILLER_DQ1:
+ case PATTERN_KILLER_DQ2:
+ case PATTERN_KILLER_DQ3:
+ case PATTERN_KILLER_DQ4:
+ case PATTERN_KILLER_DQ5:
+ case PATTERN_KILLER_DQ6:
+ case PATTERN_KILLER_DQ7:
+ pattern = pattern_table_get_killer_word(
+ (u8)(type - PATTERN_KILLER_DQ0), index);
+ break;
+ case PATTERN_RL2:
+ if (index < 6)
+ pattern = PATTERN_00;
+ else
+ pattern = PATTERN_01;
+ break;
+ case PATTERN_TEST:
+ if (index > 1 && index < 6)
+ pattern = PATTERN_00;
+ else
+ pattern = PATTERN_FF;
+ break;
+ case PATTERN_FULL_SSO0:
+ case PATTERN_FULL_SSO1:
+ case PATTERN_FULL_SSO2:
+ case PATTERN_FULL_SSO3:
+ pattern = pattern_table_get_sso_word(
+ (u8)(type - PATTERN_FULL_SSO0), index);
+ break;
+ case PATTERN_VREF:
+ pattern = pattern_table_get_vref_word(index);
+ break;
+ case PATTERN_SSO_FULL_XTALK_DQ0:
+ case PATTERN_SSO_FULL_XTALK_DQ1:
+ case PATTERN_SSO_FULL_XTALK_DQ2:
+ case PATTERN_SSO_FULL_XTALK_DQ3:
+ case PATTERN_SSO_FULL_XTALK_DQ4:
+ case PATTERN_SSO_FULL_XTALK_DQ5:
+ case PATTERN_SSO_FULL_XTALK_DQ6:
+ case PATTERN_SSO_FULL_XTALK_DQ7:
+ pattern = pattern_table_get_sso_full_xtalk_word(
+ (u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index);
+ break;
+ case PATTERN_SSO_XTALK_FREE_DQ0:
+ case PATTERN_SSO_XTALK_FREE_DQ1:
+ case PATTERN_SSO_XTALK_FREE_DQ2:
+ case PATTERN_SSO_XTALK_FREE_DQ3:
+ case PATTERN_SSO_XTALK_FREE_DQ4:
+ case PATTERN_SSO_XTALK_FREE_DQ5:
+ case PATTERN_SSO_XTALK_FREE_DQ6:
+ case PATTERN_SSO_XTALK_FREE_DQ7:
+ pattern = pattern_table_get_sso_xtalk_free_word(
+ (u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index);
+ break;
+ case PATTERN_ISI_XTALK_FREE:
+ pattern = pattern_table_get_isi_word(index);
+ break;
+ default:
+ printf("error: %s: unsupported pattern type [%d] found\n",
+ __func__, (int)type);
+ pattern = 0;
+ break;
+ }
+ } else {
+ /* 16bit patterns */
+ switch (type) {
+ case PATTERN_PBS1:
+ case PATTERN_PBS2:
+ case PATTERN_PBS3:
+ pattern = PATTERN_55AA;
+ break;
+ case PATTERN_RL:
+ if (index < 3)
+ pattern = PATTERN_00;
+ else
+ pattern = PATTERN_80;
+ break;
+ case PATTERN_STATIC_PBS:
+ pattern = PATTERN_00FF;
+ break;
+ case PATTERN_KILLER_DQ0:
+ case PATTERN_KILLER_DQ1:
+ case PATTERN_KILLER_DQ2:
+ case PATTERN_KILLER_DQ3:
+ case PATTERN_KILLER_DQ4:
+ case PATTERN_KILLER_DQ5:
+ case PATTERN_KILLER_DQ6:
+ case PATTERN_KILLER_DQ7:
+ pattern = pattern_table_get_killer_word16(
+ (u8)(type - PATTERN_KILLER_DQ0), index);
+ break;
+ case PATTERN_RL2:
+ if (index < 3)
+ pattern = PATTERN_00;
+ else
+ pattern = PATTERN_01;
+ break;
+ case PATTERN_TEST:
+ if ((index == 0) || (index == 3))
+ pattern = 0x00000000;
+ else
+ pattern = 0xFFFFFFFF;
+ break;
+ case PATTERN_FULL_SSO0:
+ pattern = 0x0000ffff;
+ break;
+ case PATTERN_FULL_SSO1:
+ case PATTERN_FULL_SSO2:
+ case PATTERN_FULL_SSO3:
+ pattern = pattern_table_get_sso_word(
+ (u8)(type - PATTERN_FULL_SSO1), index);
+ break;
+ case PATTERN_VREF:
+ pattern = pattern_table_get_vref_word16(index);
+ break;
+ case PATTERN_SSO_FULL_XTALK_DQ0:
+ case PATTERN_SSO_FULL_XTALK_DQ1:
+ case PATTERN_SSO_FULL_XTALK_DQ2:
+ case PATTERN_SSO_FULL_XTALK_DQ3:
+ case PATTERN_SSO_FULL_XTALK_DQ4:
+ case PATTERN_SSO_FULL_XTALK_DQ5:
+ case PATTERN_SSO_FULL_XTALK_DQ6:
+ case PATTERN_SSO_FULL_XTALK_DQ7:
+ pattern = pattern_table_get_sso_full_xtalk_word16(
+ (u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index);
+ break;
+ case PATTERN_SSO_XTALK_FREE_DQ0:
+ case PATTERN_SSO_XTALK_FREE_DQ1:
+ case PATTERN_SSO_XTALK_FREE_DQ2:
+ case PATTERN_SSO_XTALK_FREE_DQ3:
+ case PATTERN_SSO_XTALK_FREE_DQ4:
+ case PATTERN_SSO_XTALK_FREE_DQ5:
+ case PATTERN_SSO_XTALK_FREE_DQ6:
+ case PATTERN_SSO_XTALK_FREE_DQ7:
+ pattern = pattern_table_get_sso_xtalk_free_word16(
+ (u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index);
+ break;
+ case PATTERN_ISI_XTALK_FREE:
+ pattern = pattern_table_get_isi_word16(index);
+ break;
+ default:
+ if (((int)type == 29) || ((int)type == 30))
+ break;
+
+ printf("error: %s: unsupported pattern type [%d] found\n",
+ __func__, (int)type);
+ pattern = 0;
+ break;
+ }
+ }
+
+ return pattern;
+}
+
+/* Device attribute functions */
+void ddr3_tip_dev_attr_init(u32 dev_num)
+{
+ u32 attr_id;
+
+ for (attr_id = 0; attr_id < MV_ATTR_LAST; attr_id++)
+ ddr_dev_attributes[attr_id] = 0xFF;
+
+ ddr_dev_attr_init_done = 1;
+}
+
+u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id)
+{
+ if (ddr_dev_attr_init_done == 0)
+ ddr3_tip_dev_attr_init(dev_num);
+
+ return ddr_dev_attributes[attr_id];
+}
+
+void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value)
+{
+ if (ddr_dev_attr_init_done == 0)
+ ddr3_tip_dev_attr_init(dev_num);
+
+ ddr_dev_attributes[attr_id] = value;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c
new file mode 100644
index 000000000..58ffb2050
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c
@@ -0,0 +1,677 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_regs.h"
+
+#define VREF_INITIAL_STEP 3
+#define VREF_SECOND_STEP 1
+#define VREF_MAX_INDEX 7
+#define MAX_VALUE (1024 - 1)
+#define MIN_VALUE (-MAX_VALUE)
+#define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0x1f)
+
+u32 ca_delay;
+int ddr3_tip_centr_skip_min_win_check = 0;
+u8 current_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
+u8 last_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
+u16 current_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
+u16 last_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
+u8 lim_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
+u8 interface_state[MAX_INTERFACE_NUM];
+u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 vref_window_size_th = 12;
+
+static u8 pup_st[MAX_BUS_NUM][MAX_INTERFACE_NUM];
+
+static u32 rd_sample_mask[] = {
+ 0,
+ 8,
+ 16,
+ 24
+};
+
+#define VREF_STEP_1 0
+#define VREF_STEP_2 1
+#define VREF_CONVERGE 2
+
+/*
+ * ODT additional timing
+ */
+int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id)
+{
+ u32 cs_num = 0, max_read_sample = 0, min_read_sample = 0x1f;
+ u32 data_read[MAX_INTERFACE_NUM] = { 0 };
+ u32 read_sample[MAX_CS_NUM];
+ u32 val;
+ u32 pup_index;
+ int max_phase = MIN_VALUE, current_phase;
+ enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
+ u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+ unsigned int max_cs = mv_ddr_cs_num_get();
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DUNIT_ODT_CTRL_REG,
+ 0 << 8, 0x3 << 8));
+ CHECK_STATUS(ddr3_tip_if_read(dev_num, access_type, if_id,
+ RD_DATA_SMPL_DLYS_REG,
+ data_read, MASK_ALL_BITS));
+ val = data_read[if_id];
+
+ for (cs_num = 0; cs_num < max_cs; cs_num++) {
+ read_sample[cs_num] = GET_RD_SAMPLE_DELAY(val, cs_num);
+
+ /* find maximum of read_samples */
+ if (read_sample[cs_num] >= max_read_sample) {
+ if (read_sample[cs_num] == max_read_sample)
+ max_phase = MIN_VALUE;
+ else
+ max_read_sample = read_sample[cs_num];
+
+ for (pup_index = 0;
+ pup_index < octets_per_if_num;
+ pup_index++) {
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup_index,
+ DDR_PHY_DATA,
+ RL_PHY_REG(cs_num),
+ &val));
+
+ current_phase = ((int)val & 0xe0) >> 6;
+ if (current_phase >= max_phase)
+ max_phase = current_phase;
+ }
+ }
+
+ /* find minimum */
+ if (read_sample[cs_num] < min_read_sample)
+ min_read_sample = read_sample[cs_num];
+ }
+
+ min_read_sample = min_read_sample + 2;
+ max_read_sample = max_read_sample + 7 + (max_phase + 1) / 2 + 1;
+ if (min_read_sample >= 0xf)
+ min_read_sample = 0xf;
+ if (max_read_sample >= 0x1f)
+ max_read_sample = 0x1f;
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DDR_ODT_TIMING_LOW_REG,
+ ((min_read_sample - 1) << 12),
+ 0xf << 12));
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DDR_ODT_TIMING_LOW_REG,
+ (max_read_sample << 16),
+ 0x1f << 16));
+
+ return MV_OK;
+}
+
+int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4])
+{
+ u32 reg_pup = RESULT_PHY_REG;
+ u32 reg_data;
+ u32 cs_num;
+ int i;
+
+ cs_num = 0;
+
+ /* TBD */
+ reg_pup += cs_num;
+
+ for (i = 0; i < 4; i++) {
+ CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST, i,
+ DDR_PHY_DATA, reg_pup,
+ &reg_data));
+ res[i] = (reg_data >> RESULT_PHY_RX_OFFS) & 0x1f;
+ }
+
+ return 0;
+}
+
+/*
+ * This algorithm deals with the vertical optimum from Voltage point of view
+ * of the sample signal.
+ * Voltage sample point can improve the Eye / window size of the bit and the
+ * pup.
+ * The problem is that it is tune for all DQ the same so there isn't any
+ * PBS like code.
+ * It is more like centralization.
+ * But because we don't have The training SM support we do it a bit more
+ * smart search to save time.
+ */
+int ddr3_tip_vref(u32 dev_num)
+{
+ /*
+ * The Vref register have non linear order. Need to check what will be
+ * in future projects.
+ */
+ u32 vref_map[8] = {
+ 1, 2, 3, 4, 5, 6, 7, 0
+ };
+ /* State and parameter definitions */
+ u32 initial_step = VREF_INITIAL_STEP;
+ /* need to be assign with minus ????? */
+ u32 second_step = VREF_SECOND_STEP;
+ u32 algo_run_flag = 0, currrent_vref = 0;
+ u32 while_count = 0;
+ u32 pup = 0, if_id = 0, num_pup = 0, rep = 0;
+ u32 val = 0;
+ u32 reg_addr = 0xa8;
+ u32 copy_start_pattern, copy_end_pattern;
+ enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
+ u8 res[4];
+ 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();
+
+ CHECK_STATUS(ddr3_tip_special_rx(dev_num));
+
+ /* save start/end pattern */
+ copy_start_pattern = start_pattern;
+ copy_end_pattern = end_pattern;
+
+ /* set vref as centralization pattern */
+ start_pattern = PATTERN_VREF;
+ end_pattern = PATTERN_VREF;
+
+ /* init params */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0;
+ pup < octets_per_if_num; pup++) {
+ current_vref[pup][if_id] = 0;
+ last_vref[pup][if_id] = 0;
+ lim_vref[pup][if_id] = 0;
+ current_valid_window[pup][if_id] = 0;
+ last_valid_window[pup][if_id] = 0;
+ if (vref_window_size[if_id][pup] >
+ vref_window_size_th) {
+ pup_st[pup][if_id] = VREF_CONVERGE;
+ DEBUG_TRAINING_HW_ALG(
+ DEBUG_LEVEL_INFO,
+ ("VREF config, IF[ %d ]pup[ %d ] - Vref tune not requered (%d)\n",
+ if_id, pup, __LINE__));
+ } else {
+ pup_st[pup][if_id] = VREF_STEP_1;
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr, &val));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST,
+ pup, DDR_PHY_DATA, reg_addr,
+ (val & (~0xf)) | vref_map[0]));
+ DEBUG_TRAINING_HW_ALG(
+ DEBUG_LEVEL_INFO,
+ ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
+ if_id, pup,
+ (val & (~0xf)) | vref_map[0],
+ __LINE__));
+ }
+ }
+ interface_state[if_id] = 0;
+ }
+
+ /* TODO: Set number of active interfaces */
+ num_pup = octets_per_if_num * MAX_INTERFACE_NUM;
+
+ while ((algo_run_flag <= num_pup) & (while_count < 10)) {
+ while_count++;
+ for (rep = 1; rep < 4; rep++) {
+ ddr3_tip_centr_skip_min_win_check = 1;
+ ddr3_tip_centralization_rx(dev_num);
+ ddr3_tip_centr_skip_min_win_check = 0;
+
+ /* Read Valid window results only for non converge pups */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (interface_state[if_id] != 4) {
+ get_valid_win_rx(dev_num, if_id, res);
+ for (pup = 0;
+ pup < octets_per_if_num;
+ pup++) {
+ VALIDATE_BUS_ACTIVE
+ (tm->bus_act_mask, pup);
+ if (pup_st[pup]
+ [if_id] ==
+ VREF_CONVERGE)
+ continue;
+
+ current_valid_window[pup]
+ [if_id] =
+ (current_valid_window[pup]
+ [if_id] * (rep - 1) +
+ 1000 * res[pup]) / rep;
+ }
+ }
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ DEBUG_TRAINING_HW_ALG(
+ DEBUG_LEVEL_TRACE,
+ ("current_valid_window: IF[ %d ] - ", if_id));
+
+ for (pup = 0;
+ pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
+ ("%d ",
+ current_valid_window
+ [pup][if_id]));
+ }
+ DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("\n"));
+ }
+
+ /* Compare results and respond as function of state */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0;
+ pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
+ ("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n",
+ if_id, pup,
+ pup_st[pup]
+ [if_id], __LINE__));
+
+ if (pup_st[pup][if_id] == VREF_CONVERGE)
+ continue;
+
+ DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
+ ("I/F[ %d ], pup[ %d ] CHECK progress - Current %d Last %d, limit VREF %d (%d)\n",
+ if_id, pup,
+ current_valid_window[pup]
+ [if_id],
+ last_valid_window[pup]
+ [if_id], lim_vref[pup]
+ [if_id], __LINE__));
+
+ /*
+ * The -1 is for solution resolution +/- 1 tap
+ * of ADLL
+ */
+ if (current_valid_window[pup][if_id] + 200 >=
+ (last_valid_window[pup][if_id])) {
+ if (pup_st[pup][if_id] == VREF_STEP_1) {
+ /*
+ * We stay in the same state and
+ * step just update the window
+ * size (take the max) and Vref
+ */
+ if (current_vref[pup]
+ [if_id] == VREF_MAX_INDEX) {
+ /*
+ * If we step to the end
+ * and didn't converge
+ * to some particular
+ * better Vref value
+ * define the pup as
+ * converge and step
+ * back to nominal
+ * Vref.
+ */
+ pup_st[pup]
+ [if_id] =
+ VREF_CONVERGE;
+ algo_run_flag++;
+ interface_state
+ [if_id]++;
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
+ if_id, pup,
+ current_vref[pup]
+ [if_id],
+ __LINE__));
+ } else {
+ /* continue to update the Vref index */
+ current_vref[pup]
+ [if_id] =
+ ((current_vref[pup]
+ [if_id] +
+ initial_step) >
+ VREF_MAX_INDEX) ?
+ VREF_MAX_INDEX
+ : (current_vref[pup]
+ [if_id] +
+ initial_step);
+ if (current_vref[pup]
+ [if_id] ==
+ VREF_MAX_INDEX) {
+ pup_st[pup]
+ [if_id]
+ =
+ VREF_STEP_2;
+ }
+ lim_vref[pup]
+ [if_id] =
+ last_vref[pup]
+ [if_id] =
+ current_vref[pup]
+ [if_id];
+ }
+
+ last_valid_window[pup]
+ [if_id] =
+ GET_MAX(current_valid_window
+ [pup][if_id],
+ last_valid_window
+ [pup]
+ [if_id]);
+
+ /* update the Vref for next stage */
+ currrent_vref =
+ current_vref[pup]
+ [if_id];
+ CHECK_STATUS
+ (ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ &val));
+ CHECK_STATUS
+ (ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ (val & (~0xf)) |
+ vref_map[currrent_vref]));
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
+ if_id, pup,
+ (val & (~0xf)) |
+ vref_map[currrent_vref],
+ __LINE__));
+ } else if (pup_st[pup][if_id]
+ == VREF_STEP_2) {
+ /*
+ * We keep on search back with
+ * the same step size.
+ */
+ last_valid_window[pup]
+ [if_id] =
+ GET_MAX(current_valid_window
+ [pup][if_id],
+ last_valid_window
+ [pup]
+ [if_id]);
+ last_vref[pup][if_id] =
+ current_vref[pup]
+ [if_id];
+
+ /* we finish all search space */
+ if ((current_vref[pup]
+ [if_id] - second_step) == lim_vref[pup][if_id]) {
+ /*
+ * If we step to the end
+ * and didn't converge
+ * to some particular
+ * better Vref value
+ * define the pup as
+ * converge and step
+ * back to nominal
+ * Vref.
+ */
+ pup_st[pup]
+ [if_id] =
+ VREF_CONVERGE;
+ algo_run_flag++;
+
+ interface_state
+ [if_id]++;
+
+ current_vref[pup]
+ [if_id] =
+ (current_vref[pup]
+ [if_id] -
+ second_step);
+
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
+ if_id, pup,
+ current_vref[pup]
+ [if_id],
+ __LINE__));
+ } else
+ /* we finish all search space */
+ if (current_vref[pup]
+ [if_id] ==
+ lim_vref[pup]
+ [if_id]) {
+ /*
+ * If we step to the end
+ * and didn't converge
+ * to some particular
+ * better Vref value
+ * define the pup as
+ * converge and step
+ * back to nominal
+ * Vref.
+ */
+ pup_st[pup]
+ [if_id] =
+ VREF_CONVERGE;
+
+ algo_run_flag++;
+ interface_state
+ [if_id]++;
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
+ if_id, pup,
+ current_vref[pup]
+ [if_id],
+ __LINE__));
+ } else {
+ current_vref[pup]
+ [if_id] =
+ current_vref[pup]
+ [if_id] -
+ second_step;
+ }
+
+ /* Update the Vref for next stage */
+ currrent_vref =
+ current_vref[pup]
+ [if_id];
+ CHECK_STATUS
+ (ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ &val));
+ CHECK_STATUS
+ (ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ (val & (~0xf)) |
+ vref_map[currrent_vref]));
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
+ if_id, pup,
+ (val & (~0xf)) |
+ vref_map[currrent_vref],
+ __LINE__));
+ }
+ } else {
+ /* we change state and change step */
+ if (pup_st[pup][if_id] == VREF_STEP_1) {
+ pup_st[pup][if_id] =
+ VREF_STEP_2;
+ lim_vref[pup][if_id] =
+ current_vref[pup]
+ [if_id] - initial_step;
+ last_valid_window[pup]
+ [if_id] =
+ current_valid_window[pup]
+ [if_id];
+ last_vref[pup][if_id] =
+ current_vref[pup]
+ [if_id];
+ current_vref[pup][if_id] =
+ last_vref[pup][if_id] -
+ second_step;
+
+ /* Update the Vref for next stage */
+ CHECK_STATUS
+ (ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ &val));
+ CHECK_STATUS
+ (ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ (val & (~0xf)) |
+ vref_map[current_vref[pup]
+ [if_id]]));
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
+ if_id, pup,
+ (val & (~0xf)) |
+ vref_map[current_vref[pup]
+ [if_id]],
+ __LINE__));
+
+ } else if (pup_st[pup][if_id] == VREF_STEP_2) {
+ /*
+ * The last search was the max
+ * point set value and exit
+ */
+ CHECK_STATUS
+ (ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ &val));
+ CHECK_STATUS
+ (ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ (val & (~0xf)) |
+ vref_map[last_vref[pup]
+ [if_id]]));
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
+ if_id, pup,
+ (val & (~0xf)) |
+ vref_map[last_vref[pup]
+ [if_id]],
+ __LINE__));
+ pup_st[pup][if_id] =
+ VREF_CONVERGE;
+ algo_run_flag++;
+ interface_state[if_id]++;
+ DEBUG_TRAINING_HW_ALG
+ (DEBUG_LEVEL_TRACE,
+ ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
+ if_id, pup,
+ current_vref[pup]
+ [if_id], __LINE__));
+ }
+ }
+ }
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0;
+ pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr, &val));
+ DEBUG_TRAINING_HW_ALG(
+ DEBUG_LEVEL_INFO,
+ ("FINAL values: I/F[ %d ], pup[ %d ] - Vref = %X (%d)\n",
+ if_id, pup, val, __LINE__));
+ }
+ }
+
+ flow_result[if_id] = TEST_SUCCESS;
+
+ /* restore start/end pattern */
+ start_pattern = copy_start_pattern;
+ end_pattern = copy_end_pattern;
+
+ return 0;
+}
+
+/*
+ * CK/CA Delay
+ */
+int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap)
+{
+ u32 if_id = 0;
+ u32 ck_num_adll_tap = 0, ca_num_adll_tap = 0, data = 0;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /*
+ * ck_delay_table is delaying the of the clock signal only.
+ * (to overcome timing issues between_c_k & command/address signals)
+ */
+ /*
+ * ca_delay is delaying the of the entire command & Address signals
+ * (include Clock signal to overcome DGL error on the Clock versus
+ * the DQS).
+ */
+
+ /* Calc ADLL Tap */
+ if (ck_delay == PARAM_UNDEFINED)
+ DEBUG_TRAINING_HW_ALG(
+ DEBUG_LEVEL_ERROR,
+ ("ERROR: ck_delay is not initialized!\n"));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ /* Calc delay ps in ADLL tap */
+ ck_num_adll_tap = ck_delay / adll_tap;
+ ca_num_adll_tap = ca_delay / adll_tap;
+
+ data = (ck_num_adll_tap & 0x3f) +
+ ((ca_num_adll_tap & 0x3f) << 10);
+
+ /*
+ * Set the ADLL number to the CK ADLL for Interfaces for
+ * all Pup
+ */
+ DEBUG_TRAINING_HW_ALG(
+ DEBUG_LEVEL_TRACE,
+ ("ck_num_adll_tap %d ca_num_adll_tap %d adll_tap %d\n",
+ ck_num_adll_tap, ca_num_adll_tap, adll_tap));
+
+ CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_CONTROL,
+ 0x0, data));
+ }
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.h
new file mode 100644
index 000000000..fe0436668
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_HW_ALGO_H_
+#define _DDR3_TRAINING_HW_ALGO_H_
+
+int ddr3_tip_vref(u32 dev_num);
+int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id);
+int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap);
+
+#endif /* _DDR3_TRAINING_HW_ALGO_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip.h
new file mode 100644
index 000000000..056c21497
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_H_
+#define _DDR3_TRAINING_IP_H_
+
+#include "ddr_topology_def.h"
+
+#define TIP_ENG_LOCK 0x02000000
+#define TIP_TX_DLL_RANGE_MAX 64
+
+#define GET_MIN(arg1, arg2) ((arg1) < (arg2)) ? (arg1) : (arg2)
+#define GET_MAX(arg1, arg2) ((arg1) < (arg2)) ? (arg2) : (arg1)
+
+#define INIT_CONTROLLER_MASK_BIT 0x00000001
+#define STATIC_LEVELING_MASK_BIT 0x00000002
+#define SET_LOW_FREQ_MASK_BIT 0x00000004
+#define LOAD_PATTERN_MASK_BIT 0x00000008
+#define SET_MEDIUM_FREQ_MASK_BIT 0x00000010
+#define WRITE_LEVELING_MASK_BIT 0x00000020
+#define LOAD_PATTERN_2_MASK_BIT 0x00000040
+#define READ_LEVELING_MASK_BIT 0x00000080
+#define SW_READ_LEVELING_MASK_BIT 0x00000100
+#define WRITE_LEVELING_SUPP_MASK_BIT 0x00000200
+#define PBS_RX_MASK_BIT 0x00000400
+#define PBS_TX_MASK_BIT 0x00000800
+#define SET_TARGET_FREQ_MASK_BIT 0x00001000
+#define ADJUST_DQS_MASK_BIT 0x00002000
+#define WRITE_LEVELING_TF_MASK_BIT 0x00004000
+#define LOAD_PATTERN_HIGH_MASK_BIT 0x00008000
+#define READ_LEVELING_TF_MASK_BIT 0x00010000
+#define WRITE_LEVELING_SUPP_TF_MASK_BIT 0x00020000
+#define DM_PBS_TX_MASK_BIT 0x00040000
+#define RL_DQS_BURST_MASK_BIT 0x00080000
+#define CENTRALIZATION_RX_MASK_BIT 0x00100000
+#define CENTRALIZATION_TX_MASK_BIT 0x00200000
+#define TX_EMPHASIS_MASK_BIT 0x00400000
+#define PER_BIT_READ_LEVELING_TF_MASK_BIT 0x00800000
+#define VREF_CALIBRATION_MASK_BIT 0x01000000
+#define WRITE_LEVELING_LF_MASK_BIT 0x02000000
+
+/* DDR4 Specific Training Mask bits */
+
+enum hws_result {
+ TEST_FAILED = 0,
+ TEST_SUCCESS = 1,
+ NO_TEST_DONE = 2
+};
+
+enum hws_training_result {
+ RESULT_PER_BIT,
+ RESULT_PER_BYTE
+};
+
+enum auto_tune_stage {
+ INIT_CONTROLLER,
+ STATIC_LEVELING,
+ SET_LOW_FREQ,
+ LOAD_PATTERN,
+ SET_MEDIUM_FREQ,
+ WRITE_LEVELING,
+ LOAD_PATTERN_2,
+ READ_LEVELING,
+ WRITE_LEVELING_SUPP,
+ PBS_RX,
+ PBS_TX,
+ SET_TARGET_FREQ,
+ ADJUST_DQS,
+ WRITE_LEVELING_TF,
+ READ_LEVELING_TF,
+ WRITE_LEVELING_SUPP_TF,
+ DM_PBS_TX,
+ VREF_CALIBRATION,
+ CENTRALIZATION_RX,
+ CENTRALIZATION_TX,
+ TX_EMPHASIS,
+ LOAD_PATTERN_HIGH,
+ PER_BIT_READ_LEVELING_TF,
+ WRITE_LEVELING_LF,
+ MAX_STAGE_LIMIT
+};
+
+enum hws_access_type {
+ ACCESS_TYPE_UNICAST = 0,
+ ACCESS_TYPE_MULTICAST = 1
+};
+
+enum hws_algo_type {
+ ALGO_TYPE_DYNAMIC,
+ ALGO_TYPE_STATIC
+};
+
+struct init_cntr_param {
+ int is_ctrl64_bit;
+ int do_mrs_phy;
+ int init_phy;
+ int msys_init;
+};
+
+struct pattern_info {
+ u8 num_of_phases_tx;
+ u8 tx_burst_size;
+ u8 delay_between_bursts;
+ u8 num_of_phases_rx;
+ u32 start_addr;
+ u8 pattern_len;
+};
+
+struct cs_element {
+ u8 cs_num;
+ u8 num_of_cs;
+};
+
+struct hws_tip_freq_config_info {
+ u8 is_supported;
+ u8 bw_per_freq;
+ u8 rate_per_freq;
+};
+
+struct hws_cs_config_info {
+ u32 cs_reg_value;
+ u32 cs_cbe_value;
+};
+
+struct dfx_access {
+ u8 pipe;
+ u8 client;
+};
+
+struct hws_xsb_info {
+ struct dfx_access *dfx_table;
+};
+
+int ddr3_tip_register_dq_table(u32 dev_num, u32 *table);
+int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable);
+int hws_ddr3_tip_init_controller(u32 dev_num,
+ struct init_cntr_param *init_cntr_prm);
+int hws_ddr3_tip_load_topology_map(u32 dev_num,
+ struct mv_ddr_topology_map *topology);
+int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type);
+int ddr3_tip_is_pup_lock(u32 *pup_buf, enum hws_training_result read_mode);
+u8 ddr3_tip_get_buf_min(u8 *buf_ptr);
+u8 ddr3_tip_get_buf_max(u8 *buf_ptr);
+#endif /* _DDR3_TRAINING_IP_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h
new file mode 100644
index 000000000..38058cba8
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_BIST_H_
+#define _DDR3_TRAINING_IP_BIST_H_
+
+#include "ddr3_training_ip.h"
+
+enum hws_bist_operation {
+ BIST_STOP = 0,
+ BIST_START = 1
+};
+
+enum hws_stress_jump {
+ STRESS_NONE = 0,
+ STRESS_ENABLE = 1
+};
+
+enum hws_pattern_duration {
+ DURATION_SINGLE = 0,
+ DURATION_STOP_AT_FAIL = 1,
+ DURATION_ADDRESS = 2,
+ DURATION_CONT = 4
+};
+
+struct bist_result {
+ u32 bist_error_cnt;
+ u32 bist_fail_low;
+ u32 bist_fail_high;
+ u32 bist_last_fail_addr;
+};
+
+int ddr3_tip_bist_read_result(u32 dev_num, u32 if_id,
+ struct bist_result *pst_bist_result);
+int ddr3_tip_bist_activate(u32 dev_num, enum hws_pattern pattern,
+ enum hws_access_type access_type,
+ u32 if_num, enum hws_dir direction,
+ enum hws_stress_jump addr_stress_jump,
+ enum hws_pattern_duration duration,
+ enum hws_bist_operation oper_type,
+ u32 offset, u32 cs_num, u32 pattern_addr_length);
+int hws_ddr3_run_bist(u32 dev_num, enum hws_pattern pattern, u32 *result,
+ u32 cs_num);
+int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction,
+ u32 mode);
+int ddr3_tip_run_leveling_sweep_test(int dev_num, u32 repeat_num,
+ u32 direction, u32 mode);
+int ddr3_tip_print_regs(u32 dev_num);
+int ddr3_tip_reg_dump(u32 dev_num);
+int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 read_type,
+ u32 burst_length);
+int mv_ddr_dm_to_dq_diff_get(u8 adll_byte_high, u8 adll_byte_low, u8 *vw_vector,
+ int *delta_h_adll, int *delta_l_adll);
+int mv_ddr_dm_vw_get(enum hws_pattern pattern, u32 cs, u8 *vw_vector);
+#endif /* _DDR3_TRAINING_IP_BIST_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_centralization.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_centralization.h
new file mode 100644
index 000000000..392842a10
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_centralization.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_CENTRALIZATION_H
+#define _DDR3_TRAINING_IP_CENTRALIZATION_H
+
+int ddr3_tip_centralization_tx(u32 dev_num);
+int ddr3_tip_centralization_rx(u32 dev_num);
+int ddr3_tip_print_centralization_result(u32 dev_num);
+int ddr3_tip_special_rx(u32 dev_num);
+
+#endif /* _DDR3_TRAINING_IP_CENTRALIZATION_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h
new file mode 100644
index 000000000..e28b7ecee
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_DB_H_
+#define _DDR3_TRAINING_IP_DB_H_
+
+enum hws_pattern {
+ PATTERN_PBS1,
+ PATTERN_PBS2,
+ PATTERN_PBS3,
+ PATTERN_TEST,
+ PATTERN_RL,
+ PATTERN_RL2,
+ PATTERN_STATIC_PBS,
+ PATTERN_KILLER_DQ0,
+ PATTERN_KILLER_DQ1,
+ PATTERN_KILLER_DQ2,
+ PATTERN_KILLER_DQ3,
+ PATTERN_KILLER_DQ4,
+ PATTERN_KILLER_DQ5,
+ PATTERN_KILLER_DQ6,
+ PATTERN_KILLER_DQ7,
+ PATTERN_VREF,
+ PATTERN_FULL_SSO0,
+ PATTERN_FULL_SSO1,
+ PATTERN_FULL_SSO2,
+ PATTERN_FULL_SSO3,
+ PATTERN_LAST,
+ PATTERN_SSO_FULL_XTALK_DQ0,
+ PATTERN_SSO_FULL_XTALK_DQ1,
+ PATTERN_SSO_FULL_XTALK_DQ2,
+ PATTERN_SSO_FULL_XTALK_DQ3,
+ PATTERN_SSO_FULL_XTALK_DQ4,
+ PATTERN_SSO_FULL_XTALK_DQ5,
+ PATTERN_SSO_FULL_XTALK_DQ6,
+ PATTERN_SSO_FULL_XTALK_DQ7,
+ PATTERN_SSO_XTALK_FREE_DQ0,
+ PATTERN_SSO_XTALK_FREE_DQ1,
+ PATTERN_SSO_XTALK_FREE_DQ2,
+ PATTERN_SSO_XTALK_FREE_DQ3,
+ PATTERN_SSO_XTALK_FREE_DQ4,
+ PATTERN_SSO_XTALK_FREE_DQ5,
+ PATTERN_SSO_XTALK_FREE_DQ6,
+ PATTERN_SSO_XTALK_FREE_DQ7,
+ PATTERN_ISI_XTALK_FREE
+};
+
+enum mv_wl_supp_mode {
+ WRITE_LEVELING_SUPP_REG_MODE,
+ WRITE_LEVELING_SUPP_ECC_MODE_DATA_PUPS,
+ WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4,
+ WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3,
+ WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8
+};
+
+enum mv_ddr_dev_attribute {
+ MV_ATTR_TIP_REV,
+ MV_ATTR_PHY_EDGE,
+ MV_ATTR_OCTET_PER_INTERFACE,
+ MV_ATTR_PLL_BEFORE_INIT,
+ MV_ATTR_TUNE_MASK,
+ MV_ATTR_INIT_FREQ,
+ MV_ATTR_MID_FREQ,
+ MV_ATTR_DFS_LOW_FREQ,
+ MV_ATTR_DFS_LOW_PHY,
+ MV_ATTR_DELAY_ENABLE,
+ MV_ATTR_CK_DELAY,
+ MV_ATTR_CA_DELAY,
+ MV_ATTR_INTERLEAVE_WA,
+ MV_ATTR_LAST
+};
+
+enum mv_ddr_tip_revison {
+ MV_TIP_REV_NA,
+ MV_TIP_REV_1, /* NP5 */
+ MV_TIP_REV_2, /* BC2 */
+ MV_TIP_REV_3, /* AC3 */
+ MV_TIP_REV_4, /* A-380/A-390 */
+ MV_TIP_REV_LAST
+};
+
+enum mv_ddr_phy_edge {
+ MV_DDR_PHY_EDGE_POSITIVE,
+ MV_DDR_PHY_EDGE_NEGATIVE
+};
+
+/* Device attribute functions */
+void ddr3_tip_dev_attr_init(u32 dev_num);
+u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id);
+void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value);
+
+#endif /* _DDR3_TRAINING_IP_DB_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h
new file mode 100644
index 000000000..8765df7cf
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_DEF_H
+#define _DDR3_TRAINING_IP_DEF_H
+
+#define PATTERN_55 0x55555555
+#define PATTERN_AA 0xaaaaaaaa
+#define PATTERN_80 0x80808080
+#define PATTERN_20 0x20202020
+#define PATTERN_01 0x01010101
+#define PATTERN_FF 0xffffffff
+#define PATTERN_00 0x00000000
+
+/* 16bit bus width patterns */
+#define PATTERN_55AA 0x5555aaaa
+#define PATTERN_00FF 0x0000ffff
+#define PATTERN_0080 0x00008080
+
+#define INVALID_VALUE 0xffffffff
+#define MAX_NUM_OF_DUNITS 32
+/*
+ * length *2 = length in words of pattern, first low address,
+ * second high address
+ */
+#define TEST_PATTERN_LENGTH 4
+#define KILLER_PATTERN_DQ_NUMBER 8
+#define SSO_DQ_NUMBER 4
+#define PATTERN_MAXIMUM_LENGTH 64
+#define ADLL_TX_LENGTH 64
+#define ADLL_RX_LENGTH 32
+
+#define PARAM_NOT_CARE 0
+#define PARAM_UNDEFINED 0xffffffff
+
+#define READ_LEVELING_PHY_OFFSET 2
+#define WRITE_LEVELING_PHY_OFFSET 0
+
+#define MASK_ALL_BITS 0xffffffff
+
+#define CS_BIT_MASK 0xf
+
+/* DFX access */
+#define BROADCAST_ID 28
+#define MULTICAST_ID 29
+
+#define XSB_BASE_ADDR 0x00004000
+#define XSB_CTRL_0_REG 0x00000000
+#define XSB_CTRL_1_REG 0x00000004
+#define XSB_CMD_REG 0x00000008
+#define XSB_ADDRESS_REG 0x0000000c
+#define XSB_DATA_REG 0x00000010
+#define PIPE_ENABLE_ADDR 0x000f8000
+#define ENABLE_DDR_TUNING_ADDR 0x000f829c
+
+#define CLIENT_BASE_ADDR 0x00002000
+#define CLIENT_CTRL_REG 0x00000000
+
+#define TARGET_INT 0x1801
+#define TARGET_EXT 0x180e
+#define BYTE_EN 0
+#define CMD_READ 0
+#define CMD_WRITE 1
+
+#define INTERNAL_ACCESS_PORT 1
+#define EXECUTING 1
+#define ACCESS_EXT 1
+#define CS2_EXIST_BIT 2
+#define TRAINING_ID 0xf
+#define EXT_TRAINING_ID 1
+#define EXT_MODE 0x4
+
+#define GET_RESULT_STATE(res) (res)
+#define SET_RESULT_STATE(res, state) (res = state)
+
+#define ADDR_SIZE_512MB 0x04000000
+#define ADDR_SIZE_1GB 0x08000000
+#define ADDR_SIZE_2GB 0x10000000
+#define ADDR_SIZE_4GB 0x20000000
+#define ADDR_SIZE_8GB 0x40000000
+#define ADDR_SIZE_16GB 0x80000000
+
+
+enum hws_edge_compare {
+ EDGE_PF,
+ EDGE_FP,
+ EDGE_FPF,
+ EDGE_PFP
+};
+
+enum hws_control_element {
+ HWS_CONTROL_ELEMENT_ADLL, /* per bit 1 edge */
+ HWS_CONTROL_ELEMENT_DQ_SKEW,
+ HWS_CONTROL_ELEMENT_DQS_SKEW
+};
+
+enum hws_search_dir {
+ HWS_LOW2HIGH,
+ HWS_HIGH2LOW,
+ HWS_SEARCH_DIR_LIMIT
+};
+
+enum hws_operation {
+ OPERATION_READ = 0,
+ OPERATION_WRITE = 1
+};
+
+enum hws_training_ip_stat {
+ HWS_TRAINING_IP_STATUS_FAIL,
+ HWS_TRAINING_IP_STATUS_SUCCESS,
+ HWS_TRAINING_IP_STATUS_TIMEOUT
+};
+
+enum hws_ddr_cs {
+ CS_SINGLE,
+ CS_NON_SINGLE
+};
+
+enum hws_ddr_phy {
+ DDR_PHY_DATA = 0,
+ DDR_PHY_CONTROL = 1
+};
+
+enum hws_dir {
+ OPER_WRITE,
+ OPER_READ,
+ OPER_WRITE_AND_READ
+};
+
+enum hws_wl_supp {
+ PHASE_SHIFT,
+ CLOCK_SHIFT,
+ ALIGN_SHIFT
+};
+
+enum mv_ddr_tip_bit_state {
+ BIT_LOW_UI,
+ BIT_HIGH_UI,
+ BIT_SPLIT_IN,
+ BIT_SPLIT_OUT,
+ BIT_STATE_LAST
+};
+
+enum mv_ddr_tip_byte_state{
+ BYTE_NOT_DEFINED,
+ BYTE_HOMOGENEOUS_LOW = 0x1,
+ BYTE_HOMOGENEOUS_HIGH = 0x2,
+ BYTE_HOMOGENEOUS_SPLIT_IN = 0x4,
+ BYTE_HOMOGENEOUS_SPLIT_OUT = 0x8,
+ BYTE_SPLIT_OUT_MIX = 0x10,
+ BYTE_STATE_LAST
+};
+
+struct reg_data {
+ unsigned int reg_addr;
+ unsigned int reg_data;
+ unsigned int reg_mask;
+};
+
+enum dm_direction {
+ DM_DIR_INVERSE,
+ DM_DIR_DIRECT
+};
+
+#endif /* _DDR3_TRAINING_IP_DEF_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
new file mode 100644
index 000000000..102f9bd63
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
@@ -0,0 +1,1680 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_regs.h"
+#include "ddr_training_ip_db.h"
+
+#define PATTERN_1 0x55555555
+#define PATTERN_2 0xaaaaaaaa
+
+#define VALIDATE_TRAINING_LIMIT(e1, e2) \
+ ((((e2) - (e1) + 1) > 33) && ((e1) < 67))
+
+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,
+ RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
+ RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
+ RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
+ RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
+ RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
+ RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
+ RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
+ RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
+ RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
+ RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
+ RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_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,
+ 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,
+#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,
+#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,
+ RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
+ RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
+ RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
+ RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
+ RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
+ RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
+ RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
+ RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
+ RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
+ RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_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[] = {
+ /*
+ * num tx phases, tx burst, delay between, rx pattern,
+ * start_address, pattern_len
+ */
+ {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 */
+ {0xf, 0x7, 2, 0x7, 0x0210, 16}, /* PATTERN_KILLER_DQ2 */
+ {0xf, 0x7, 2, 0x7, 0x0250, 16}, /* PATTERN_KILLER_DQ3 */
+ {0xf, 0x7, 2, 0x7, 0x0290, 16}, /* PATTERN_KILLER_DQ4 */
+ {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 */
+ {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, 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[] = {
+ /*
+ * num tx phases, tx burst, delay between, rx pattern,
+ * start_address, pattern_len
+ */
+ {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 */
+ {0x1f, 0xf, 2, 0xf, 0x0210, 32}, /* PATTERN_KILLER_DQ2 */
+ {0x1f, 0xf, 2, 0xf, 0x0250, 32}, /* PATTERN_KILLER_DQ3 */
+ {0x1f, 0xf, 2, 0xf, 0x0290, 32}, /* PATTERN_KILLER_DQ4 */
+ {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 */
+ {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, 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;
+enum hws_ddr_cs traintrain_cs_type;
+u32 train_pup_num;
+enum hws_training_result train_result_type;
+enum hws_control_element train_control_element;
+enum hws_search_dir traine_search_dir;
+enum hws_dir train_direction;
+u32 train_if_select;
+u32 train_init_value;
+u32 train_number_iterations;
+enum hws_pattern train_pattern;
+enum hws_edge_compare train_edge_compare;
+u32 train_cs_num;
+u32 train_if_acess, train_if_id, train_pup_access;
+u32 max_polling_for_done = 1000000;
+
+u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
+ enum hws_training_result result_type,
+ u32 interface_num)
+{
+ u32 *buf_ptr = NULL;
+
+ buf_ptr = &training_res
+ [MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * search +
+ interface_num * MAX_BUS_NUM * BUS_WIDTH_IN_BITS];
+
+ return buf_ptr;
+}
+
+enum {
+ PASS,
+ FAIL
+};
+/*
+ * IP Training search
+ * Note: for one edge search only from fail to pass, else jitter can
+ * be be entered into solution.
+ */
+int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
+ u32 interface_num,
+ 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, u32 num_iter,
+ enum hws_pattern pattern,
+ enum hws_edge_compare edge_comp,
+ 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,
+ reg_data, pup_id;
+ u32 tx_burst_size;
+ u32 delay_between_burst;
+ u32 rd_mode;
+ 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();
+ 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));
+ }
+ if (interface_num >= MAX_INTERFACE_NUM) {
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("if_id %d not valid\n",
+ interface_num));
+ }
+ if (train_status == NULL) {
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("error param 4\n"));
+ return MV_BAD_PARAM;
+ }
+
+ /* load pattern */
+ if (cs_type == CS_SINGLE) {
+ /* All CSs to CS0 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ 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_CTRL_REG,
+ (0x3 | (effective_cs << 26)), 0xc000003));
+ } else {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ DUAL_DUNIT_CFG_REG, 0, 1 << 3));
+ /* CS select */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26,
+ 0x3 | 3 << 26));
+ }
+
+ /* load pattern to ODPG */
+ ddr3_tip_load_pattern_to_odpg(dev_num, access_type, interface_num,
+ pattern,
+ pattern_table[pattern].start_addr);
+ tx_burst_size = (direction == OPER_WRITE) ?
+ pattern_table[pattern].tx_burst_size : 0;
+ delay_between_burst = (direction == OPER_WRITE) ? 2 : 0;
+ rd_mode = (direction == OPER_WRITE) ? 1 : 0;
+ CHECK_STATUS(ddr3_tip_configure_odpg
+ (dev_num, access_type, interface_num, direction,
+ pattern_table[pattern].num_of_phases_tx, tx_burst_size,
+ pattern_table[pattern].num_of_phases_rx,
+ delay_between_burst, rd_mode, effective_cs, STRESS_NONE,
+ DURATION_SINGLE));
+ reg_data = (direction == OPER_READ) ? 0 : (0x3 << 30);
+ reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa;
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ 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) ?
+ (1 << 7) : 0;
+
+ /* change from Pass to Fail will lock the result */
+ if (pup_access_type == ACCESS_TYPE_MULTICAST)
+ reg_data |= 0xe << 14;
+ else
+ reg_data |= pup_num << 14;
+
+ if (edge_comp == EDGE_FP) {
+ /* don't search for readl edge change, only the state */
+ reg_data |= (0 << 20);
+ } else if (edge_comp == EDGE_FPF) {
+ reg_data |= (0 << 20);
+ } else {
+ reg_data |= (3 << 20);
+ }
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ 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, OPCODE_REG0_REG(1),
+ 1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26),
+ 0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26)));
+
+ /*
+ * Write2_dunit(0x10b4, Number_iteration , [15:0])
+ * Max number of iterations
+ */
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
+ OPCODE_REG1_REG(1), num_iter,
+ 0xffff));
+ if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
+ direction == OPER_READ) {
+ /*
+ * Write2_dunit(0x10c0, 0x5f , [7:0])
+ * MC PBS Reg Address at DDR PHY
+ */
+ reg_data = PBS_RX_BCAST_PHY_REG(effective_cs);
+ } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
+ direction == OPER_WRITE) {
+ reg_data = PBS_TX_BCAST_PHY_REG(effective_cs);
+ } else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
+ direction == OPER_WRITE) {
+ /*
+ * LOOP 0x00000001 + 4*n:
+ * where n (0-3) represents M_CS number
+ */
+ /*
+ * Write2_dunit(0x10c0, 0x1 , [7:0])
+ * ADLL WR Reg Address at DDR PHY
+ */
+ 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 = 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 */
+ } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
+ direction == OPER_READ) {
+ /* TBD not defined in 0.5.0 requirement */
+ }
+
+ reg_data |= (0x6 << 28);
+ CHECK_STATUS(ddr3_tip_if_write
+ (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 = 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;
+ index_cnt++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ mask_results_dq_reg_map[index_cnt], 0,
+ 1 << 24));
+ }
+
+ /* Mask disabled buses */
+ for (pup_id = 0; pup_id < octets_per_if_num;
+ pup_id++) {
+ if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
+ continue;
+
+ 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,
+ mask_results_dq_reg_map
+ [index_cnt], (1 << 24), 1 << 24));
+ }
+ }
+
+ for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
+ index_cnt++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ mask_results_pup_reg_map[index_cnt],
+ (1 << 24), 1 << 24));
+ }
+ } else if (result_type == RESULT_PER_BYTE) {
+ /* write to adll */
+ for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
+ index_cnt++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ mask_results_pup_reg_map[index_cnt], 0,
+ 1 << 24));
+ }
+ for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
+ index_cnt++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, interface_num,
+ mask_results_dq_reg_map[index_cnt],
+ (1 << 24), (1 << 24)));
+ }
+ }
+
+ /* trigger training */
+ mv_ddr_training_enable();
+
+ /* wa for 16-bit mode: wait for all rfu tests to finish or timeout */
+ mdelay(1);
+
+ /* 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;
+ }
+
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+
+ return MV_OK;
+}
+
+/*
+ * Load expected Pattern to ODPG
+ */
+int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum hws_pattern pattern,
+ u32 load_addr)
+{
+ 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++) { /* 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_DATA_WR_ADDR_REG, pattern_length_cnt,
+ MASK_ALL_BITS));
+ }
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS));
+
+ return MV_OK;
+}
+
+/*
+ * Configure ODPG
+ */
+int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum hws_dir direction, u32 tx_phases,
+ u32 tx_burst_size, u32 rx_phases,
+ u32 delay_between_burst, u32 rd_mode, u32 cs_num,
+ u32 addr_stress_jump, u32 single_pattern)
+{
+ u32 data_value = 0;
+ int ret;
+
+ data_value = ((single_pattern << 2) | (tx_phases << 5) |
+ (tx_burst_size << 11) | (delay_between_burst << 15) |
+ (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_CTRL_REG, data_value, 0xaffffffc);
+ if (ret != MV_OK)
+ return ret;
+
+ return MV_OK;
+}
+
+int ddr3_tip_process_result(u32 *ar_result, enum hws_edge e_edge,
+ enum hws_edge_search e_edge_search,
+ u32 *edge_result)
+{
+ u32 i, res;
+ int tap_val, max_val = -10000, min_val = 10000;
+ int lock_success = 1;
+
+ for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
+ res = GET_LOCK_RESULT(ar_result[i]);
+ if (res == 0) {
+ lock_success = 0;
+ break;
+ }
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("lock failed for bit %d\n", i));
+ }
+
+ if (lock_success == 1) {
+ for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
+ tap_val = GET_TAP_RESULT(ar_result[i], e_edge);
+ if (tap_val > max_val)
+ max_val = tap_val;
+ if (tap_val < min_val)
+ min_val = tap_val;
+ if (e_edge_search == TRAINING_EDGE_MAX)
+ *edge_result = (u32) max_val;
+ else
+ *edge_result = (u32) min_val;
+
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("i %d ar_result[i] 0x%x tap_val %d max_val %d min_val %d Edge_result %d\n",
+ i, ar_result[i], tap_val,
+ max_val, min_val,
+ *edge_result));
+ }
+ } else {
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Read training search result
+ */
+int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
+ enum hws_access_type pup_access_type,
+ u32 pup_num, u32 bit_num,
+ enum hws_search_dir search,
+ enum hws_dir direction,
+ enum hws_training_result result_type,
+ enum hws_training_load_op operation,
+ u32 cs_num_type, u32 **load_res,
+ int is_read_from_db, u8 cons_tap,
+ int is_check_result_validity)
+{
+ u32 reg_offset, pup_cnt, start_pup, end_pup, start_reg, end_reg;
+ u32 *interface_train_res = NULL;
+ u16 *reg_addr = NULL;
+ 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();
+ 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,
+ * i.e. in multi CS, the number of CS per memory is the same for
+ * all pups
+ */
+ CHECK_STATUS(ddr3_tip_if_write
+ (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_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,
+ result_type, direction, search, pup_num,
+ if_id, pup_access_type));
+
+ if ((load_res == NULL) && (is_read_from_db == 1)) {
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("ddr3_tip_read_training_result load_res = NULL"));
+ return MV_FAIL;
+ }
+ if (pup_num >= octets_per_if_num) {
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("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 (result_type == RESULT_PER_BIT)
+ reg_addr = mask_results_dq_reg_map;
+ else
+ reg_addr = mask_results_pup_reg_map;
+ if (pup_access_type == ACCESS_TYPE_UNICAST) {
+ start_pup = pup_num;
+ end_pup = pup_num;
+ } else { /*pup_access_type == ACCESS_TYPE_MULTICAST) */
+
+ start_pup = 0;
+ end_pup = octets_per_if_num - 1;
+ }
+
+ for (pup_cnt = start_pup; pup_cnt <= end_pup; 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",
+ if_id, start_pup, end_pup, pup_cnt));
+ if (result_type == RESULT_PER_BIT) {
+ if (bit_num == ALL_BITS_PER_PUP) {
+ start_reg = pup_cnt * BUS_WIDTH_IN_BITS;
+ end_reg = (pup_cnt + 1) * BUS_WIDTH_IN_BITS - 1;
+ } else {
+ start_reg =
+ pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
+ end_reg = pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
+ }
+ } else {
+ start_reg = pup_cnt;
+ end_reg = pup_cnt;
+ }
+
+ interface_train_res =
+ ddr3_tip_get_buf_ptr(dev_num, search, result_type,
+ if_id);
+ DEBUG_TRAINING_IP_ENGINE(
+ DEBUG_LEVEL_TRACE,
+ ("start_reg %d end_reg %d interface %p\n",
+ start_reg, end_reg, interface_train_res));
+ if (interface_train_res == NULL) {
+ DEBUG_TRAINING_IP_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("interface_train_res is NULL\n"));
+ return MV_FAIL;
+ }
+
+ for (reg_offset = start_reg; reg_offset <= end_reg;
+ reg_offset++) {
+ if (operation == TRAINING_LOAD_OPERATION_UNLOAD) {
+ if (is_read_from_db == 0) {
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ reg_addr[reg_offset],
+ read_data,
+ MASK_ALL_BITS));
+ if (is_check_result_validity == 1) {
+ if ((read_data[if_id] &
+ TIP_ENG_LOCK) == 0) {
+ interface_train_res
+ [reg_offset] =
+ TIP_ENG_LOCK +
+ TIP_TX_DLL_RANGE_MAX;
+ } else {
+ interface_train_res
+ [reg_offset] =
+ read_data
+ [if_id] +
+ cons_tap;
+ }
+ } else {
+ interface_train_res[reg_offset]
+ = read_data[if_id] +
+ cons_tap;
+ }
+ DEBUG_TRAINING_IP_ENGINE
+ (DEBUG_LEVEL_TRACE,
+ ("reg_offset %d value 0x%x addr %p\n",
+ reg_offset,
+ interface_train_res
+ [reg_offset],
+ &interface_train_res
+ [reg_offset]));
+ } else {
+ *load_res =
+ &interface_train_res[start_reg];
+ DEBUG_TRAINING_IP_ENGINE
+ (DEBUG_LEVEL_TRACE,
+ ("*load_res %p\n", *load_res));
+ }
+ } else {
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
+ ("not supported\n"));
+ }
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Load all pattern to memory using ODPG
+ */
+int ddr3_tip_load_all_pattern_to_mem(u32 dev_num)
+{
+ u32 pattern = 0, if_id;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; 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_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* enable single cs */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
+ }
+
+ for (pattern = 0; pattern < PATTERN_LAST; pattern++) {
+ if (pattern == PATTERN_TEST)
+ continue;
+ ddr3_tip_load_pattern_to_mem(dev_num, pattern);
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Load specific pattern to memory using ODPG
+ */
+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 mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /* load pattern to memory */
+ /*
+ * Write Tx mode, CS0, phases, Tx burst size, delay between burst,
+ * rx pattern phases
+ */
+ reg_data =
+ 0x1 | (pattern_table[pattern].num_of_phases_tx << 5) |
+ (pattern_table[pattern].tx_burst_size << 11) |
+ (pattern_table[pattern].delay_between_bursts << 15) |
+ (pattern_table[pattern].num_of_phases_rx << 21) | (0x1 << 25) |
+ (effective_cs << 26);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ 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_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_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);
+
+ 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_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, (u32)(0x1 << 31),
+ (u32)(0x1 << 31)));
+ }
+ mdelay(1);
+
+ 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_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_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;
+}
+
+/*
+ * Training search routine
+ */
+int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
+ enum hws_access_type access_type,
+ u32 if_id,
+ enum hws_access_type pup_access_type,
+ u32 pup_num, u32 bit_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 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 = 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,
+ ("train_status is NULL\n"));
+ return MV_FAIL;
+ }
+
+ if ((train_cs_type > CS_NON_SINGLE) ||
+ (edge_comp >= EDGE_PFP) ||
+ (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 >= octets_per_if_num) ||
+ (pup_access_type > ACCESS_TYPE_MULTICAST) ||
+ (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) {
+ DEBUG_TRAINING_IP_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("wrong parameter train_cs_type %d edge_comp %d pattern %d direction %d search_dir %d control_element %d result_type %d pup_num %d pup_access_type %d if_id %d access_type %d\n",
+ train_cs_type, edge_comp, pattern, direction,
+ search_dir, control_element, result_type, pup_num,
+ pup_access_type, if_id, access_type));
+ return MV_FAIL;
+ }
+
+ if (edge_comp == EDGE_FPF) {
+ start_search = HWS_LOW2HIGH;
+ end_search = HWS_HIGH2LOW;
+ edge_comp_used = EDGE_FP;
+ } else {
+ start_search = search_dir;
+ end_search = search_dir;
+ edge_comp_used = edge_comp;
+ }
+
+ for (search_dir_id = start_search; search_dir_id <= end_search;
+ search_dir_id++) {
+ init_value_used = (search_dir_id == HWS_LOW2HIGH) ?
+ init_value_l2h : init_value_h2l;
+ DEBUG_TRAINING_IP_ENGINE(
+ DEBUG_LEVEL_TRACE,
+ ("dev_num %d, access_type %d, if_id %d, pup_access_type %d,pup_num %d, result_type %d, control_element %d search_dir_id %d, direction %d, interface_mask %d,init_value_used %d, num_iter %d, pattern %d, edge_comp_used %d, train_cs_type %d, cs_num %d\n",
+ dev_num, access_type, if_id, pup_access_type, pup_num,
+ result_type, control_element, search_dir_id,
+ direction, interface_mask, init_value_used, num_iter,
+ pattern, edge_comp_used, train_cs_type, cs_num));
+
+ ddr3_tip_ip_training(dev_num, access_type, if_id,
+ pup_access_type, pup_num, result_type,
+ control_element, search_dir_id, direction,
+ interface_mask, init_value_used, num_iter,
+ pattern, edge_comp_used, train_cs_type,
+ cs_num, train_status);
+ if (access_type == ACCESS_TYPE_MULTICAST) {
+ start_if = 0;
+ end_if = MAX_INTERFACE_NUM - 1;
+ } else {
+ start_if = if_id;
+ end_if = if_id;
+ }
+
+ for (interface_num = start_if; interface_num <= end_if;
+ 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,
+ pup_num, bit_num, search_dir_id,
+ direction, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD,
+ train_cs_type, NULL, 0, cons_tap,
+ 0));
+ }
+ }
+
+ 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)
+{
+ u8 e1, e2;
+ 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 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));
+ }
+
+ if (if_id >= MAX_INTERFACE_NUM) {
+ DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
+ ("if_id %d not valid\n", if_id));
+ }
+
+ 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;
+ end_if = MAX_INTERFACE_NUM - 1;
+ } else {
+ start_if = if_id;
+ end_if = if_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;
+ else
+ bit_end = 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,
+ ("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));
+ 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 */
+
+ /* phase 2 will occur only in write operation */
+ if (bit_bit_mask_active != 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;
+
+ 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;
+ }
+
+ /* 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));
+ }
+ }
+ }
+ } /* 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;
+ 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_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,
+ 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),
+ &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,
+ CRX_PHY_REG(effective_cs),
+ &phy_reg_bk[if_id][bus_cnt]
+ [2]));
+ } else {
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST,
+ bus_cnt, DDR_PHY_DATA,
+ 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),
+ 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,
+ CRX_PHY_REG(effective_cs),
+ phy_reg_bk[if_id][bus_cnt]
+ [2]));
+ }
+ }
+ }
+
+ return MV_OK;
+}
+
+int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
+ enum hws_search_dir search_dir,
+ enum hws_dir direction,
+ enum hws_edge_compare edge,
+ u32 init_val1, u32 init_val2,
+ u32 num_of_iterations,
+ u32 start_pattern, u32 end_pattern)
+{
+ u32 pattern, if_id, pup_id;
+ enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
+ u32 *res = NULL;
+ u32 search_state = 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();
+
+ ddr3_tip_load_phy_values(1);
+
+ for (pattern = start_pattern; pattern <= end_pattern; pattern++) {
+ for (search_state = 0; search_state < HWS_SEARCH_DIR_LIMIT;
+ search_state++) {
+ ddr3_tip_ip_training_wrapper(dev_num,
+ ACCESS_TYPE_MULTICAST, 0,
+ ACCESS_TYPE_MULTICAST, 0,
+ result_type,
+ HWS_CONTROL_ELEMENT_ADLL,
+ search_dir, direction,
+ 0xfff, init_val1,
+ init_val2,
+ num_of_iterations, pattern,
+ edge, CS_SINGLE,
+ PARAM_NOT_CARE,
+ train_status);
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup_id = 0; pup_id <
+ octets_per_if_num;
+ pup_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask,
+ pup_id);
+ CHECK_STATUS
+ (ddr3_tip_read_training_result
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup_id,
+ ALL_BITS_PER_PUP,
+ search_state,
+ direction, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD,
+ CS_SINGLE, &res, 1, 0,
+ 0));
+ if (result_type == RESULT_PER_BYTE) {
+ DEBUG_TRAINING_IP_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("search_state %d if_id %d pup_id %d 0x%x\n",
+ search_state, if_id,
+ pup_id, res[0]));
+ } else {
+ DEBUG_TRAINING_IP_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("search_state %d if_id %d pup_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ search_state, if_id,
+ pup_id, res[0],
+ res[1], res[2],
+ res[3], res[4],
+ res[5], res[6],
+ res[7]));
+ }
+ }
+ } /* interface */
+ } /* search */
+ } /* pattern */
+
+ ddr3_tip_load_phy_values(0);
+
+ 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 mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ 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;
+}
+
+u16 *ddr3_tip_get_mask_results_dq_reg()
+{
+#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()
+{
+#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;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h
new file mode 100644
index 000000000..2d40e68db
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_ENGINE_H_
+#define _DDR3_TRAINING_IP_ENGINE_H_
+
+#include "ddr3_training_ip_def.h"
+#include "ddr3_training_ip_flow.h"
+#include "ddr3_training_ip_pbs.h"
+
+#define EDGE_1 0
+#define EDGE_2 1
+#define ALL_PUP_TRAINING 0xe
+#define PUP_RESULT_EDGE_1_MASK 0xff
+#define PUP_RESULT_EDGE_2_MASK (0xff << 8)
+#define PUP_LOCK_RESULT_BIT 25
+
+#define GET_TAP_RESULT(reg, edge) \
+ (((edge) == EDGE_1) ? ((reg) & PUP_RESULT_EDGE_1_MASK) : \
+ (((reg) & PUP_RESULT_EDGE_2_MASK) >> 8));
+#define GET_LOCK_RESULT(reg) \
+ (((reg) & (1<<PUP_LOCK_RESULT_BIT)) >> PUP_LOCK_RESULT_BIT)
+
+#define EDGE_FAILURE 128
+#define ALL_BITS_PER_PUP 128
+
+#define MIN_WINDOW_SIZE 6
+#define MAX_WINDOW_SIZE_RX 32
+#define MAX_WINDOW_SIZE_TX 64
+
+int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
+ enum hws_search_dir search_dir,
+ enum hws_dir direction,
+ enum hws_edge_compare edge,
+ u32 init_val1, u32 init_val2,
+ u32 num_of_iterations, u32 start_pattern,
+ u32 end_pattern);
+int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern);
+int ddr3_tip_load_all_pattern_to_mem(u32 dev_num);
+int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
+ enum hws_access_type pup_access_type,
+ u32 pup_num, u32 bit_num,
+ enum hws_search_dir search,
+ enum hws_dir direction,
+ enum hws_training_result result_type,
+ enum hws_training_load_op operation,
+ u32 cs_num_type, u32 **load_res,
+ int is_read_from_db, u8 cons_tap,
+ int is_check_result_validity);
+int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
+ u32 interface_num,
+ 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, u32 num_iter,
+ enum hws_pattern pattern,
+ enum hws_edge_compare edge_comp,
+ enum hws_ddr_cs cs_type, u32 cs_num,
+ enum hws_training_ip_stat *train_status);
+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_value1,
+ u32 init_value2, 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 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id);
+void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data);
+void ddr3_tip_print_bist_res(void);
+struct pattern_info *ddr3_tip_get_pattern_table(void);
+u16 *ddr3_tip_get_mask_results_dq_reg(void);
+u16 *ddr3_tip_get_mask_results_pup_reg_map(void);
+int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern,
+ enum dm_direction dm_dir);
+int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr);
+#endif /* _DDR3_TRAINING_IP_ENGINE_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h
new file mode 100644
index 000000000..ab152cb45
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_FLOW_H_
+#define _DDR3_TRAINING_IP_FLOW_H_
+
+#include "ddr3_training_ip.h"
+#include "ddr3_training_ip_db.h"
+
+#define KILLER_PATTERN_LENGTH 32
+#define EXT_ACCESS_BURST_LENGTH 8
+
+#define ECC_READ_BUS_0 0
+#define ECC_PHY_ACCESS_3 3
+#define ECC_PHY_ACCESS_4 4
+#define ECC_PHY_ACCESS_8 8
+#define BUS_WIDTH_IN_BITS 8
+#define MAX_POLLING_ITERATIONS 1000000
+#define ADLL_LENGTH 32
+
+#define GP_RSVD0_REG 0x182e0
+
+/*
+ * DFX address Space
+ * Table 2: DFX address space
+ * Address Bits Value Description
+ * [31 : 20] 0x? DFX base address bases PCIe mapping
+ * [19 : 15] 0...Number_of_client-1 Client Index inside pipe.
+ * See also Table 1 Multi_cast = 29 Broadcast = 28
+ * [14 : 13] 2'b01 Access to Client Internal Register
+ * [12 : 0] Client Internal Register offset See related Client Registers
+ * [14 : 13] 2'b00 Access to Ram Wrappers Internal Register
+ * [12 : 6] 0 Number_of_rams-1 Ram Index inside Client
+ * [5 : 0] Ram Wrapper Internal Register offset See related Ram Wrappers
+ * Registers
+ */
+
+/* nsec */
+#define AUTO_ZQC_TIMING 15384
+
+enum mr_number {
+ MR_CMD0,
+ MR_CMD1,
+ MR_CMD2,
+ MR_CMD3,
+ MR_LAST
+};
+
+struct mv_ddr_mr_data {
+ u32 cmd;
+ u32 reg_addr;
+};
+
+struct write_supp_result {
+ enum hws_wl_supp stage;
+ int is_pup_fail;
+};
+
+int ddr3_tip_write_leveling_static_config(u32 dev_num, u32 if_id,
+ enum mv_ddr_freq frequency,
+ u32 *round_trip_delay_arr);
+int ddr3_tip_read_leveling_static_config(u32 dev_num, u32 if_id,
+ enum mv_ddr_freq frequency,
+ u32 *total_round_trip_delay_arr);
+int ddr3_tip_if_write(u32 dev_num, enum hws_access_type interface_access,
+ u32 if_id, u32 reg_addr, u32 data_value, u32 mask);
+int ddr3_tip_if_polling(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, u32 exp_value, u32 mask, u32 offset,
+ u32 poll_tries);
+int ddr3_tip_if_read(u32 dev_num, enum hws_access_type interface_access,
+ u32 if_id, u32 reg_addr, u32 *data, u32 mask);
+int ddr3_tip_bus_read_modify_write(u32 dev_num,
+ enum hws_access_type access_type,
+ u32 if_id, u32 phy_id,
+ enum hws_ddr_phy phy_type,
+ u32 reg_addr, u32 data_value, u32 reg_mask);
+int ddr3_tip_bus_read(u32 dev_num, u32 if_id, enum hws_access_type phy_access,
+ u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr,
+ u32 *data);
+int ddr3_tip_bus_write(u32 dev_num, enum hws_access_type e_interface_access,
+ u32 if_id, enum hws_access_type e_phy_access, u32 phy_id,
+ enum hws_ddr_phy e_phy_type, u32 reg_addr,
+ u32 data_value);
+int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type e_access, u32 if_id,
+ enum mv_ddr_freq memory_freq);
+int ddr3_tip_adjust_dqs(u32 dev_num);
+int ddr3_tip_init_controller(u32 dev_num);
+int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr,
+ u32 num_of_bursts, u32 *addr);
+int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr,
+ u32 num_of_bursts, u32 *addr);
+int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 ui_freq);
+int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq);
+int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num);
+int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 ui_freq);
+int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num);
+int ddr3_tip_dynamic_write_leveling(u32 dev_num, int phase_remove);
+int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num);
+int ddr3_tip_static_init_controller(u32 dev_num);
+int ddr3_tip_configure_phy(u32 dev_num);
+int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum hws_pattern pattern,
+ u32 load_addr);
+int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern e_pattern);
+int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum hws_dir direction, u32 tx_phases,
+ u32 tx_burst_size, u32 rx_phases,
+ u32 delay_between_burst, u32 rd_mode, u32 cs_num,
+ u32 addr_stress_jump, u32 single_pattern);
+int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, enum mr_number mr_num, u32 data, u32 mask);
+int ddr3_tip_write_cs_result(u32 dev_num, u32 offset);
+int ddr3_tip_reset_fifo_ptr(u32 dev_num);
+int ddr3_tip_read_pup_value(u32 dev_num, u32 pup_values[], int reg_addr, u32 mask);
+int ddr3_tip_read_adll_value(u32 dev_num, u32 pup_values[], u32 reg_addr, u32 mask);
+int ddr3_tip_write_adll_value(u32 dev_num, u32 pup_values[], u32 reg_addr);
+int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params);
+
+#endif /* _DDR3_TRAINING_IP_FLOW_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_pbs.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_pbs.h
new file mode 100644
index 000000000..323c67aa5
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_pbs.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_PBS_H_
+#define _DDR3_TRAINING_IP_PBS_H_
+
+enum {
+ EBA_CONFIG,
+ EEBA_CONFIG,
+ SBA_CONFIG
+};
+
+enum hws_training_load_op {
+ TRAINING_LOAD_OPERATION_UNLOAD,
+ TRAINING_LOAD_OPERATION_LOAD
+};
+
+enum hws_edge {
+ TRAINING_EDGE_1,
+ TRAINING_EDGE_2
+};
+
+enum hws_edge_search {
+ TRAINING_EDGE_MAX,
+ TRAINING_EDGE_MIN
+};
+
+enum pbs_dir {
+ PBS_TX_MODE = 0,
+ PBS_RX_MODE,
+ NUM_OF_PBS_MODES
+};
+
+int ddr3_tip_pbs_rx(u32 dev_num);
+int ddr3_tip_print_all_pbs_result(u32 dev_num);
+int ddr3_tip_pbs_tx(u32 dev_num);
+
+#endif /* _DDR3_TRAINING_IP_PBS_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h
new file mode 100644
index 000000000..2df592e1b
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_IP_PRV_IF_H
+#define _DDR3_TRAINING_IP_PRV_IF_H
+
+#include "ddr3_training_ip.h"
+#include "ddr3_training_ip_flow.h"
+#include "ddr3_training_ip_bist.h"
+
+enum hws_static_config_type {
+ WRITE_LEVELING_STATIC,
+ READ_LEVELING_STATIC
+};
+
+struct ddr3_device_info {
+ u32 device_id;
+ u32 ck_delay;
+};
+
+typedef int (*HWS_TIP_DUNIT_MUX_SELECT_FUNC_PTR)(u8 dev_num, int enable);
+typedef int (*HWS_TIP_DUNIT_REG_READ_FUNC_PTR)(
+ u8 dev_num, enum hws_access_type interface_access, u32 if_id,
+ u32 offset, u32 *data, u32 mask);
+typedef int (*HWS_TIP_DUNIT_REG_WRITE_FUNC_PTR)(
+ u8 dev_num, enum hws_access_type interface_access, u32 if_id,
+ u32 offset, u32 data, u32 mask);
+typedef int (*HWS_TIP_GET_FREQ_CONFIG_INFO)(
+ u8 dev_num, enum mv_ddr_freq freq,
+ struct hws_tip_freq_config_info *freq_config_info);
+typedef int (*HWS_TIP_GET_DEVICE_INFO)(
+ u8 dev_num, struct ddr3_device_info *info_ptr);
+typedef int (*HWS_GET_CS_CONFIG_FUNC_PTR)(
+ u8 dev_num, u32 cs_mask, struct hws_cs_config_info *cs_info);
+typedef int (*HWS_SET_FREQ_DIVIDER_FUNC_PTR)(
+ u8 dev_num, u32 if_id, enum mv_ddr_freq freq);
+typedef int (*HWS_GET_INIT_FREQ)(u8 dev_num, enum mv_ddr_freq *freq);
+typedef int (*HWS_TRAINING_IP_IF_WRITE_FUNC_PTR)(
+ u32 dev_num, enum hws_access_type access_type, u32 dunit_id,
+ u32 reg_addr, u32 data, u32 mask);
+typedef int (*HWS_TRAINING_IP_IF_READ_FUNC_PTR)(
+ u32 dev_num, enum hws_access_type access_type, u32 dunit_id,
+ u32 reg_addr, u32 *data, u32 mask);
+typedef int (*HWS_TRAINING_IP_BUS_WRITE_FUNC_PTR)(
+ u32 dev_num, enum hws_access_type dunit_access_type, u32 if_id,
+ enum hws_access_type phy_access_type, u32 phy_id,
+ enum hws_ddr_phy phy_type, u32 reg_addr, u32 data);
+typedef int (*HWS_TRAINING_IP_BUS_READ_FUNC_PTR)(
+ u32 dev_num, u32 if_id, enum hws_access_type phy_access_type,
+ u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, u32 *data);
+typedef int (*HWS_TRAINING_IP_ALGO_RUN_FUNC_PTR)(
+ u32 dev_num, enum hws_algo_type algo_type);
+typedef int (*HWS_TRAINING_IP_SET_FREQ_FUNC_PTR)(
+ u32 dev_num, enum hws_access_type access_type, u32 if_id,
+ enum mv_ddr_freq frequency);
+typedef int (*HWS_TRAINING_IP_INIT_CONTROLLER_FUNC_PTR)(
+ u32 dev_num, struct init_cntr_param *init_cntr_prm);
+typedef int (*HWS_TRAINING_IP_PBS_RX_FUNC_PTR)(u32 dev_num);
+typedef int (*HWS_TRAINING_IP_PBS_TX_FUNC_PTR)(u32 dev_num);
+typedef int (*HWS_TRAINING_IP_SELECT_CONTROLLER_FUNC_PTR)(
+ u32 dev_num, int enable);
+typedef int (*HWS_TRAINING_IP_TOPOLOGY_MAP_LOAD_FUNC_PTR)(
+ u32 dev_num, struct mv_ddr_topology_map *tm);
+typedef int (*HWS_TRAINING_IP_STATIC_CONFIG_FUNC_PTR)(
+ u32 dev_num, enum mv_ddr_freq frequency,
+ enum hws_static_config_type static_config_type, u32 if_id);
+typedef int (*HWS_TRAINING_IP_EXTERNAL_READ_PTR)(
+ u32 dev_num, u32 if_id, u32 ddr_addr, u32 num_bursts, u32 *data);
+typedef int (*HWS_TRAINING_IP_EXTERNAL_WRITE_PTR)(
+ u32 dev_num, u32 if_id, u32 ddr_addr, u32 num_bursts, u32 *data);
+typedef int (*HWS_TRAINING_IP_BIST_ACTIVATE)(
+ u32 dev_num, enum hws_pattern pattern, enum hws_access_type access_type,
+ u32 if_num, enum hws_dir direction,
+ enum hws_stress_jump addr_stress_jump,
+ enum hws_pattern_duration duration,
+ enum hws_bist_operation oper_type, u32 offset, u32 cs_num,
+ u32 pattern_addr_length);
+typedef int (*HWS_TRAINING_IP_BIST_READ_RESULT)(
+ u32 dev_num, u32 if_id, struct bist_result *pst_bist_result);
+typedef int (*HWS_TRAINING_IP_LOAD_TOPOLOGY)(u32 dev_num, u32 config_num);
+typedef int (*HWS_TRAINING_IP_READ_LEVELING)(u32 dev_num, u32 config_num);
+typedef int (*HWS_TRAINING_IP_WRITE_LEVELING)(u32 dev_num, u32 config_num);
+typedef u32 (*HWS_TRAINING_IP_GET_TEMP)(u8 dev_num);
+typedef u8 (*HWS_TRAINING_IP_GET_RATIO)(u32 freq);
+
+struct hws_tip_config_func_db {
+ HWS_TIP_DUNIT_MUX_SELECT_FUNC_PTR tip_dunit_mux_select_func;
+ void (*mv_ddr_dunit_read)(u32 addr, u32 mask, u32 *data);
+ void (*mv_ddr_dunit_write)(u32 addr, u32 mask, u32 data);
+ HWS_TIP_GET_FREQ_CONFIG_INFO tip_get_freq_config_info_func;
+ HWS_TIP_GET_DEVICE_INFO tip_get_device_info_func;
+ HWS_SET_FREQ_DIVIDER_FUNC_PTR tip_set_freq_divider_func;
+ HWS_GET_CS_CONFIG_FUNC_PTR tip_get_cs_config_info;
+ HWS_TRAINING_IP_GET_TEMP tip_get_temperature;
+ HWS_TRAINING_IP_GET_RATIO tip_get_clock_ratio;
+ HWS_TRAINING_IP_EXTERNAL_READ_PTR tip_external_read;
+ HWS_TRAINING_IP_EXTERNAL_WRITE_PTR tip_external_write;
+ int (*mv_ddr_phy_read)(enum hws_access_type phy_access,
+ u32 phy, enum hws_ddr_phy phy_type,
+ u32 reg_addr, u32 *data);
+ int (*mv_ddr_phy_write)(enum hws_access_type phy_access,
+ u32 phy, enum hws_ddr_phy phy_type,
+ u32 reg_addr, u32 data,
+ enum hws_operation op_type);
+};
+
+int ddr3_tip_init_config_func(u32 dev_num,
+ struct hws_tip_config_func_db *config_func);
+int ddr3_tip_register_xsb_info(u32 dev_num,
+ struct hws_xsb_info *xsb_info_table);
+enum hws_result *ddr3_tip_get_result_ptr(u32 stage);
+int ddr3_set_freq_config_info(struct hws_tip_freq_config_info *table);
+int print_device_info(u8 dev_num);
+
+#endif /* _DDR3_TRAINING_IP_PRV_IF_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.c
new file mode 100644
index 000000000..6523281f2
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.c
@@ -0,0 +1,1963 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_training_db.h"
+#include "ddr_training_ip_db.h"
+#include "mv_ddr_regs.h"
+
+#define WL_ITERATION_NUM 10
+
+static u32 pup_mask_table[] = {
+ 0x000000ff,
+ 0x0000ff00,
+ 0x00ff0000,
+ 0xff000000
+};
+
+static struct write_supp_result wr_supp_res[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+
+static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num);
+static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num);
+static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num);
+static int ddr3_tip_wl_supp_align_phase_shift(u32 dev_num, u32 if_id,
+ u32 bus_id);
+static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id,
+ u32 edge_offset);
+
+enum {
+ PASS,
+ FAIL
+};
+/*****************************************************************************
+Dynamic read leveling
+******************************************************************************/
+int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq)
+{
+ u32 data, mask;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ u32 bus_num, if_id, cl_val;
+ enum mv_ddr_speed_bin speed_bin_index;
+ /* save current CS value */
+ u32 cs_enable_reg_val[MAX_INTERFACE_NUM] = { 0 };
+ int is_any_pup_fail = 0;
+ u32 data_read[MAX_INTERFACE_NUM + 1] = { 0 };
+ u8 rl_values[MAX_CS_NUM][MAX_BUS_NUM][MAX_INTERFACE_NUM];
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+ u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_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 (effective_cs = 0; effective_cs < MAX_CS_NUM; effective_cs++)
+ for (bus_num = 0; bus_num < MAX_BUS_NUM; bus_num++)
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++)
+ rl_values[effective_cs][bus_num][if_id] = 0;
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+
+ /* save current cs enable reg val */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val,
+ MASK_ALL_BITS));
+ /* enable single cs */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
+ }
+
+ ddr3_tip_reset_fifo_ptr(dev_num);
+
+ /*
+ * Phase 1: Load pattern (using ODPG)
+ *
+ * enter Read Leveling mode
+ * only 27 bits are masked
+ * assuming non multi-CS configuration
+ * write to CS = 0 for the non multi CS configuration, note
+ * that the results shall be read back to the required CS !!!
+ */
+
+ /* BUS count is 0 shifted 26 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0x3, 0x3));
+ CHECK_STATUS(ddr3_tip_configure_odpg
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0,
+ pattern_table[PATTERN_RL].num_of_phases_tx, 0,
+ pattern_table[PATTERN_RL].num_of_phases_rx, 0, 0,
+ effective_cs, STRESS_NONE, DURATION_SINGLE));
+
+ /* load pattern to ODPG */
+ ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, PATTERN_RL,
+ pattern_table[PATTERN_RL].
+ start_addr);
+
+ /*
+ * Phase 2: ODPG to Read Leveling mode
+ */
+
+ /* General Training Opcode register */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_WR_RD_MODE_ENA_REG, 0,
+ MASK_ALL_BITS));
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ GENERAL_TRAINING_OPCODE_REG,
+ (0x301b01 | effective_cs << 2), 0x3c3fef));
+
+ /* Object1 opcode register 0 & 1 */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ speed_bin_index =
+ tm->interface_params[if_id].speed_bin_index;
+ cl_val = mv_ddr_cl_val_get(speed_bin_index, freq);
+ data = (cl_val << 17) | (0x3 << 25);
+ mask = (0xff << 9) | (0x1f << 17) | (0x3 << 25);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ OPCODE_REG0_REG(1), data, mask));
+ }
+
+ /* Set iteration count to max value */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ OPCODE_REG1_REG(1), 0xd00, 0xd00));
+
+ /*
+ * Phase 2: Mask config
+ */
+
+ ddr3_tip_dynamic_read_leveling_seq(dev_num);
+
+ /*
+ * Phase 3: Read Leveling execution
+ */
+
+ /* temporary jira dunit=14751 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_DBG_1_REG, 0, (u32)(1 << 31)));
+ /* configure phy reset value */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_DBG_3_REG, (0x7f << 24),
+ (u32)(0xff << 24)));
+ /* data pup rd reset enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, 0, (1 << 30)));
+ /* data pup rd reset disable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, (1 << 30), (1 << 30)));
+ /* training SW override & training RL mode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x1, 0x9));
+ /* training enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_REG, (1 << 24) | (1 << 20),
+ (1 << 24) | (1 << 20)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_REG, (u32)(1 << 31), (u32)(1 << 31)));
+
+ /* trigger training */
+ mv_ddr_training_enable();
+
+ /* check for training done */
+ if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n"));
+ return MV_FAIL;
+ }
+ /* check for training pass */
+ if (data != PASS)
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n"));
+
+ /* disable odpg; switch back to functional mode */
+ mv_ddr_odpg_disable();
+
+ if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("odpg disable failed\n"));
+ return MV_FAIL;
+ }
+
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+
+ /* double loop on bus, pup */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* check training done */
+ is_any_pup_fail = 0;
+ for (bus_num = 0;
+ bus_num < octets_per_if_num;
+ bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num);
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, (1 << 25), (1 << 25),
+ mask_results_pup_reg_map[bus_num],
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("\n_r_l: DDR3 poll failed(2) for IF %d CS %d bus %d",
+ if_id, effective_cs, bus_num));
+ is_any_pup_fail = 1;
+ } else {
+ /* read result per pup */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ mask_results_pup_reg_map
+ [bus_num], data_read,
+ 0xff));
+ rl_values[effective_cs][bus_num]
+ [if_id] = (u8)data_read[if_id];
+ }
+ }
+
+ if (is_any_pup_fail == 1) {
+ training_result[training_stage][if_id] =
+ TEST_FAILED;
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("RL exit read leveling\n"));
+
+ /*
+ * Phase 3: Exit Read Leveling
+ */
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, (1 << 3), (1 << 3)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_1_REG, (1 << 16), (1 << 16)));
+ /* set ODPG to functional */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS));
+
+ /*
+ * Copy the result from the effective CS search to the
+ * real Functional CS
+ */
+ /*ddr3_tip_write_cs_result(dev_num, RL_PHY_REG(0); */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS));
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ /* double loop on bus, pup */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_num = 0;
+ bus_num < octets_per_if_num;
+ bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num);
+ /* read result per pup from arry */
+ data = rl_values[effective_cs][bus_num][if_id];
+ data = (data & 0x1f) |
+ (((data & 0xe0) >> 5) << 6);
+ ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_num, DDR_PHY_DATA,
+ RL_PHY_REG(effective_cs),
+ data);
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* restore cs enable value */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id],
+ MASK_ALL_BITS));
+ if (odt_config != 0) {
+ CHECK_STATUS(ddr3_tip_write_additional_odt_setting
+ (dev_num, if_id));
+ }
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (training_result[training_stage][if_id] == TEST_FAILED)
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Legacy Dynamic write leveling
+ */
+int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num)
+{
+ u32 c_cs, if_id, cs_mask = 0;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /*
+ * In TRAINIUNG reg (0x15b0) write 0x80000008 | cs_mask:
+ * Trn_start
+ * cs_mask = 0x1 <<20 Trn_CS0 - CS0 is included in the DDR3 training
+ * cs_mask = 0x1 <<21 Trn_CS1 - CS1 is included in the DDR3 training
+ * cs_mask = 0x1 <<22 Trn_CS2 - CS2 is included in the DDR3 training
+ * cs_mask = 0x1 <<23 Trn_CS3 - CS3 is included in the DDR3 training
+ * Trn_auto_seq = write leveling
+ */
+ for (c_cs = 0; c_cs < max_cs; c_cs++)
+ cs_mask = cs_mask | 1 << (20 + c_cs);
+
+ 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_MULTICAST, 0,
+ TRAINING_REG, (0x80000008 | cs_mask),
+ 0xffffffff));
+ mdelay(20);
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0,
+ (u32)0x80000000, TRAINING_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("polling failed for Old WL result\n"));
+ return MV_FAIL;
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Legacy Dynamic read leveling
+ */
+int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num)
+{
+ u32 c_cs, if_id, cs_mask = 0;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /*
+ * In TRAINIUNG reg (0x15b0) write 0x80000040 | cs_mask:
+ * Trn_start
+ * cs_mask = 0x1 <<20 Trn_CS0 - CS0 is included in the DDR3 training
+ * cs_mask = 0x1 <<21 Trn_CS1 - CS1 is included in the DDR3 training
+ * cs_mask = 0x1 <<22 Trn_CS2 - CS2 is included in the DDR3 training
+ * cs_mask = 0x1 <<23 Trn_CS3 - CS3 is included in the DDR3 training
+ * Trn_auto_seq = Read Leveling using training pattern
+ */
+ for (c_cs = 0; c_cs < max_cs; c_cs++)
+ cs_mask = cs_mask | 1 << (20 + c_cs);
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, 0, TRAINING_REG,
+ (0x80000040 | cs_mask), 0xffffffff));
+ mdelay(100);
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0,
+ (u32)0x80000000, TRAINING_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("polling failed for Old RL result\n"));
+ return MV_FAIL;
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Dynamic per bit read leveling
+ */
+int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq)
+{
+ u32 data, mask;
+ u32 bus_num, if_id, cl_val, bit_num;
+ u32 curr_numb, curr_min_delay;
+ int adll_array[3] = { 0, -0xa, 0x14 };
+ u32 phyreg3_arr[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ enum mv_ddr_speed_bin speed_bin_index;
+ int is_any_pup_fail = 0;
+ int break_loop = 0;
+ u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; /* save current CS value */
+ u32 data_read[MAX_INTERFACE_NUM];
+ int per_bit_rl_pup_status[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u32 data2_write[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+ u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
+ 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; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_num = 0;
+ bus_num <= octets_per_if_num; bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num);
+ per_bit_rl_pup_status[if_id][bus_num] = 0;
+ data2_write[if_id][bus_num] = 0;
+ /* read current value of phy register 0x3 */
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST,
+ bus_num, DDR_PHY_DATA,
+ CRX_PHY_REG(0),
+ &phyreg3_arr[if_id][bus_num]));
+ }
+ }
+
+ /* NEW RL machine */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+
+ /* save current cs enable reg val */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, &cs_enable_reg_val[if_id],
+ MASK_ALL_BITS));
+ /* enable single cs */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
+ }
+
+ ddr3_tip_reset_fifo_ptr(dev_num);
+ for (curr_numb = 0; curr_numb < 3; curr_numb++) {
+ /*
+ * Phase 1: Load pattern (using ODPG)
+ *
+ * enter Read Leveling mode
+ * only 27 bits are masked
+ * assuming non multi-CS configuration
+ * write to CS = 0 for the non multi CS configuration, note that
+ * the results shall be read back to the required CS !!!
+ */
+
+ /* BUS count is 0 shifted 26 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0x3, 0x3));
+ CHECK_STATUS(ddr3_tip_configure_odpg
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0,
+ pattern_table[PATTERN_TEST].num_of_phases_tx, 0,
+ pattern_table[PATTERN_TEST].num_of_phases_rx, 0,
+ 0, 0, STRESS_NONE, DURATION_SINGLE));
+
+ /* load pattern to ODPG */
+ ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, PATTERN_TEST,
+ pattern_table[PATTERN_TEST].
+ start_addr);
+
+ /*
+ * Phase 2: ODPG to Read Leveling mode
+ */
+
+ /* General Training Opcode register */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_WR_RD_MODE_ENA_REG, 0,
+ MASK_ALL_BITS));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ GENERAL_TRAINING_OPCODE_REG, 0x301b01, 0x3c3fef));
+
+ /* Object1 opcode register 0 & 1 */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ speed_bin_index =
+ tm->interface_params[if_id].speed_bin_index;
+ cl_val = mv_ddr_cl_val_get(speed_bin_index, freq);
+ data = (cl_val << 17) | (0x3 << 25);
+ mask = (0xff << 9) | (0x1f << 17) | (0x3 << 25);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ OPCODE_REG0_REG(1), data, mask));
+ }
+
+ /* Set iteration count to max value */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ OPCODE_REG1_REG(1), 0xd00, 0xd00));
+
+ /*
+ * Phase 2: Mask config
+ */
+
+ ddr3_tip_dynamic_per_bit_read_leveling_seq(dev_num);
+
+ /*
+ * Phase 3: Read Leveling execution
+ */
+
+ /* temporary jira dunit=14751 */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_DBG_1_REG, 0, (u32)(1 << 31)));
+ /* configure phy reset value */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_DBG_3_REG, (0x7f << 24),
+ (u32)(0xff << 24)));
+ /* data pup rd reset enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, 0, (1 << 30)));
+ /* data pup rd reset disable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, (1 << 30), (1 << 30)));
+ /* training SW override & training RL mode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x1, 0x9));
+ /* training enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_REG, (1 << 24) | (1 << 20),
+ (1 << 24) | (1 << 20)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_REG, (u32)(1 << 31), (u32)(1 << 31)));
+
+ /* trigger training */
+ mv_ddr_training_enable();
+
+ /* check for training done */
+ if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n"));
+ return MV_FAIL;
+ }
+ /* check for training pass */
+ if (data != PASS)
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n"));
+
+ /* disable odpg; switch back to functional mode */
+ mv_ddr_odpg_disable();
+
+ if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("odpg disable failed\n"));
+ return MV_FAIL;
+ }
+
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+
+ /* double loop on bus, pup */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* check training done */
+ for (bus_num = 0;
+ bus_num < octets_per_if_num;
+ bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num);
+
+ if (per_bit_rl_pup_status[if_id][bus_num]
+ == 0) {
+ curr_min_delay = 0;
+ for (bit_num = 0; bit_num < 8;
+ bit_num++) {
+ if (ddr3_tip_if_polling
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id, (1 << 25),
+ (1 << 25),
+ mask_results_dq_reg_map
+ [bus_num * 8 + bit_num],
+ MAX_POLLING_ITERATIONS) !=
+ MV_OK) {
+ DEBUG_LEVELING
+ (DEBUG_LEVEL_ERROR,
+ ("\n_r_l: DDR3 poll failed(2) for bus %d bit %d\n",
+ bus_num,
+ bit_num));
+ } else {
+ /* read result per pup */
+ CHECK_STATUS
+ (ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ mask_results_dq_reg_map
+ [bus_num * 8 +
+ bit_num],
+ data_read,
+ MASK_ALL_BITS));
+ data =
+ (data_read
+ [if_id] &
+ 0x1f) |
+ ((data_read
+ [if_id] &
+ 0xe0) << 1);
+ if (curr_min_delay == 0)
+ curr_min_delay =
+ data;
+ else if (data <
+ curr_min_delay)
+ curr_min_delay =
+ data;
+ if (data > data2_write[if_id][bus_num])
+ data2_write
+ [if_id]
+ [bus_num] =
+ data;
+ }
+ }
+
+ if (data2_write[if_id][bus_num] <=
+ (curr_min_delay +
+ MAX_DQ_READ_LEVELING_DELAY)) {
+ per_bit_rl_pup_status[if_id]
+ [bus_num] = 1;
+ }
+ }
+ }
+ }
+
+ /* check if there is need to search new phyreg3 value */
+ if (curr_numb < 2) {
+ /* if there is DLL that is not checked yet */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_num = 0;
+ bus_num < octets_per_if_num;
+ bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask,
+ bus_num);
+ if (per_bit_rl_pup_status[if_id]
+ [bus_num] != 1) {
+ /* go to next ADLL value */
+ CHECK_STATUS
+ (ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_num, DDR_PHY_DATA,
+ CRX_PHY_REG(0),
+ (phyreg3_arr[if_id]
+ [bus_num] +
+ adll_array[curr_numb])));
+ break_loop = 1;
+ break;
+ }
+ }
+ if (break_loop)
+ break;
+ }
+ } /* if (curr_numb < 2) */
+ if (!break_loop)
+ break;
+ } /* for ( curr_numb = 0; curr_numb <3; curr_numb++) */
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_num = 0; bus_num < octets_per_if_num;
+ bus_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num);
+ if (per_bit_rl_pup_status[if_id][bus_num] == 1)
+ ddr3_tip_bus_write(dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_num, DDR_PHY_DATA,
+ RL_PHY_REG(effective_cs),
+ data2_write[if_id]
+ [bus_num]);
+ else
+ is_any_pup_fail = 1;
+ }
+
+ /* TBD flow does not support multi CS */
+ /*
+ * cs_bitmask = tm->interface_params[if_id].
+ * as_bus_params[bus_num].cs_bitmask;
+ */
+ /* divide by 4 is used for retrieving the CS number */
+ /*
+ * TBD BC2 - what is the PHY address for other
+ * CS ddr3_tip_write_cs_result() ???
+ */
+ /*
+ * find what should be written to PHY
+ * - max delay that is less than threshold
+ */
+ if (is_any_pup_fail == 1) {
+ training_result[training_stage][if_id] = TEST_FAILED;
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+ }
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("RL exit read leveling\n"));
+
+ /*
+ * Phase 3: Exit Read Leveling
+ */
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, (1 << 3), (1 << 3)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_1_REG, (1 << 16), (1 << 16)));
+ /* set ODPG to functional */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS));
+ /*
+ * Copy the result from the effective CS search to the real
+ * Functional CS
+ */
+ ddr3_tip_write_cs_result(dev_num, RL_PHY_REG(0));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* restore cs enable value */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id],
+ MASK_ALL_BITS));
+ if (odt_config != 0) {
+ CHECK_STATUS(ddr3_tip_write_additional_odt_setting
+ (dev_num, if_id));
+ }
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (training_result[training_stage][if_id] == TEST_FAILED)
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs,
+ u32 *cs_mask)
+{
+ u32 all_bus_cs = 0, same_bus_cs;
+ u32 bus_cnt;
+ 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();
+
+ *cs_mask = same_bus_cs = CS_BIT_MASK;
+
+ /*
+ * In some of the devices (such as BC2), the CS is per pup and there
+ * for mixed mode is valid on like other devices where CS configuration
+ * is per interface.
+ * In order to know that, we do 'Or' and 'And' operation between all
+ * CS (of the pups).
+ * If they are they are not the same then it's mixed mode so all CS
+ * should be configured (when configuring the MRS)
+ */
+ for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+
+ all_bus_cs |= tm->interface_params[if_id].
+ as_bus_params[bus_cnt].cs_bitmask;
+ same_bus_cs &= tm->interface_params[if_id].
+ as_bus_params[bus_cnt].cs_bitmask;
+
+ /* cs enable is active low */
+ *cs_mask &= ~tm->interface_params[if_id].
+ as_bus_params[bus_cnt].cs_bitmask;
+ }
+
+ if (all_bus_cs == same_bus_cs)
+ *cs_mask = (*cs_mask | (~(1 << effective_cs))) & CS_BIT_MASK;
+
+ return MV_OK;
+}
+
+/*
+ * Dynamic write leveling
+ */
+int ddr3_tip_dynamic_write_leveling(u32 dev_num, int phase_remove)
+{
+ u32 reg_data = 0, temp = 0, iter, if_id, bus_cnt;
+ u32 cs_enable_reg_val[MAX_INTERFACE_NUM] = { 0 };
+ u32 cs_mask[MAX_INTERFACE_NUM];
+ u32 read_data_sample_delay_vals[MAX_INTERFACE_NUM] = { 0 };
+ u32 read_data_ready_delay_vals[MAX_INTERFACE_NUM] = { 0 };
+ /* 0 for failure */
+ u32 res_values[MAX_INTERFACE_NUM * MAX_BUS_NUM] = { 0 };
+ u32 test_res = 0; /* 0 - success for all pup */
+ u32 data_read[MAX_INTERFACE_NUM];
+ u8 wl_values[MAX_CS_NUM][MAX_BUS_NUM][MAX_INTERFACE_NUM];
+ u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
+ u32 cs_mask0[MAX_INTERFACE_NUM] = { 0 };
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ 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_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+
+ /* save Read Data Sample Delay */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ RD_DATA_SMPL_DLYS_REG,
+ read_data_sample_delay_vals, MASK_ALL_BITS));
+ /* save Read Data Ready Delay */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ RD_DATA_RDY_DLYS_REG, read_data_ready_delay_vals,
+ MASK_ALL_BITS));
+ /* save current cs reg val */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS));
+ }
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) {
+ /* Enable multi-CS */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, 0, (1 << 3)));
+ }
+
+ /*
+ * Phase 1: DRAM 2 Write Leveling mode
+ */
+
+ /*Assert 10 refresh commands to DRAM to all CS */
+ for (iter = 0; iter < WL_ITERATION_NUM; iter++) {
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; 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_OP_REG,
+ (u32)((~(0xf) << 8) | 0x2), 0xf1f));
+ }
+ }
+ /* check controller back to normal */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (ddr3_tip_if_polling
+ (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f,
+ SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("WL: DDR3 poll failed(3)"));
+ }
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ /*enable write leveling to all cs - Q off , WL n */
+ /* calculate interface cs mask */
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1,
+ 0x1000, 0x1080));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* cs enable is active low */
+ ddr3_tip_calc_cs_mask(dev_num, if_id, effective_cs,
+ &cs_mask[if_id]);
+ }
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
+ /* Enable Output buffer to relevant CS - Q on , WL on */
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd
+ (dev_num, cs_mask, MR_CMD1, 0x80, 0x1080));
+
+ /*enable odt for relevant CS */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ 0x1498, (0x3 << (effective_cs * 2)), 0xf));
+ } else {
+ /* FIXME: should be the same as _CPU case */
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd
+ (dev_num, cs_mask, MR_CMD1, 0xc0, 0x12c4));
+ }
+
+ /*
+ * Phase 2: Set training IP to write leveling mode
+ */
+
+ CHECK_STATUS(ddr3_tip_dynamic_write_leveling_seq(dev_num));
+
+ /* phase 3: trigger training */
+ mv_ddr_training_enable();
+
+ /* check for training done */
+ if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, data_read) != MV_OK) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n"));
+ } else { /* check for training pass */
+ reg_data = data_read[0];
+ if (tm->bus_act_mask == 0xb) /* set to data to 0 to skip the check */
+ reg_data = 0;
+ if (reg_data != PASS)
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n"));
+
+ /* check for training completion per bus */
+ for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ /* training status */
+ ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0,
+ mask_results_pup_reg_map[bus_cnt],
+ data_read, MASK_ALL_BITS);
+ reg_data = data_read[0];
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("WL: IF %d BUS %d reg 0x%x\n",
+ 0, bus_cnt, reg_data));
+ if ((reg_data & (1 << 25)) == 0)
+ res_values[bus_cnt] = 1;
+ ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0,
+ mask_results_pup_reg_map[bus_cnt],
+ data_read, 0xff);
+ /*
+ * Save the read value that should be
+ * write to PHY register
+ */
+ wl_values[effective_cs][bus_cnt][0] = (u8)data_read[0];
+ }
+ }
+
+ /*
+ * Phase 3.5: Validate result
+ */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ 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);
+ /*
+ * Read result control register according to subphy
+ * "16" below is for a half-phase
+ */
+ reg_data = wl_values[effective_cs][bus_cnt][if_id] + 16;
+ /*
+ * Write to WL register: ADLL [4:0], Phase [8:6],
+ * Centralization ADLL [15:10] + 0x10
+ */
+ reg_data = (reg_data & 0x1f) |
+ (((reg_data & 0xe0) >> 5) << 6) |
+ (((reg_data & 0x1f) + phy_reg1_val) << 10);
+ /* Search with WL CS0 subphy reg */
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_cnt,
+ DDR_PHY_DATA, WL_PHY_REG(0), reg_data);
+ /*
+ * Check for change in data read from DRAM.
+ * If changed, fix the result
+ */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ TRAINING_WL_REG,
+ data_read, MASK_ALL_BITS));
+ if (((data_read[if_id] & (1 << (bus_cnt + 20))) >>
+ (bus_cnt + 20)) == 0) {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_ERROR,
+ ("WLValues was changed from 0x%X",
+ wl_values[effective_cs]
+ [bus_cnt][if_id]));
+ wl_values[effective_cs]
+ [bus_cnt][if_id] += 32;
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_ERROR,
+ ("to 0x%X",
+ wl_values[effective_cs]
+ [bus_cnt][if_id]));
+ }
+ }
+ }
+
+ /*
+ * Phase 4: Exit write leveling mode
+ */
+
+ /* disable DQs toggling */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ WL_DQS_PATTERN_REG, 0x0, 0x1));
+
+ /* Update MRS 1 (WL off) */
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1,
+ 0x1000, 0x1080));
+ } else {
+ /* FIXME: should be same as _CPU case */
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1,
+ 0x1000, 0x12c4));
+ }
+
+ /* Update MRS 1 (return to functional mode - Q on , WL off) */
+ CHECK_STATUS(ddr3_tip_write_mrs_cmd
+ (dev_num, cs_mask0, MR_CMD1, 0x0, 0x1080));
+
+ /* set phy to normal mode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x5, 0x7));
+
+ /* exit sw override mode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x4, 0x7));
+ }
+
+ /*
+ * Phase 5: Load WL values to each PHY
+ */
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ test_res = 0;
+ for (bus_cnt = 0;
+ bus_cnt < octets_per_if_num;
+ bus_cnt++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
+ /* check if result == pass */
+ if (res_values
+ [(if_id *
+ octets_per_if_num) +
+ bus_cnt] == 0) {
+ /*
+ * read result control register
+ * according to pup
+ */
+ reg_data =
+ wl_values[effective_cs][bus_cnt]
+ [if_id];
+ /*
+ * Write into write leveling register
+ * ([4:0] ADLL, [8:6] Phase, [15:10]
+ * (centralization) ADLL + 0x10)
+ */
+ reg_data =
+ (reg_data & 0x1f) |
+ (((reg_data & 0xe0) >> 5) << 6) |
+ (((reg_data & 0x1f) +
+ phy_reg1_val) << 10);
+ /*
+ * in case phase remove should be executed
+ * need to remove more than one phase.
+ * this will take place only in low frequency,
+ * where there could be more than one phase between sub-phys
+ */
+ if (phase_remove == 1) {
+ temp = (reg_data >> WR_LVL_PH_SEL_OFFS) & WR_LVL_PH_SEL_PHASE1;
+ reg_data &= ~(WR_LVL_PH_SEL_MASK << WR_LVL_PH_SEL_OFFS);
+ reg_data |= (temp << WR_LVL_PH_SEL_OFFS);
+ }
+
+ ddr3_tip_bus_write(
+ dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_cnt,
+ DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs),
+ reg_data);
+ } else {
+ test_res = 1;
+ /*
+ * read result control register
+ * according to pup
+ */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ mask_results_pup_reg_map
+ [bus_cnt], data_read,
+ 0xff));
+ reg_data = data_read[if_id];
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_ERROR,
+ ("WL: IF %d BUS %d failed, reg 0x%x\n",
+ if_id, bus_cnt, reg_data));
+ }
+ }
+
+ if (test_res != 0) {
+ training_result[training_stage][if_id] =
+ TEST_FAILED;
+ }
+ }
+ }
+ /* Set to 0 after each loop to avoid illegal value may be used */
+ effective_cs = 0;
+
+ /*
+ * Copy the result from the effective CS search to the real
+ * Functional CS
+ */
+ /* ddr3_tip_write_cs_result(dev_num, WL_PHY_REG(0); */
+ /* restore saved values */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* restore Read Data Sample Delay */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ RD_DATA_SMPL_DLYS_REG,
+ read_data_sample_delay_vals[if_id],
+ MASK_ALL_BITS));
+
+ /* restore Read Data Ready Delay */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ RD_DATA_RDY_DLYS_REG,
+ read_data_ready_delay_vals[if_id],
+ MASK_ALL_BITS));
+
+ /* enable multi cs */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id],
+ MASK_ALL_BITS));
+ }
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
+ /* Disable modt0 for CS0 training - need to adjust for multi-CS
+ * in case of ddr4 set 0xf else 0
+ */
+ if (odt_config != 0) {
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf));
+ }
+ else {
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_ODT_CTRL_HIGH_REG, 0xf, 0xf));
+ }
+
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (training_result[training_stage][if_id] == TEST_FAILED)
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Dynamic write leveling supplementary
+ */
+int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num)
+{
+ int adll_offset;
+ u32 if_id, bus_id, data, data_tmp;
+ int is_if_fail = 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();
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ is_if_fail = 0;
+
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ wr_supp_res[if_id][bus_id].is_pup_fail = 1;
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs),
+ &data));
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("WL Supp: adll_offset=0 data delay = %d\n",
+ data));
+ if (ddr3_tip_wl_supp_align_phase_shift
+ (dev_num, if_id, bus_id) == MV_OK) {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("WL Supp: IF %d bus_id %d adll_offset=0 Success !\n",
+ if_id, bus_id));
+ continue;
+ }
+
+ /* change adll */
+ adll_offset = 5;
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs),
+ data + adll_offset));
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs),
+ &data_tmp));
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("WL Supp: adll_offset= %d data delay = %d\n",
+ adll_offset, data_tmp));
+
+ if (ddr3_tip_wl_supp_align_phase_shift
+ (dev_num, if_id, bus_id) == MV_OK) {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("WL Supp: IF %d bus_id %d adll_offset= %d Success !\n",
+ if_id, bus_id, adll_offset));
+ continue;
+ }
+
+ /* change adll */
+ adll_offset = -5;
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs),
+ data + adll_offset));
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs),
+ &data_tmp));
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("WL Supp: adll_offset= %d data delay = %d\n",
+ adll_offset, data_tmp));
+ if (ddr3_tip_wl_supp_align_phase_shift
+ (dev_num, if_id, bus_id) == MV_OK) {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("WL Supp: IF %d bus_id %d adll_offset= %d Success !\n",
+ if_id, bus_id, adll_offset));
+ continue;
+ } else {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_ERROR,
+ ("WL Supp: IF %d bus_id %d Failed !\n",
+ if_id, bus_id));
+ is_if_fail = 1;
+ }
+ }
+
+ if (is_if_fail == 1) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("WL Supp: CS# %d: IF %d failed\n",
+ effective_cs, if_id));
+ training_result[training_stage][if_id] = TEST_FAILED;
+ } else {
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+ }
+ }
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (training_result[training_stage][if_id] == TEST_FAILED)
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Phase Shift
+ */
+static int ddr3_tip_wl_supp_align_phase_shift(u32 dev_num, u32 if_id,
+ u32 bus_id)
+{
+ u32 original_phase;
+ u32 data, write_data;
+
+ wr_supp_res[if_id][bus_id].stage = PHASE_SHIFT;
+ if (ddr3_tip_xsb_compare_test
+ (dev_num, if_id, bus_id, 0) == MV_OK)
+ return MV_OK;
+
+ /* Read current phase */
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id,
+ DDR_PHY_DATA, WL_PHY_REG(effective_cs), &data));
+ original_phase = (data >> 6) & 0x7;
+
+ /* Set phase (0x0[6-8]) -2 */
+ if (original_phase >= 1) {
+ if (original_phase == 1)
+ write_data = data & ~0x1df;
+ else
+ write_data = (data & ~0x1c0) |
+ ((original_phase - 2) << 6);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), write_data);
+ if (ddr3_tip_xsb_compare_test
+ (dev_num, if_id, bus_id, -2) == MV_OK)
+ return MV_OK;
+ }
+
+ /* Set phase (0x0[6-8]) +2 */
+ if (original_phase <= 5) {
+ write_data = (data & ~0x1c0) |
+ ((original_phase + 2) << 6);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), write_data);
+ if (ddr3_tip_xsb_compare_test
+ (dev_num, if_id, bus_id, 2) == MV_OK)
+ return MV_OK;
+ }
+
+ /* Set phase (0x0[6-8]) +4 */
+ if (original_phase <= 3) {
+ write_data = (data & ~0x1c0) |
+ ((original_phase + 4) << 6);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), write_data);
+ if (ddr3_tip_xsb_compare_test
+ (dev_num, if_id, bus_id, 4) == MV_OK)
+ return MV_OK;
+ }
+
+ /* Set phase (0x0[6-8]) +6 */
+ if (original_phase <= 1) {
+ write_data = (data & ~0x1c0) |
+ ((original_phase + 6) << 6);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), write_data);
+ if (ddr3_tip_xsb_compare_test
+ (dev_num, if_id, bus_id, 6) == MV_OK)
+ return MV_OK;
+ }
+
+ /* Write original WL result back */
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), data);
+ wr_supp_res[if_id][bus_id].is_pup_fail = 1;
+
+ return MV_FAIL;
+}
+
+/*
+ * Compare Test
+ */
+static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id,
+ u32 edge_offset)
+{
+ u32 num_of_succ_byte_compare, word_in_pattern;
+ u32 word_offset, i, num_of_word_mult;
+ u32 read_pattern[TEST_PATTERN_LENGTH * 2];
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+ u32 pattern_test_pattern_table[8];
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /* 3 below for INTERFACE_BUS_MASK_16BIT */
+ num_of_word_mult = (tm->bus_act_mask == 3) ? 1 : 2;
+
+ for (i = 0; i < 8; i++) {
+ pattern_test_pattern_table[i] =
+ pattern_table_get_word(dev_num, PATTERN_TEST, (u8)i);
+ }
+
+ /* External write, read and compare */
+ CHECK_STATUS(ddr3_tip_load_pattern_to_mem(dev_num, PATTERN_TEST));
+
+ CHECK_STATUS(ddr3_tip_reset_fifo_ptr(dev_num));
+
+ CHECK_STATUS(ddr3_tip_ext_read
+ (dev_num, if_id,
+ ((pattern_table[PATTERN_TEST].start_addr << 3) +
+ ((SDRAM_CS_SIZE + 1) * effective_cs)), 1, read_pattern));
+
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("XSB-compt CS#%d: IF %d bus_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, if_id, bus_id,
+ read_pattern[0], read_pattern[1],
+ read_pattern[2], read_pattern[3],
+ read_pattern[4], read_pattern[5],
+ read_pattern[6], read_pattern[7]));
+
+ /* compare byte per pup */
+ num_of_succ_byte_compare = 0;
+ for (word_in_pattern = start_xsb_offset;
+ word_in_pattern < (TEST_PATTERN_LENGTH * num_of_word_mult);
+ word_in_pattern++) {
+ word_offset = word_in_pattern;
+ if ((word_offset > (TEST_PATTERN_LENGTH * 2 - 1)))
+ continue;
+
+ if ((read_pattern[word_in_pattern] & pup_mask_table[bus_id]) ==
+ (pattern_test_pattern_table[word_offset] &
+ pup_mask_table[bus_id]))
+ num_of_succ_byte_compare++;
+ }
+
+ if ((TEST_PATTERN_LENGTH * num_of_word_mult - start_xsb_offset) ==
+ num_of_succ_byte_compare) {
+ wr_supp_res[if_id][bus_id].stage = edge_offset;
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("supplementary: shift to %d for if %d pup %d success\n",
+ edge_offset, if_id, bus_id));
+ wr_supp_res[if_id][bus_id].is_pup_fail = 0;
+
+ return MV_OK;
+ } else {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("XSB-compt CS#%d: IF %d bus_id %d num_of_succ_byte_compare %d - Fail!\n",
+ effective_cs, if_id, bus_id, num_of_succ_byte_compare));
+
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("XSB-compt: expected 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ pattern_test_pattern_table[0],
+ pattern_test_pattern_table[1],
+ pattern_test_pattern_table[2],
+ pattern_test_pattern_table[3],
+ pattern_test_pattern_table[4],
+ pattern_test_pattern_table[5],
+ pattern_test_pattern_table[6],
+ pattern_test_pattern_table[7]));
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_TRACE,
+ ("XSB-compt: recieved 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ read_pattern[0], read_pattern[1],
+ read_pattern[2], read_pattern[3],
+ read_pattern[4], read_pattern[5],
+ read_pattern[6], read_pattern[7]));
+
+ return MV_FAIL;
+ }
+}
+
+/*
+ * Dynamic write leveling sequence
+ */
+static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num)
+{
+ u32 bus_id, dq_id;
+ 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();
+ 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();
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x1, 0x5));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_WL_REG, 0x50, 0xff));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_WL_REG, 0x5c, 0xff));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ GENERAL_TRAINING_OPCODE_REG, 0x381b82, 0x3c3faf));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ OPCODE_REG0_REG(1), (0x3 << 25), (0x3ffff << 9)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ OPCODE_REG1_REG(1), 0x80, 0xffff));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ WL_DONE_CNTR_REF_REG, 0x14, 0xff));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ TRAINING_WL_REG, 0xff5c, 0xffff));
+
+ /* mask PBS */
+ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_dq_reg_map[dq_id], 0x1 << 24,
+ 0x1 << 24));
+ }
+
+ /* Mask all results */
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_pup_reg_map[bus_id], 0x1 << 24,
+ 0x1 << 24));
+ }
+
+ /* Unmask only wanted */
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_pup_reg_map[bus_id], 0, 0x1 << 24));
+ }
+
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ WL_DQS_PATTERN_REG, 0x1, 0x1));
+
+ return MV_OK;
+}
+
+/*
+ * Dynamic read leveling sequence
+ */
+static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num)
+{
+ u32 bus_id, dq_id;
+ 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();
+ 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();
+
+ /* mask PBS */
+ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_dq_reg_map[dq_id], 0x1 << 24,
+ 0x1 << 24));
+ }
+
+ /* Mask all results */
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_pup_reg_map[bus_id], 0x1 << 24,
+ 0x1 << 24));
+ }
+
+ /* Unmask only wanted */
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_pup_reg_map[bus_id], 0, 0x1 << 24));
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Dynamic read leveling sequence
+ */
+static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num)
+{
+ u32 bus_id, dq_id;
+ 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();
+ 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();
+
+ /* mask PBS */
+ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_dq_reg_map[dq_id], 0x1 << 24,
+ 0x1 << 24));
+ }
+
+ /* Mask all results */
+ for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_pup_reg_map[bus_id], 0x1 << 24,
+ 0x1 << 24));
+ }
+
+ /* Unmask only wanted */
+ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, dq_id / 8);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ mask_results_dq_reg_map[dq_id], 0x0 << 24,
+ 0x1 << 24));
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Print write leveling supplementary results
+ */
+int ddr3_tip_print_wl_supp_result(u32 dev_num)
+{
+ u32 bus_id = 0, if_id = 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();
+
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO,
+ ("I/F0 PUP0 Result[0 - success, 1-fail] ...\n"));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0; bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO,
+ ("%d ,", wr_supp_res[if_id]
+ [bus_id].is_pup_fail));
+ }
+ }
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_INFO,
+ ("I/F0 PUP0 Stage[0-phase_shift, 1-clock_shift, 2-align_shift] ...\n"));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bus_id = 0; bus_id < octets_per_if_num;
+ bus_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO,
+ ("%d ,", wr_supp_res[if_id]
+ [bus_id].stage));
+ }
+ }
+
+ return MV_OK;
+}
+
+#define RD_FIFO_PTR_LOW_STAT_INDIR_ADDR 0x9a
+#define RD_FIFO_PTR_HIGH_STAT_INDIR_ADDR 0x9b
+/* position of falling dqs edge in fifo; walking 1 */
+#define RD_FIFO_DQS_FALL_EDGE_POS_0 0x1
+#define RD_FIFO_DQS_FALL_EDGE_POS_1 0x2
+#define RD_FIFO_DQS_FALL_EDGE_POS_2 0x4
+#define RD_FIFO_DQS_FALL_EDGE_POS_3 0x8
+#define RD_FIFO_DQS_FALL_EDGE_POS_4 0x10 /* lock */
+/* position of rising dqs edge in fifo; walking 0 */
+#define RD_FIFO_DQS_RISE_EDGE_POS_0 0x1fff
+#define RD_FIFO_DQS_RISE_EDGE_POS_1 0x3ffe
+#define RD_FIFO_DQS_RISE_EDGE_POS_2 0x3ffd
+#define RD_FIFO_DQS_RISE_EDGE_POS_3 0x3ffb
+#define RD_FIFO_DQS_RISE_EDGE_POS_4 0x3ff7 /* lock */
+#define TEST_ADDR 0x8
+#define TAPS_PER_UI 32
+#define UI_PER_RD_SAMPLE 4
+#define TAPS_PER_RD_SAMPLE ((UI_PER_RD_SAMPLE) * (TAPS_PER_UI))
+#define MAX_RD_SAMPLES 32
+#define MAX_RL_VALUE ((MAX_RD_SAMPLES) * (TAPS_PER_RD_SAMPLE))
+#define RD_FIFO_DLY 8
+#define STEP_SIZE 64
+#define RL_JITTER_WIDTH_LMT 20
+#define ADLL_TAPS_IN_CYCLE 64
+
+enum rl_dqs_burst_state {
+ RL_AHEAD = 0,
+ RL_INSIDE,
+ RL_BEHIND
+};
+
+
+int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq)
+{
+ enum rl_dqs_burst_state rl_state[MAX_CS_NUM][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } };
+ enum hws_ddr_phy subphy_type = DDR_PHY_DATA;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ int cl_val = tm->interface_params[0].cas_l;
+ int rl_adll_val, rl_phase_val, sdr_cycle_incr, rd_sample, rd_ready;
+ int final_rd_sample, final_rd_ready;
+ int i, subphy_id, step;
+ int pass_lock_num = 0;
+ int init_pass_lock_num;
+ int phase_delta;
+ int min_phase, max_phase;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ u32 rl_values[MAX_CS_NUM][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } };
+ u32 rl_min_values[MAX_CS_NUM][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } };
+ u32 rl_max_values[MAX_CS_NUM][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } };
+ u32 rl_val, rl_min_val[MAX_CS_NUM], rl_max_val[MAX_CS_NUM];
+ u32 reg_val_low, reg_val_high;
+ u32 reg_val, reg_mask;
+ uintptr_t test_addr = TEST_ADDR;
+
+
+ /* initialization */
+ if (mv_ddr_is_ecc_ena()) {
+ ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, TRAINING_SW_2_REG,
+ &reg_val, MASK_ALL_BITS);
+ reg_mask = (TRAINING_ECC_MUX_MASK << TRAINING_ECC_MUX_OFFS) |
+ (TRAINING_SW_OVRD_MASK << TRAINING_SW_OVRD_OFFS);
+ reg_val &= ~reg_mask;
+ reg_val |= (TRAINING_ECC_MUX_DIS << TRAINING_ECC_MUX_OFFS) |
+ (TRAINING_SW_OVRD_ENA << TRAINING_SW_OVRD_OFFS);
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_SW_2_REG,
+ reg_val, MASK_ALL_BITS);
+ ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, TRAINING_REG,
+ &reg_val, MASK_ALL_BITS);
+ reg_mask = (TRN_START_MASK << TRN_START_OFFS);
+ reg_val &= ~reg_mask;
+ reg_val |= TRN_START_ENA << TRN_START_OFFS;
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG,
+ reg_val, MASK_ALL_BITS);
+ }
+
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++)
+ for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++)
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++)
+ if (IS_BUS_ACTIVE(tm->bus_act_mask, subphy_id) == 0)
+ pass_lock_num++; /* increment on inactive subphys */
+
+ init_pass_lock_num = pass_lock_num / max_cs;
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+ }
+ }
+
+ /* search for dqs edges per subphy */
+ if_id = 0;
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+
+ pass_lock_num = init_pass_lock_num;
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG,
+ effective_cs << ODPG_DATA_CS_OFFS,
+ ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS);
+ rl_min_val[effective_cs] = MAX_RL_VALUE;
+ rl_max_val[effective_cs] = 0;
+ step = STEP_SIZE;
+ for (i = 0; i < MAX_RL_VALUE; i += step) {
+ rl_val = 0;
+ sdr_cycle_incr = i / TAPS_PER_RD_SAMPLE; /* sdr cycle increment */
+ rd_sample = cl_val + 2 * sdr_cycle_incr;
+ /* fifo out to in delay in search is constant */
+ rd_ready = rd_sample + RD_FIFO_DLY;
+
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_SMPL_DLYS_REG,
+ rd_sample << RD_SMPL_DLY_CS_OFFS(effective_cs),
+ RD_SMPL_DLY_CS_MASK << RD_SMPL_DLY_CS_OFFS(effective_cs));
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_RDY_DLYS_REG,
+ rd_ready << RD_RDY_DLY_CS_OFFS(effective_cs),
+ RD_RDY_DLY_CS_MASK << RD_RDY_DLY_CS_OFFS(effective_cs));
+
+ /* one sdr (single data rate) cycle incremented on every four phases of ddr clock */
+ sdr_cycle_incr = i % TAPS_PER_RD_SAMPLE;
+ rl_adll_val = sdr_cycle_incr % MAX_RD_SAMPLES;
+ rl_phase_val = sdr_cycle_incr / MAX_RD_SAMPLES;
+ rl_val = ((rl_adll_val & RL_REF_DLY_MASK) << RL_REF_DLY_OFFS) |
+ ((rl_phase_val & RL_PH_SEL_MASK) << RL_PH_SEL_OFFS);
+
+ /* write to all subphys (even to not connected or locked) */
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ 0, DDR_PHY_DATA, RL_PHY_REG(effective_cs), rl_val);
+
+ /* reset read fifo assertion */
+ ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG,
+ DATA_PUP_RD_RESET_ENA << DATA_PUP_RD_RESET_OFFS,
+ DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS);
+
+ /* reset read fifo deassertion */
+ ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG,
+ DATA_PUP_RD_RESET_DIS << DATA_PUP_RD_RESET_OFFS,
+ DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS);
+
+ /* perform one read burst */
+ if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask))
+ readq(test_addr);
+ else
+ readl(test_addr);
+
+ /* progress read ptr; decide on rl state per byte */
+ for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) {
+ if (rl_state[effective_cs][subphy_id][if_id] == RL_BEHIND)
+ continue; /* skip locked subphys */
+ ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_id, DDR_PHY_DATA,
+ RD_FIFO_PTR_LOW_STAT_INDIR_ADDR, &reg_val_low);
+ ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_id, DDR_PHY_DATA,
+ RD_FIFO_PTR_HIGH_STAT_INDIR_ADDR, &reg_val_high);
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("%s: cs %d, step %d, subphy %d, state %d, low 0x%04x, high 0x%04x; move to ",
+ __func__, effective_cs, i, subphy_id,
+ rl_state[effective_cs][subphy_id][if_id],
+ reg_val_low, reg_val_high));
+
+ switch (rl_state[effective_cs][subphy_id][if_id]) {
+ case RL_AHEAD:
+ /* improve search resolution getting closer to the window */
+ if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_4 &&
+ reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_4) {
+ rl_state[effective_cs][subphy_id][if_id] = RL_INSIDE;
+ rl_values[effective_cs][subphy_id][if_id] = i;
+ rl_min_values[effective_cs][subphy_id][if_id] = i;
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("new state %d\n",
+ rl_state[effective_cs][subphy_id][if_id]));
+ } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_3 &&
+ reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_3) {
+ step = (step < 2) ? step : 2;
+ } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_2 &&
+ reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_2) {
+ step = (step < 16) ? step : 16;
+ } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_1 &&
+ reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_1) {
+ step = (step < 32) ? step : 32;
+ } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_0 &&
+ reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_0) {
+ step = (step < 64) ? step : 64;
+ } else {
+ /* otherwise, step is unchanged */
+ }
+ break;
+ case RL_INSIDE:
+ if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_4 &&
+ reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_4) {
+ rl_max_values[effective_cs][subphy_id][if_id] = i;
+ if ((rl_max_values[effective_cs][subphy_id][if_id] -
+ rl_min_values[effective_cs][subphy_id][if_id]) >
+ ADLL_TAPS_IN_CYCLE) {
+ rl_state[effective_cs][subphy_id][if_id] = RL_BEHIND;
+ rl_values[effective_cs][subphy_id][if_id] =
+ (i + rl_values[effective_cs][subphy_id][if_id]) / 2;
+ pass_lock_num++;
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("new lock %d\n", pass_lock_num));
+ if (rl_min_val[effective_cs] >
+ rl_values[effective_cs][subphy_id][if_id])
+ rl_min_val[effective_cs] =
+ rl_values[effective_cs][subphy_id][if_id];
+ if (rl_max_val[effective_cs] <
+ rl_values[effective_cs][subphy_id][if_id])
+ rl_max_val[effective_cs] =
+ rl_values[effective_cs][subphy_id][if_id];
+ step = 2;
+ }
+ }
+ if (reg_val_low != RD_FIFO_DQS_FALL_EDGE_POS_4 ||
+ reg_val_high != RD_FIFO_DQS_RISE_EDGE_POS_4) {
+ if ((i - rl_values[effective_cs][subphy_id][if_id]) <
+ RL_JITTER_WIDTH_LMT) {
+ /* inside the jitter; not valid segment */
+ rl_state[effective_cs][subphy_id][if_id] = RL_AHEAD;
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("new state %d; jitter on mask\n",
+ rl_state[effective_cs][subphy_id][if_id]));
+ } else { /* finished valid segment */
+ rl_state[effective_cs][subphy_id][if_id] = RL_BEHIND;
+ rl_values[effective_cs][subphy_id][if_id] =
+ (i + rl_values[effective_cs][subphy_id][if_id]) / 2;
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("new state %d, solution %d\n",
+ rl_state[effective_cs][subphy_id][if_id],
+ rl_values[effective_cs][subphy_id][if_id]));
+ pass_lock_num++;
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE,
+ ("new lock %d\n", pass_lock_num));
+ if (rl_min_val[effective_cs] >
+ rl_values[effective_cs][subphy_id][if_id])
+ rl_min_val[effective_cs] =
+ rl_values[effective_cs][subphy_id][if_id];
+ if (rl_max_val[effective_cs] <
+ rl_values[effective_cs][subphy_id][if_id])
+ rl_max_val[effective_cs] =
+ rl_values[effective_cs][subphy_id][if_id];
+ step = 2;
+ }
+ }
+ break;
+ case RL_BEHIND: /* do nothing */
+ break;
+ }
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("\n"));
+ }
+ DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("pass_lock_num %d\n", pass_lock_num));
+ /* exit condition */
+ if (pass_lock_num == MAX_BUS_NUM)
+ break;
+ } /* for-loop on i */
+
+ if (pass_lock_num != MAX_BUS_NUM) {
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("%s: cs %d, pass_lock_num %d, max_bus_num %d, init_pass_lock_num %d\n",
+ __func__, effective_cs, pass_lock_num, MAX_BUS_NUM, init_pass_lock_num));
+ for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_id);
+ DEBUG_LEVELING(DEBUG_LEVEL_ERROR,
+ ("%s: subphy %d %s\n",
+ __func__, subphy_id,
+ (rl_state[effective_cs][subphy_id][if_id] == RL_BEHIND) ?
+ "locked" : "not locked"));
+ }
+ }
+ } /* for-loop on effective_cs */
+
+ /* post-processing read leveling results */
+ if_id = 0;
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+ phase_delta = 0;
+ i = rl_min_val[effective_cs];
+ sdr_cycle_incr = i / TAPS_PER_RD_SAMPLE; /* sdr cycle increment */
+ rd_sample = cl_val + 2 * sdr_cycle_incr;
+ rd_ready = rd_sample + RD_FIFO_DLY;
+ min_phase = (rl_min_val[effective_cs] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE)) % MAX_RD_SAMPLES;
+ max_phase = (rl_max_val[effective_cs] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE)) % MAX_RD_SAMPLES;
+ final_rd_sample = rd_sample;
+ final_rd_ready = rd_ready;
+
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_SMPL_DLYS_REG,
+ rd_sample << RD_SMPL_DLY_CS_OFFS(effective_cs),
+ RD_SMPL_DLY_CS_MASK << RD_SMPL_DLY_CS_OFFS(effective_cs));
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_RDY_DLYS_REG,
+ rd_ready << RD_RDY_DLY_CS_OFFS(effective_cs),
+ RD_RDY_DLY_CS_MASK << RD_RDY_DLY_CS_OFFS(effective_cs));
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO,
+ ("%s: cs %d, min phase %d, max phase %d, read sample %d\n",
+ __func__, effective_cs, min_phase, max_phase, rd_sample));
+
+ for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_id);
+ /* reduce sdr cycle per cs; extract rl adll and phase values */
+ i = rl_values[effective_cs][subphy_id][if_id] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE);
+ rl_adll_val = i % MAX_RD_SAMPLES;
+ rl_phase_val = i / MAX_RD_SAMPLES;
+ rl_phase_val -= phase_delta;
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO,
+ ("%s: final results: cs %d, subphy %d, read sample %d read ready %d, rl_phase_val %d, rl_adll_val %d\n",
+ __func__, effective_cs, subphy_id, final_rd_sample,
+ final_rd_ready, rl_phase_val, rl_adll_val));
+
+ rl_val = ((rl_adll_val & RL_REF_DLY_MASK) << RL_REF_DLY_OFFS) |
+ ((rl_phase_val & RL_PH_SEL_MASK) << RL_PH_SEL_OFFS);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_UNICAST,
+ subphy_id, subphy_type, RL_PHY_REG(effective_cs), rl_val);
+ }
+ } /* for-loop on effective cs */
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (odt_config != 0)
+ CHECK_STATUS(ddr3_tip_write_additional_odt_setting(dev_num, if_id));
+ }
+
+
+ /* reset read fifo assertion */
+ ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG,
+ DATA_PUP_RD_RESET_ENA << DATA_PUP_RD_RESET_OFFS,
+ DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS);
+
+ /* reset read fifo deassertion */
+ ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG,
+ DATA_PUP_RD_RESET_DIS << DATA_PUP_RD_RESET_OFFS,
+ DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS);
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.h
new file mode 100644
index 000000000..6719fb83f
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_leveling.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR3_TRAINING_LEVELING_H_
+#define _DDR3_TRAINING_LEVELING_H_
+
+#define MAX_DQ_READ_LEVELING_DELAY 15
+
+int ddr3_tip_print_wl_supp_result(u32 dev_num);
+int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs,
+ u32 *cs_mask);
+
+#endif /* _DDR3_TRAINING_LEVELING_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_pbs.c b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_pbs.c
new file mode 100644
index 000000000..b7dfebd93
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr3_training_pbs.c
@@ -0,0 +1,1012 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_training_db.h"
+#include "mv_ddr_common.h"
+#include "mv_ddr_regs.h"
+
+#define TYPICAL_PBS_VALUE 12
+
+u32 nominal_adll[MAX_INTERFACE_NUM * MAX_BUS_NUM];
+enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
+u8 result_mat[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+u8 result_mat_rx_dqs[MAX_INTERFACE_NUM][MAX_BUS_NUM][MAX_CS_NUM];
+/* 4-EEWA, 3-EWA, 2-SWA, 1-Fail, 0-Pass */
+u8 result_all_bit[MAX_BUS_NUM * BUS_WIDTH_IN_BITS * MAX_INTERFACE_NUM];
+u8 max_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 min_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 max_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 min_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u32 pbsdelay_per_pup[NUM_OF_PBS_MODES][MAX_INTERFACE_NUM][MAX_BUS_NUM][MAX_CS_NUM];
+u8 adll_shift_lock[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+u8 adll_shift_val[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+enum hws_pattern pbs_pattern = PATTERN_VREF;
+static u8 pup_state[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+
+/*
+ * Name: ddr3_tip_pbs
+ * Desc: PBS
+ * Args: TBD
+ * Notes:
+ * Returns: OK if success, other error code if fail.
+ */
+int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode)
+{
+ u32 res0[MAX_INTERFACE_NUM];
+ int adll_tap = MEGA / mv_ddr_freq_get(medium_freq) / 64;
+ int pad_num = 0;
+ enum hws_search_dir search_dir =
+ (pbs_mode == PBS_RX_MODE) ? HWS_HIGH2LOW : HWS_LOW2HIGH;
+ enum hws_dir dir = (pbs_mode == PBS_RX_MODE) ? OPER_READ : OPER_WRITE;
+ int iterations = (pbs_mode == PBS_RX_MODE) ? 31 : 63;
+ u32 res_valid_mask = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f;
+ int init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations;
+ enum hws_edge_compare search_edge = EDGE_FP;
+ u32 pup = 0, bit = 0, if_id = 0, all_lock = 0, cs_num = 0;
+ u32 reg_addr = 0;
+ u32 validation_val = 0;
+ u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
+ u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
+ u8 temp = 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();
+
+ /* save current cs enable reg val */
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ /* save current cs enable reg val */
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS));
+
+ /* enable single cs */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
+ }
+
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ CRX_PHY_REG(effective_cs) :
+ CTX_PHY_REG(effective_cs);
+ ddr3_tip_read_adll_value(dev_num, nominal_adll, reg_addr, MASK_ALL_BITS);
+
+ /* stage 1 shift ADLL */
+ ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, RESULT_PER_BIT,
+ HWS_CONTROL_ELEMENT_ADLL, search_dir, dir,
+ tm->if_act_mask, init_val, iterations,
+ pbs_pattern, search_edge, CS_SINGLE, cs_num,
+ train_status);
+ validation_val = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0;
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ min_adll_per_pup[if_id][pup] =
+ (pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f;
+ pup_state[if_id][pup] = 0x3;
+ adll_shift_lock[if_id][pup] = 1;
+ max_adll_per_pup[if_id][pup] = 0x0;
+ }
+ }
+
+ /* EBA */
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ mask_results_dq_reg_map[
+ bit + pup * BUS_WIDTH_IN_BITS],
+ res0, MASK_ALL_BITS));
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
+ if_id, bit, pup,
+ res0[if_id]));
+ if (pup_state[if_id][pup] != 3)
+ continue;
+ /* if not EBA state than move to next pup */
+
+ if ((res0[if_id] & 0x2000000) == 0) {
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("-- Fail Training IP\n"));
+ /* training machine failed */
+ pup_state[if_id][pup] = 1;
+ adll_shift_lock[if_id][pup] = 0;
+ continue;
+ }
+
+ else if ((res0[if_id] & res_valid_mask) ==
+ validation_val) {
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("-- FAIL EBA %d %d %d %d\n",
+ if_id, bit, pup,
+ res0[if_id]));
+ pup_state[if_id][pup] = 4;
+ /* this pup move to EEBA */
+ adll_shift_lock[if_id][pup] = 0;
+ continue;
+ } else {
+ /*
+ * The search ended in Pass we need
+ * Fail
+ */
+ res0[if_id] =
+ (pbs_mode == PBS_RX_MODE) ?
+ ((res0[if_id] &
+ res_valid_mask) + 1) :
+ ((res0[if_id] &
+ res_valid_mask) - 1);
+ max_adll_per_pup[if_id][pup] =
+ (max_adll_per_pup[if_id][pup] <
+ res0[if_id]) ?
+ (u8)res0[if_id] :
+ max_adll_per_pup[if_id][pup];
+ min_adll_per_pup[if_id][pup] =
+ (res0[if_id] >
+ min_adll_per_pup[if_id][pup]) ?
+ min_adll_per_pup[if_id][pup] :
+ (u8)
+ res0[if_id];
+ /*
+ * vs the Rx we are searching for the
+ * smallest value of DQ shift so all
+ * Bus would fail
+ */
+ adll_shift_val[if_id][pup] =
+ (pbs_mode == PBS_RX_MODE) ?
+ max_adll_per_pup[if_id][pup] :
+ min_adll_per_pup[if_id][pup];
+ }
+ }
+ }
+ }
+
+ /* EEBA */
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ if (pup_state[if_id][pup] != 4)
+ continue;
+ /*
+ * if pup state different from EEBA than move to
+ * next pup
+ */
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x54 + effective_cs * 0x10) :
+ (0x14 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA,
+ reg_addr, 0x1f));
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x55 + effective_cs * 0x10) :
+ (0x15 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA,
+ reg_addr, 0x1f));
+ /* initialize the Edge2 Max. */
+ adll_shift_val[if_id][pup] = 0;
+ min_adll_per_pup[if_id][pup] =
+ (pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f;
+ max_adll_per_pup[if_id][pup] = 0x0;
+
+ ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, RESULT_PER_BIT,
+ HWS_CONTROL_ELEMENT_ADLL,
+ search_dir, dir,
+ tm->if_act_mask, init_val,
+ iterations, pbs_pattern,
+ search_edge, CS_SINGLE, cs_num,
+ train_status);
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ ("ADLL shift results:\n"));
+
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ mask_results_dq_reg_map[
+ bit + pup *
+ BUS_WIDTH_IN_BITS],
+ res0, MASK_ALL_BITS));
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
+ if_id, bit, pup,
+ res0[if_id]));
+
+ if ((res0[if_id] & 0x2000000) == 0) {
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ (" -- EEBA Fail\n"));
+ bit = BUS_WIDTH_IN_BITS;
+ /* exit bit loop */
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("-- EEBA Fail Training IP\n"));
+ /*
+ * training machine failed but pass
+ * before in the EBA so maybe the DQS
+ * shift change env.
+ */
+ pup_state[if_id][pup] = 2;
+ adll_shift_lock[if_id][pup] = 0;
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x54 + effective_cs * 0x10) :
+ (0x14 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ 0x0));
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x55 + effective_cs * 0x10) :
+ (0x15 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ 0x0));
+ continue;
+ } else if ((res0[if_id] & res_valid_mask) ==
+ validation_val) {
+ /* exit bit loop */
+ bit = BUS_WIDTH_IN_BITS;
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("-- FAIL EEBA\n"));
+ /* this pup move to SBA */
+ pup_state[if_id][pup] = 2;
+ adll_shift_lock[if_id][pup] = 0;
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x54 + effective_cs * 0x10) :
+ (0x14 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ 0x0));
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x55 + effective_cs * 0x10) :
+ (0x15 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num,
+ ACCESS_TYPE_UNICAST,
+ if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ 0x0));
+ continue;
+ } else {
+ adll_shift_lock[if_id][pup] = 1;
+ /*
+ * The search ended in Pass we need
+ * Fail
+ */
+ res0[if_id] =
+ (pbs_mode == PBS_RX_MODE) ?
+ ((res0[if_id] &
+ res_valid_mask) + 1) :
+ ((res0[if_id] &
+ res_valid_mask) - 1);
+ max_adll_per_pup[if_id][pup] =
+ (max_adll_per_pup[if_id][pup] <
+ res0[if_id]) ?
+ (u8)res0[if_id] :
+ max_adll_per_pup[if_id][pup];
+ min_adll_per_pup[if_id][pup] =
+ (res0[if_id] >
+ min_adll_per_pup[if_id][pup]) ?
+ min_adll_per_pup[if_id][pup] :
+ (u8)res0[if_id];
+ /*
+ * vs the Rx we are searching for the
+ * smallest value of DQ shift so all Bus
+ * would fail
+ */
+ adll_shift_val[if_id][pup] =
+ (pbs_mode == PBS_RX_MODE) ?
+ max_adll_per_pup[if_id][pup] :
+ min_adll_per_pup[if_id][pup];
+ }
+ }
+ }
+ }
+
+ /* Print Stage result */
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("FP I/F %d, ADLL Shift for EBA: pup[%d] Lock status = %d Lock Val = %d,%d\n",
+ if_id, pup,
+ adll_shift_lock[if_id][pup],
+ max_adll_per_pup[if_id][pup],
+ min_adll_per_pup[if_id][pup]));
+ }
+ }
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ ("Update ADLL Shift of all pups:\n"));
+
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (adll_shift_lock[if_id][pup] != 1)
+ continue;
+ /* if pup not locked continue to next pup */
+
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x3 + effective_cs * 4) :
+ (0x1 + effective_cs * 4);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA,
+ reg_addr, adll_shift_val[if_id][pup]));
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
+ ("FP I/F %d, Pup[%d] = %d\n", if_id,
+ pup, adll_shift_val[if_id][pup]));
+ }
+ }
+
+ /* PBS EEBA&EBA */
+ /* Start the Per Bit Skew search */
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ max_pbs_per_pup[if_id][pup] = 0x0;
+ min_pbs_per_pup[if_id][pup] = 0x1f;
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ /* reset result for PBS */
+ result_all_bit[bit + pup * BUS_WIDTH_IN_BITS +
+ if_id * MAX_BUS_NUM *
+ BUS_WIDTH_IN_BITS] = 0;
+ }
+ }
+ }
+
+ iterations = 31;
+ search_dir = HWS_LOW2HIGH;
+ /* !!!!! ran sh (search_dir == HWS_LOW2HIGH)?0:iterations; */
+ init_val = 0;
+
+ ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ RESULT_PER_BIT, HWS_CONTROL_ELEMENT_DQ_SKEW,
+ search_dir, dir, tm->if_act_mask, init_val,
+ iterations, pbs_pattern, search_edge,
+ CS_SINGLE, cs_num, train_status);
+
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (adll_shift_lock[if_id][pup] != 1) {
+ /* if pup not lock continue to next pup */
+ continue;
+ }
+
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ mask_results_dq_reg_map[
+ bit +
+ pup * BUS_WIDTH_IN_BITS],
+ res0, MASK_ALL_BITS));
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ ("Per Bit Skew search, FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
+ if_id, bit, pup,
+ res0[if_id]));
+ if ((res0[if_id] & 0x2000000) == 0) {
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ ("--EBA PBS Fail - Training IP machine\n"));
+ /* exit the bit loop */
+ bit = BUS_WIDTH_IN_BITS;
+ /*
+ * ADLL is no long in lock need new
+ * search
+ */
+ adll_shift_lock[if_id][pup] = 0;
+ /* Move to SBA */
+ pup_state[if_id][pup] = 2;
+ max_pbs_per_pup[if_id][pup] = 0x0;
+ min_pbs_per_pup[if_id][pup] = 0x1f;
+ continue;
+ } else {
+ temp = (u8)(res0[if_id] &
+ res_valid_mask);
+ max_pbs_per_pup[if_id][pup] =
+ (temp >
+ max_pbs_per_pup[if_id][pup]) ?
+ temp :
+ max_pbs_per_pup[if_id][pup];
+ min_pbs_per_pup[if_id][pup] =
+ (temp <
+ min_pbs_per_pup[if_id][pup]) ?
+ temp :
+ min_pbs_per_pup[if_id][pup];
+ result_all_bit[bit +
+ pup * BUS_WIDTH_IN_BITS +
+ if_id * MAX_BUS_NUM *
+ BUS_WIDTH_IN_BITS] =
+ temp;
+ }
+ }
+ }
+ }
+
+ /* Check all Pup lock */
+ all_lock = 1;
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ all_lock = all_lock * adll_shift_lock[if_id][pup];
+ }
+ }
+
+ /* Only if not all Pups Lock */
+ if (all_lock == 0) {
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ ("##########ADLL shift for SBA###########\n"));
+
+ /* ADLL shift for SBA */
+ search_dir = (pbs_mode == PBS_RX_MODE) ? HWS_LOW2HIGH :
+ HWS_HIGH2LOW;
+ init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations;
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ if (adll_shift_lock[if_id][pup] == 1) {
+ /*if pup lock continue to next pup */
+ continue;
+ }
+ /*init the var altogth init before */
+ adll_shift_lock[if_id][pup] = 0;
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x54 + effective_cs * 0x10) :
+ (0x14 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr, 0));
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x55 + effective_cs * 0x10) :
+ (0x15 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr, 0));
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x5f + effective_cs * 0x10) :
+ (0x1f + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr, 0));
+ /* initilaze the Edge2 Max. */
+ adll_shift_val[if_id][pup] = 0;
+ min_adll_per_pup[if_id][pup] = 0x1f;
+ max_adll_per_pup[if_id][pup] = 0x0;
+
+ ddr3_tip_ip_training(dev_num,
+ ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ RESULT_PER_BIT,
+ HWS_CONTROL_ELEMENT_ADLL,
+ search_dir, dir,
+ tm->if_act_mask,
+ init_val, iterations,
+ pbs_pattern,
+ search_edge, CS_SINGLE,
+ cs_num, train_status);
+
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ mask_results_dq_reg_map
+ [bit +
+ pup *
+ BUS_WIDTH_IN_BITS],
+ res0, MASK_ALL_BITS));
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
+ if_id, bit, pup, res0[if_id]));
+ if ((res0[if_id] & 0x2000000) == 0) {
+ /* exit the bit loop */
+ bit = BUS_WIDTH_IN_BITS;
+ /* Fail SBA --> Fail PBS */
+ pup_state[if_id][pup] = 1;
+ DEBUG_PBS_ENGINE
+ (DEBUG_LEVEL_INFO,
+ (" SBA Fail\n"));
+ continue;
+ } else {
+ /*
+ * - increment to get all
+ * 8 bit lock.
+ */
+ adll_shift_lock[if_id][pup]++;
+ /*
+ * The search ended in Pass
+ * we need Fail
+ */
+ res0[if_id] =
+ (pbs_mode == PBS_RX_MODE) ?
+ ((res0[if_id] & res_valid_mask) + 1) :
+ ((res0[if_id] & res_valid_mask) - 1);
+ max_adll_per_pup[if_id][pup] =
+ (max_adll_per_pup[if_id]
+ [pup] < res0[if_id]) ?
+ (u8)res0[if_id] :
+ max_adll_per_pup[if_id][pup];
+ min_adll_per_pup[if_id][pup] =
+ (res0[if_id] >
+ min_adll_per_pup[if_id]
+ [pup]) ?
+ min_adll_per_pup[if_id][pup] :
+ (u8)res0[if_id];
+ /*
+ * vs the Rx we are searching for
+ * the smallest value of DQ shift
+ * so all Bus would fail
+ */
+ adll_shift_val[if_id][pup] =
+ (pbs_mode == PBS_RX_MODE) ?
+ max_adll_per_pup[if_id][pup] :
+ min_adll_per_pup[if_id][pup];
+ }
+ }
+ /* 1 is lock */
+ adll_shift_lock[if_id][pup] =
+ (adll_shift_lock[if_id][pup] == 8) ?
+ 1 : 0;
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x3 + effective_cs * 4) :
+ (0x1 + effective_cs * 4);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ adll_shift_val[if_id][pup]));
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("adll_shift_lock[%x][%x] = %x\n",
+ if_id, pup,
+ adll_shift_lock[if_id][pup]));
+ }
+ }
+
+ /* End ADLL Shift for SBA */
+ /* Start the Per Bit Skew search */
+ /* The ADLL shift finished with a Pass */
+ search_edge = (pbs_mode == PBS_RX_MODE) ? EDGE_PF : EDGE_FP;
+ search_dir = (pbs_mode == PBS_RX_MODE) ?
+ HWS_LOW2HIGH : HWS_HIGH2LOW;
+ iterations = 0x1f;
+ /* - The initial value is different in Rx and Tx mode */
+ init_val = (pbs_mode == PBS_RX_MODE) ? 0 : iterations;
+
+ ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, RESULT_PER_BIT,
+ HWS_CONTROL_ELEMENT_DQ_SKEW,
+ search_dir, dir, tm->if_act_mask,
+ init_val, iterations, pbs_pattern,
+ search_edge, CS_SINGLE, cs_num,
+ train_status);
+
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num,
+ ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE,
+ mask_results_dq_reg_map
+ [bit +
+ pup *
+ BUS_WIDTH_IN_BITS],
+ res0, MASK_ALL_BITS));
+ if (pup_state[if_id][pup] != 2) {
+ /*
+ * if pup is not SBA continue
+ * to next pup
+ */
+ bit = BUS_WIDTH_IN_BITS;
+ continue;
+ }
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("Per Bit Skew search, PF I/F %d, bit:%d, pup:%d res0 0x%x\n",
+ if_id, bit, pup, res0[if_id]));
+ if ((res0[if_id] & 0x2000000) == 0) {
+ DEBUG_PBS_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("SBA Fail\n"));
+
+ max_pbs_per_pup[if_id][pup] =
+ 0x1f;
+ result_all_bit[
+ bit + pup *
+ BUS_WIDTH_IN_BITS +
+ if_id * MAX_BUS_NUM *
+ BUS_WIDTH_IN_BITS] =
+ 0x1f;
+ } else {
+ temp = (u8)(res0[if_id] &
+ res_valid_mask);
+ max_pbs_per_pup[if_id][pup] =
+ (temp >
+ max_pbs_per_pup[if_id]
+ [pup]) ? temp :
+ max_pbs_per_pup
+ [if_id][pup];
+ min_pbs_per_pup[if_id][pup] =
+ (temp <
+ min_pbs_per_pup[if_id]
+ [pup]) ? temp :
+ min_pbs_per_pup
+ [if_id][pup];
+ result_all_bit[
+ bit + pup *
+ BUS_WIDTH_IN_BITS +
+ if_id * MAX_BUS_NUM *
+ BUS_WIDTH_IN_BITS] =
+ temp;
+ adll_shift_lock[if_id][pup] = 1;
+ }
+ }
+ }
+ }
+
+ /* Check all Pup state */
+ all_lock = 1;
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ /*
+ * DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ * ("pup_state[%d][%d] = %d\n",if_id,pup,pup_state
+ * [if_id][pup]));
+ */
+ }
+ }
+
+ /* END OF SBA */
+ /* Norm */
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
+ if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* if pup not lock continue to next pup */
+ if (adll_shift_lock[if_id][pup] != 1) {
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("PBS failed for IF #%d\n",
+ if_id));
+ training_result[training_stage][if_id]
+ = TEST_FAILED;
+
+ result_mat[if_id][pup][bit] = 0;
+ max_pbs_per_pup[if_id][pup] = 0;
+ min_pbs_per_pup[if_id][pup] = 0;
+ } else {
+ training_result[
+ training_stage][if_id] =
+ (training_result[training_stage]
+ [if_id] == TEST_FAILED) ?
+ TEST_FAILED : TEST_SUCCESS;
+ result_mat[if_id][pup][bit] =
+ result_all_bit[
+ bit + pup *
+ BUS_WIDTH_IN_BITS +
+ if_id * MAX_BUS_NUM *
+ BUS_WIDTH_IN_BITS] -
+ min_pbs_per_pup[if_id][pup];
+ }
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("The abs min_pbs[%d][%d] = %d\n",
+ if_id, pup,
+ min_pbs_per_pup[if_id][pup]));
+ }
+ }
+ }
+
+ /* Clean all results */
+ ddr3_tip_clean_pbs_result(dev_num, pbs_mode);
+
+ /* DQ PBS register update with the final result */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_INFO,
+ ("Final Results: if_id %d, pup %d, Pup State: %d\n",
+ if_id, pup, pup_state[if_id][pup]));
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ if (dq_map_table == NULL) {
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_ERROR,
+ ("dq_map_table not initialized\n"));
+ return MV_FAIL;
+ }
+ pad_num = dq_map_table[
+ bit + pup * BUS_WIDTH_IN_BITS +
+ if_id * BUS_WIDTH_IN_BITS *
+ MAX_BUS_NUM];
+ DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
+ ("result_mat: %d ",
+ result_mat[if_id][pup]
+ [bit]));
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ PBS_RX_PHY_REG(effective_cs, 0) :
+ PBS_TX_PHY_REG(effective_cs, 0);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr + pad_num,
+ result_mat[if_id][pup][bit]));
+ }
+
+ if (max_pbs_per_pup[if_id][pup] == min_pbs_per_pup[if_id][pup]) {
+ temp = TYPICAL_PBS_VALUE;
+ } else {
+ temp = ((max_adll_per_pup[if_id][pup] -
+ min_adll_per_pup[if_id][pup]) *
+ adll_tap /
+ (max_pbs_per_pup[if_id][pup] -
+ min_pbs_per_pup[if_id][pup]));
+ }
+ pbsdelay_per_pup[pbs_mode]
+ [if_id][pup][effective_cs] = temp;
+
+ /* RX results ready, write RX also */
+ if (pbs_mode == PBS_TX_MODE) {
+ /* Write TX results */
+ reg_addr = (0x14 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ (max_pbs_per_pup[if_id][pup] -
+ min_pbs_per_pup[if_id][pup]) /
+ 2));
+ reg_addr = (0x15 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ (max_pbs_per_pup[if_id][pup] -
+ min_pbs_per_pup[if_id][pup]) /
+ 2));
+
+ /* Write previously stored RX results */
+ reg_addr = (0x54 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ result_mat_rx_dqs[if_id][pup]
+ [effective_cs]));
+ reg_addr = (0x55 + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr,
+ result_mat_rx_dqs[if_id][pup]
+ [effective_cs]));
+ } else {
+ /*
+ * RX results may affect RL results correctess,
+ * so just store the results that will written
+ * in TX stage
+ */
+ result_mat_rx_dqs[if_id][pup][effective_cs] =
+ (max_pbs_per_pup[if_id][pup] -
+ min_pbs_per_pup[if_id][pup]) / 2;
+ }
+ DEBUG_PBS_ENGINE(
+ DEBUG_LEVEL_INFO,
+ (", PBS tap=%d [psec] ==> skew observed = %d\n",
+ temp,
+ ((max_pbs_per_pup[if_id][pup] -
+ min_pbs_per_pup[if_id][pup]) *
+ temp)));
+ }
+ }
+
+ /* Write back to the phy the default values */
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ CRX_PHY_REG(effective_cs) :
+ CTX_PHY_REG(effective_cs);
+ ddr3_tip_write_adll_value(dev_num, nominal_adll, reg_addr);
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ (0x5a + effective_cs * 0x10) :
+ (0x1a + effective_cs * 0x10);
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA, reg_addr,
+ 0));
+
+ /* restore cs enable value */
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_UNICAST, if_id,
+ DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id],
+ MASK_ALL_BITS));
+ }
+
+ /* exit test mode */
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ODPG_WR_RD_MODE_ENA_REG, 0xffff, MASK_ALL_BITS));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ /*
+ * no valid window found
+ * (no lock at EBA ADLL shift at EBS)
+ */
+ if (pup_state[if_id][pup] == 1)
+ return MV_FAIL;
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Name: ddr3_tip_pbs_rx.
+ * Desc: PBS TX
+ * Args: TBD
+ * Notes:
+ * Returns: OK if success, other error code if fail.
+ */
+int ddr3_tip_pbs_rx(u32 uidev_num)
+{
+ return ddr3_tip_pbs(uidev_num, PBS_RX_MODE);
+}
+
+/*
+ * Name: ddr3_tip_pbs_tx.
+ * Desc: PBS TX
+ * Args: TBD
+ * Notes:
+ * Returns: OK if success, other error code if fail.
+ */
+int ddr3_tip_pbs_tx(u32 uidev_num)
+{
+ return ddr3_tip_pbs(uidev_num, PBS_TX_MODE);
+}
+
+#ifdef DDR_VIEWER_TOOL
+/*
+ * Print PBS Result
+ */
+int ddr3_tip_print_all_pbs_result(u32 dev_num)
+{
+ u32 curr_cs;
+ unsigned int max_cs = mv_ddr_cs_num_get();
+
+ for (curr_cs = 0; curr_cs < max_cs; curr_cs++) {
+ ddr3_tip_print_pbs_result(dev_num, curr_cs, PBS_RX_MODE);
+ ddr3_tip_print_pbs_result(dev_num, curr_cs, PBS_TX_MODE);
+ }
+
+ return MV_OK;
+}
+
+/*
+ * Print PBS Result
+ */
+int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode)
+{
+ u32 data_value = 0, bit = 0, if_id = 0, pup = 0;
+ u32 reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ PBS_RX_PHY_REG(cs_num, 0) :
+ PBS_TX_PHY_REG(cs_num , 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();
+
+ printf("%s,CS%d,PBS,ADLLRATIO,,,",
+ (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx", cs_num);
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0; pup < octets_per_if_num; pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ printf("%d,",
+ pbsdelay_per_pup[pbs_mode][if_id][pup][cs_num]);
+ }
+ }
+ printf("CS%d, %s ,PBS\n", cs_num,
+ (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx");
+
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ printf("%s, DQ", (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx");
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ printf("%d ,PBS,,, ", bit);
+ for (pup = 0; pup <= octets_per_if_num;
+ pup++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
+ CHECK_STATUS(ddr3_tip_bus_read
+ (dev_num, if_id,
+ ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr + bit,
+ &data_value));
+ printf("%d , ", data_value);
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ return MV_OK;
+}
+#endif /* DDR_VIEWER_TOOL */
+
+/*
+ * Fixup PBS Result
+ */
+int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode)
+{
+ u32 if_id, pup, bit;
+ u32 reg_addr = (pbs_mode == PBS_RX_MODE) ?
+ PBS_RX_PHY_REG(effective_cs, 0) :
+ PBS_TX_PHY_REG(effective_cs, 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();
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (pup = 0; pup <= octets_per_if_num; pup++) {
+ for (bit = 0; bit <= BUS_WIDTH_IN_BITS + 3; bit++) {
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, ACCESS_TYPE_UNICAST, pup,
+ DDR_PHY_DATA, reg_addr + bit, 0));
+ }
+ }
+ }
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h
new file mode 100644
index 000000000..735731196
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR_ML_WRAPPER_H
+#define _DDR_ML_WRAPPER_H
+
+#include <common.h>
+#include <i2c.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#define INTER_REGS_BASE SOC_REGS_PHY_BASE
+
+/*
+ * MV_DEBUG_INIT need to be defines, otherwise the output of the
+ * DDR2 training code is not complete and misleading
+ */
+#define MV_DEBUG_INIT
+
+#ifdef MV_DEBUG_INIT
+#define DEBUG_INIT_S(s) puts(s)
+#define DEBUG_INIT_D(d, l) printf("%x", d)
+#define DEBUG_INIT_D_10(d, l) printf("%d", d)
+#else
+#define DEBUG_INIT_S(s)
+#define DEBUG_INIT_D(d, l)
+#define DEBUG_INIT_D_10(d, l)
+#endif
+
+#ifdef MV_DEBUG_INIT_FULL
+#define DEBUG_INIT_FULL_S(s) puts(s)
+#define DEBUG_INIT_FULL_D(d, l) printf("%x", d)
+#define DEBUG_INIT_FULL_D_10(d, l) printf("%d", d)
+#define DEBUG_WR_REG(reg, val) \
+ { DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \
+ DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); }
+#define DEBUG_RD_REG(reg, val) \
+ { DEBUG_INIT_S("Read Reg: 0x"); DEBUG_INIT_D((reg), 8); \
+ DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); }
+#else
+#define DEBUG_INIT_FULL_S(s)
+#define DEBUG_INIT_FULL_D(d, l)
+#define DEBUG_INIT_FULL_D_10(d, l)
+#define DEBUG_WR_REG(reg, val)
+#define DEBUG_RD_REG(reg, val)
+#endif
+
+#define DEBUG_INIT_FULL_C(s, d, l) \
+ { DEBUG_INIT_FULL_S(s); \
+ DEBUG_INIT_FULL_D(d, l); \
+ DEBUG_INIT_FULL_S("\n"); }
+#define DEBUG_INIT_C(s, d, l) \
+ { DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); }
+
+/*
+ * Debug (Enable/Disable modules) and Error report
+ */
+
+#ifdef BASIC_DEBUG
+#define MV_DEBUG_WL
+#define MV_DEBUG_RL
+#define MV_DEBUG_DQS_RESULTS
+#endif
+
+#ifdef FULL_DEBUG
+#define MV_DEBUG_WL
+#define MV_DEBUG_RL
+#define MV_DEBUG_DQS
+
+#define MV_DEBUG_PBS
+#define MV_DEBUG_DFS
+#define MV_DEBUG_MAIN_FULL
+#define MV_DEBUG_DFS_FULL
+#define MV_DEBUG_DQS_FULL
+#define MV_DEBUG_RL_FULL
+#define MV_DEBUG_WL_FULL
+#endif
+
+
+/* The following is a list of Marvell status */
+#define MV_ERROR (-1)
+#define MV_OK (0x00) /* Operation succeeded */
+#define MV_FAIL (0x01) /* Operation failed */
+#define MV_BAD_VALUE (0x02) /* Illegal value (general) */
+#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */
+#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */
+#define MV_BAD_PTR (0x05) /* Illegal pointer value */
+#define MV_BAD_SIZE (0x06) /* Illegal size */
+#define MV_BAD_STATE (0x07) /* Illegal state of state machine */
+#define MV_SET_ERROR (0x08) /* Set operation failed */
+#define MV_GET_ERROR (0x09) /* Get operation failed */
+#define MV_CREATE_ERROR (0x0a) /* Fail while creating an item */
+#define MV_NOT_FOUND (0x0b) /* Item not found */
+#define MV_NO_MORE (0x0c) /* No more items found */
+#define MV_NO_SUCH (0x0d) /* No such item */
+#define MV_TIMEOUT (0x0e) /* Time Out */
+#define MV_NO_CHANGE (0x0f) /* Parameter(s) is already in this value */
+#define MV_NOT_SUPPORTED (0x10) /* This request is not support */
+#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/
+#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */
+#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */
+#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */
+#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */
+#define MV_INIT_ERROR (0x16) /* Error occurred while INIT process */
+#define MV_HW_ERROR (0x17) /* Hardware error */
+#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */
+#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */
+#define MV_NOT_READY (0x1a) /* The other side is not ready yet */
+#define MV_ALREADY_EXIST (0x1b) /* Tried to create existing item */
+#define MV_OUT_OF_CPU_MEM (0x1c) /* Cpu memory allocation failed. */
+#define MV_NOT_STARTED (0x1d) /* Not started yet */
+#define MV_BUSY (0x1e) /* Item is busy. */
+#define MV_TERMINATE (0x1f) /* Item terminates it's work. */
+#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */
+#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */
+#define MV_WRITE_PROTECT (0x22) /* Write protected */
+#define MV_INVALID (int)(-1)
+
+/*
+ * Accessor functions for the registers
+ */
+static inline void reg_write(u32 addr, u32 val)
+{
+ writel(val, INTER_REGS_BASE + addr);
+}
+
+static inline u32 reg_read(u32 addr)
+{
+ return readl(INTER_REGS_BASE + addr);
+}
+
+static inline void reg_bit_set(u32 addr, u32 mask)
+{
+ setbits_le32(INTER_REGS_BASE + addr, mask);
+}
+
+static inline void reg_bit_clr(u32 addr, u32 mask)
+{
+ clrbits_le32(INTER_REGS_BASE + addr, mask);
+}
+
+#endif /* _DDR_ML_WRAPPER_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr_topology_def.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr_topology_def.h
new file mode 100644
index 000000000..7f2317edf
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr_topology_def.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR_TOPOLOGY_DEF_H
+#define _DDR_TOPOLOGY_DEF_H
+
+#include "ddr3_training_ip_def.h"
+#include "mv_ddr_topology.h"
+#include "mv_ddr_spd.h"
+#include "ddr3_logging_def.h"
+
+#define MV_DDR_MAX_BUS_NUM 9
+#define MV_DDR_MAX_IFACE_NUM 1
+
+enum mv_ddr_twin_die {
+ NOT_COMBINED,
+ COMBINED,
+};
+
+struct bus_params {
+ /* Chip Select (CS) bitmask (bits 0-CS0, bit 1- CS1 ...) */
+ u8 cs_bitmask;
+
+ /*
+ * mirror enable/disable
+ * (bits 0-CS0 mirroring, bit 1- CS1 mirroring ...)
+ */
+ int mirror_enable_bitmask;
+
+ /* DQS Swap (polarity) - true if enable */
+ int is_dqs_swap;
+
+ /* CK swap (polarity) - true if enable */
+ int is_ck_swap;
+};
+
+struct if_params {
+ /* bus configuration */
+ struct bus_params as_bus_params[MV_DDR_MAX_BUS_NUM];
+
+ /* Speed Bin Table */
+ enum mv_ddr_speed_bin speed_bin_index;
+
+ /* sdram device width */
+ enum mv_ddr_dev_width bus_width;
+
+ /* total sdram capacity per die, megabits */
+ enum mv_ddr_die_capacity memory_size;
+
+ /* The DDR frequency for each interfaces */
+ enum mv_ddr_freq memory_freq;
+
+ /*
+ * delay CAS Write Latency
+ * - 0 for using default value (jedec suggested)
+ */
+ u8 cas_wl;
+
+ /*
+ * delay CAS Latency
+ * - 0 for using default value (jedec suggested)
+ */
+ u8 cas_l;
+
+ /* operation temperature */
+ enum mv_ddr_temperature interface_temp;
+
+ /* 2T vs 1T mode (by default computed from number of CSs) */
+ enum mv_ddr_timing timing;
+};
+
+/* memory electrical configuration */
+struct mv_ddr_mem_edata {
+ enum mv_ddr_rtt_nom_park_evalue rtt_nom;
+ enum mv_ddr_rtt_nom_park_evalue rtt_park[MAX_CS_NUM];
+ enum mv_ddr_rtt_wr_evalue rtt_wr[MAX_CS_NUM];
+ enum mv_ddr_dic_evalue dic;
+};
+
+/* phy electrical configuration */
+struct mv_ddr_phy_edata {
+ enum mv_ddr_ohm_evalue drv_data_p;
+ enum mv_ddr_ohm_evalue drv_data_n;
+ enum mv_ddr_ohm_evalue drv_ctrl_p;
+ enum mv_ddr_ohm_evalue drv_ctrl_n;
+ enum mv_ddr_ohm_evalue odt_p[MAX_CS_NUM];
+ enum mv_ddr_ohm_evalue odt_n[MAX_CS_NUM];
+};
+
+/* mac electrical configuration */
+struct mv_ddr_mac_edata {
+ enum mv_ddr_odt_cfg_evalue odt_cfg_pat;
+ enum mv_ddr_odt_cfg_evalue odt_cfg_wr;
+ enum mv_ddr_odt_cfg_evalue odt_cfg_rd;
+};
+
+struct mv_ddr_edata {
+ struct mv_ddr_mem_edata mem_edata;
+ struct mv_ddr_phy_edata phy_edata;
+ struct mv_ddr_mac_edata mac_edata;
+};
+
+struct mv_ddr_topology_map {
+ /* debug level configuration */
+ enum mv_ddr_debug_level debug_level;
+
+ /* Number of interfaces (default is 12) */
+ u8 if_act_mask;
+
+ /* Controller configuration per interface */
+ struct if_params interface_params[MV_DDR_MAX_IFACE_NUM];
+
+ /* Bit mask for active buses */
+ u16 bus_act_mask;
+
+ /* source of ddr configuration data */
+ enum mv_ddr_cfg_src cfg_src;
+
+ /* ddr twin-die */
+ enum mv_ddr_twin_die twin_die_combined;
+
+ /* raw spd data */
+ union mv_ddr_spd_data spd_data;
+
+ /* timing parameters */
+ unsigned int timing_data[MV_DDR_TDATA_LAST];
+
+ /* electrical configuration */
+ struct mv_ddr_edata edata;
+
+ /* electrical parameters */
+ unsigned int electrical_data[MV_DDR_EDATA_LAST];
+
+ /* ODT configuration */
+ u32 odt_config;
+
+ /* Clock enable mask */
+ u32 clk_enable;
+
+ /* Clock delay */
+ int ck_delay;
+};
+
+enum mv_ddr_iface_mode {
+ MV_DDR_RAR_ENA,
+ MV_DDR_RAR_DIS,
+};
+
+enum mv_ddr_iface_state {
+ MV_DDR_IFACE_NRDY, /* not ready */
+ MV_DDR_IFACE_INIT, /* init'd */
+ MV_DDR_IFACE_RDY, /* ready */
+ MV_DDR_IFACE_DNE /* does not exist */
+};
+
+enum mv_ddr_validation {
+ MV_DDR_VAL_DIS,
+ MV_DDR_VAL_RX,
+ MV_DDR_VAL_TX,
+ MV_DDR_VAL_RX_TX,
+ MV_DDR_MEMORY_CHECK
+};
+
+enum mv_ddr_sscg {
+ SSCG_EN,
+ SSCG_DIS,
+};
+
+struct mv_ddr_iface {
+ /* base addr of ap ddr interface belongs to */
+ unsigned int ap_base;
+
+ /* ddr interface id */
+ unsigned int id;
+
+ /* ddr interface state */
+ enum mv_ddr_iface_state state;
+
+ /* ddr interface mode (rar enabled/disabled) */
+ enum mv_ddr_iface_mode iface_mode;
+
+ /* ddr interface base address */
+ unsigned long long iface_base_addr;
+
+ /* ddr interface size - ddr flow will update this parameter */
+ unsigned long long iface_byte_size;
+
+ /* ddr i2c spd data address */
+ unsigned int spd_data_addr;
+
+ /* ddr i2c spd page 0 select address */
+ unsigned int spd_page_sel_addr;
+
+ /* ddr interface validation mode */
+ enum mv_ddr_validation validation;
+
+ /* ddr interface validation mode */
+ enum mv_ddr_sscg sscg;
+
+ /* ddr interface topology map */
+ struct mv_ddr_topology_map tm;
+
+};
+
+struct mv_ddr_iface *mv_ddr_iface_get(void);
+
+/* DDR3 training global configuration parameters */
+struct tune_train_params {
+ u32 ck_delay;
+ u32 phy_reg3_val;
+ u32 g_zpri_data;
+ u32 g_znri_data;
+ u32 g_zpri_ctrl;
+ u32 g_znri_ctrl;
+ u32 g_zpodt_data;
+ u32 g_znodt_data;
+ u32 g_zpodt_ctrl;
+ u32 g_znodt_ctrl;
+ u32 g_dic;
+ u32 g_odt_config;
+ u32 g_rtt_nom;
+ u32 g_rtt_wr;
+ u32 g_rtt_park;
+};
+
+#endif /* _DDR_TOPOLOGY_DEF_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/ddr_training_ip_db.h b/roms/u-boot/drivers/ddr/marvell/a38x/ddr_training_ip_db.h
new file mode 100644
index 000000000..f1b4d8efc
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/ddr_training_ip_db.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _DDR_TRAINING_IP_DB_H_
+#define _DDR_TRAINING_IP_DB_H_
+
+#include "ddr3_training_ip_db.h"
+
+u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index);
+
+#endif /* _DDR3_TRAINING_IP_DB_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/dram_if.h b/roms/u-boot/drivers/ddr/marvell/a38x/dram_if.h
new file mode 100644
index 000000000..4d0846489
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/dram_if.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ */
+
+#ifndef _DRAM_IF_H_
+#define _DRAM_IF_H_
+
+/* TODO: update atf to this new prototype */
+int dram_init(void);
+void dram_mmap_config(void);
+unsigned long long dram_iface_mem_sz_get(void);
+#endif /* _DRAM_IF_H_ */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_build_message.c b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_build_message.c
new file mode 100644
index 000000000..a2bb8a96a
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_build_message.c
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+const char mv_ddr_build_message[] = "";
+const char mv_ddr_version_string[] = "mv_ddr: 14.0.0";
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.c b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.c
new file mode 100644
index 000000000..7afabbfd8
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "mv_ddr_common.h"
+#include "ddr_ml_wrapper.h"
+
+void mv_ddr_ver_print(void)
+{
+ printf("%s %s\n", mv_ddr_version_string, mv_ddr_build_message);
+}
+
+/* ceiling division for positive integers */
+unsigned int ceil_div(unsigned int x, unsigned int y)
+{
+ return (x % y) ? (x / y + 1) : (x / y);
+}
+
+/*
+ * time to number of clocks calculation based on the rounding algorithm
+ * using 97.4% inverse factor per JEDEC Standard No. 21-C, 4.1.2.L-4:
+ * Serial Presence Detect (SPD) for DDR4 SDRAM Modules
+ */
+unsigned int time_to_nclk(unsigned int t, unsigned int tclk)
+{
+ /* t & tclk parameters are in ps */
+ return ((unsigned long)t * 1000 / tclk + 974) / 1000;
+}
+
+/* round division of two positive integers to the nearest whole number */
+int round_div(unsigned int dividend, unsigned int divisor, unsigned int *quotient)
+{
+ if (quotient == NULL) {
+ printf("%s: error: NULL quotient pointer found\n", __func__);
+ return MV_FAIL;
+ }
+
+ if (divisor == 0) {
+ printf("%s: error: division by zero\n", __func__);
+ return MV_FAIL;
+ } else {
+ *quotient = (dividend + divisor / 2) / divisor;
+ }
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.h
new file mode 100644
index 000000000..321a390c0
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_common.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR_COMMON_H
+#define _MV_DDR_COMMON_H
+
+extern const char mv_ddr_build_message[];
+extern const char mv_ddr_version_string[];
+
+#define _1K 0x00000400
+#define _4K 0x00001000
+#define _8K 0x00002000
+#define _16K 0x00004000
+#define _32K 0x00008000
+#define _64K 0x00010000
+#define _128K 0x00020000
+#define _256K 0x00040000
+#define _512K 0x00080000
+
+#define _1M 0x00100000
+#define _2M 0x00200000
+#define _4M 0x00400000
+#define _8M 0x00800000
+#define _16M 0x01000000
+#define _32M 0x02000000
+#define _64M 0x04000000
+#define _128M 0x08000000
+#define _256M 0x10000000
+#define _512M 0x20000000
+
+#define _1G 0x40000000
+#define _2G 0x80000000
+#define _4G 0x100000000
+#define _8G 0x200000000
+#define _16G 0x400000000
+#define _32G 0x800000000
+#define _64G 0x1000000000
+#define _128G 0x2000000000
+
+#define MEGA 1000000
+#define MV_DDR_MEGABYTE (1024 * 1024)
+#define MV_DDR_32_BITS_MASK 0xffffffff
+
+#define GET_MAX_VALUE(x, y) \
+ (((x) > (y)) ? (x) : (y))
+
+void mv_ddr_ver_print(void);
+unsigned int ceil_div(unsigned int x, unsigned int y);
+unsigned int time_to_nclk(unsigned int t, unsigned int tclk);
+int round_div(unsigned int dividend, unsigned int divisor, unsigned int *quotient);
+
+#endif /* _MV_DDR_COMMON_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.c
new file mode 100644
index 000000000..faafc86ea
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.c
@@ -0,0 +1,1446 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_common.h"
+#include "mv_ddr_training_db.h"
+#include "mv_ddr_regs.h"
+#include "mv_ddr_sys_env_lib.h"
+
+#define DDR_INTERFACES_NUM 1
+#define DDR_INTERFACE_OCTETS_NUM 5
+
+/*
+ * 1. L2 filter should be set at binary header to 0xD000000,
+ * to avoid conflict with internal register IO.
+ * 2. U-Boot modifies internal registers base to 0xf100000,
+ * and than should update L2 filter accordingly to 0xf000000 (3.75 GB)
+ */
+#define L2_FILTER_FOR_MAX_MEMORY_SIZE 0xC0000000 /* temporary limit l2 filter to 3gb (LSP issue) */
+#define ADDRESS_FILTERING_END_REGISTER 0x8c04
+
+#define DYNAMIC_CS_SIZE_CONFIG
+#define DISABLE_L2_FILTERING_DURING_DDR_TRAINING
+
+/* Termal Sensor Registers */
+#define TSEN_CONTROL_LSB_REG 0xE4070
+#define TSEN_CONTROL_LSB_TC_TRIM_OFFSET 0
+#define TSEN_CONTROL_LSB_TC_TRIM_MASK (0x7 << TSEN_CONTROL_LSB_TC_TRIM_OFFSET)
+#define TSEN_CONTROL_MSB_REG 0xE4074
+#define TSEN_CONTROL_MSB_RST_OFFSET 8
+#define TSEN_CONTROL_MSB_RST_MASK (0x1 << TSEN_CONTROL_MSB_RST_OFFSET)
+#define TSEN_STATUS_REG 0xe4078
+#define TSEN_STATUS_READOUT_VALID_OFFSET 10
+#define TSEN_STATUS_READOUT_VALID_MASK (0x1 << \
+ TSEN_STATUS_READOUT_VALID_OFFSET)
+#define TSEN_STATUS_TEMP_OUT_OFFSET 0
+#define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET)
+
+static struct dlb_config ddr3_dlb_config_table[] = {
+ {DLB_CTRL_REG, 0x2000005c},
+ {DLB_BUS_OPT_WT_REG, 0x00880000},
+ {DLB_AGING_REG, 0x0f7f007f},
+ {DLB_EVICTION_CTRL_REG, 0x0000129f},
+ {DLB_EVICTION_TIMERS_REG, 0x00ff0000},
+ {DLB_WTS_DIFF_CS_REG, 0x04030802},
+ {DLB_WTS_DIFF_BG_REG, 0x00000a02},
+ {DLB_WTS_SAME_BG_REG, 0x09000a01},
+ {DLB_WTS_CMDS_REG, 0x00020005},
+ {DLB_WTS_ATTR_PRIO_REG, 0x00060f10},
+ {DLB_QUEUE_MAP_REG, 0x00000543},
+ {DLB_SPLIT_REG, 0x00000000},
+ {DLB_USER_CMD_REG, 0x00000000},
+ {0x0, 0x0}
+};
+
+static struct dlb_config *sys_env_dlb_config_ptr_get(void)
+{
+ return &ddr3_dlb_config_table[0];
+}
+
+static u8 a38x_bw_per_freq[MV_DDR_FREQ_LAST] = {
+ 0x3, /* MV_DDR_FREQ_100 */
+ 0x4, /* MV_DDR_FREQ_400 */
+ 0x4, /* MV_DDR_FREQ_533 */
+ 0x5, /* MV_DDR_FREQ_667 */
+ 0x5, /* MV_DDR_FREQ_800 */
+ 0x5, /* MV_DDR_FREQ_933 */
+ 0x5, /* MV_DDR_FREQ_1066 */
+ 0x3, /* MV_DDR_FREQ_311 */
+ 0x3, /* MV_DDR_FREQ_333 */
+ 0x4, /* MV_DDR_FREQ_467 */
+ 0x5, /* MV_DDR_FREQ_850 */
+ 0x5, /* MV_DDR_FREQ_600 */
+ 0x3, /* MV_DDR_FREQ_300 */
+ 0x5, /* MV_DDR_FREQ_900 */
+ 0x3, /* MV_DDR_FREQ_360 */
+ 0x5 /* MV_DDR_FREQ_1000 */
+};
+
+static u8 a38x_rate_per_freq[MV_DDR_FREQ_LAST] = {
+ 0x1, /* MV_DDR_FREQ_100 */
+ 0x2, /* MV_DDR_FREQ_400 */
+ 0x2, /* MV_DDR_FREQ_533 */
+ 0x2, /* MV_DDR_FREQ_667 */
+ 0x2, /* MV_DDR_FREQ_800 */
+ 0x3, /* MV_DDR_FREQ_933 */
+ 0x3, /* MV_DDR_FREQ_1066 */
+ 0x1, /* MV_DDR_FREQ_311 */
+ 0x1, /* MV_DDR_FREQ_333 */
+ 0x2, /* MV_DDR_FREQ_467 */
+ 0x2, /* MV_DDR_FREQ_850 */
+ 0x2, /* MV_DDR_FREQ_600 */
+ 0x1, /* MV_DDR_FREQ_300 */
+ 0x2, /* MV_DDR_FREQ_900 */
+ 0x1, /* MV_DDR_FREQ_360 */
+ 0x2 /* MV_DDR_FREQ_1000 */
+};
+
+static u16 a38x_vco_freq_per_sar_ref_clk_25_mhz[] = {
+ 666, /* 0 */
+ 1332,
+ 800,
+ 1600,
+ 1066,
+ 2132,
+ 1200,
+ 2400,
+ 1332,
+ 1332,
+ 1500,
+ 1500,
+ 1600, /* 12 */
+ 1600,
+ 1700,
+ 1700,
+ 1866,
+ 1866,
+ 1800, /* 18 */
+ 2000,
+ 2000,
+ 4000,
+ 2132,
+ 2132,
+ 2300,
+ 2300,
+ 2400,
+ 2400,
+ 2500,
+ 2500,
+ 800
+};
+
+static u16 a38x_vco_freq_per_sar_ref_clk_40_mhz[] = {
+ 666, /* 0 */
+ 1332,
+ 800,
+ 800, /* 0x3 */
+ 1066,
+ 1066, /* 0x5 */
+ 1200,
+ 2400,
+ 1332,
+ 1332,
+ 1500, /* 10 */
+ 1600, /* 0xB */
+ 1600,
+ 1600,
+ 1700,
+ 1560, /* 0xF */
+ 1866,
+ 1866,
+ 1800,
+ 2000,
+ 2000, /* 20 */
+ 4000,
+ 2132,
+ 2132,
+ 2300,
+ 2300,
+ 2400,
+ 2400,
+ 2500,
+ 2500,
+ 1800 /* 30 - 0x1E */
+};
+
+
+static u32 async_mode_at_tf;
+
+static u32 dq_bit_map_2_phy_pin[] = {
+ 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */
+ 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */
+ 3, 9, 7, 8, 1, 0, 2, 6, /* 2 */
+ 1, 0, 6, 2, 8, 3, 7, 9, /* 3 */
+ 0, 1, 2, 9, 7, 8, 3, 6, /* 4 */
+};
+
+void mv_ddr_mem_scrubbing(void)
+{
+ ddr3_new_tip_ecc_scrub();
+}
+
+static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id,
+ enum mv_ddr_freq freq);
+
+/*
+ * Read temperature TJ value
+ */
+static u32 ddr3_ctrl_get_junc_temp(u8 dev_num)
+{
+ int reg = 0;
+
+ /* Initiates TSEN hardware reset once */
+ if ((reg_read(TSEN_CONTROL_MSB_REG) & TSEN_CONTROL_MSB_RST_MASK) == 0) {
+ reg_bit_set(TSEN_CONTROL_MSB_REG, TSEN_CONTROL_MSB_RST_MASK);
+ /* set Tsen Tc Trim to correct default value (errata #132698) */
+ reg = reg_read(TSEN_CONTROL_LSB_REG);
+ reg &= ~TSEN_CONTROL_LSB_TC_TRIM_MASK;
+ reg |= 0x3 << TSEN_CONTROL_LSB_TC_TRIM_OFFSET;
+ reg_write(TSEN_CONTROL_LSB_REG, reg);
+ }
+ mdelay(10);
+
+ /* Check if the readout field is valid */
+ if ((reg_read(TSEN_STATUS_REG) & TSEN_STATUS_READOUT_VALID_MASK) == 0) {
+ printf("%s: TSEN not ready\n", __func__);
+ return 0;
+ }
+
+ reg = reg_read(TSEN_STATUS_REG);
+ reg = (reg & TSEN_STATUS_TEMP_OUT_MASK) >> TSEN_STATUS_TEMP_OUT_OFFSET;
+
+ return ((((10000 * reg) / 21445) * 1000) - 272674) / 1000;
+}
+
+/*
+ * Name: ddr3_tip_a38x_get_freq_config.
+ * Desc:
+ * Args:
+ * Notes:
+ * Returns: MV_OK if success, other error code if fail.
+ */
+static int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum mv_ddr_freq freq,
+ struct hws_tip_freq_config_info
+ *freq_config_info)
+{
+ if (a38x_bw_per_freq[freq] == 0xff)
+ return MV_NOT_SUPPORTED;
+
+ if (freq_config_info == NULL)
+ return MV_BAD_PARAM;
+
+ freq_config_info->bw_per_freq = a38x_bw_per_freq[freq];
+ freq_config_info->rate_per_freq = a38x_rate_per_freq[freq];
+ freq_config_info->is_supported = 1;
+
+ return MV_OK;
+}
+
+static void dunit_read(u32 addr, u32 mask, u32 *data)
+{
+ *data = reg_read(addr) & mask;
+}
+
+static void dunit_write(u32 addr, u32 mask, u32 data)
+{
+ u32 reg_val = data;
+
+ if (mask != MASK_ALL_BITS) {
+ dunit_read(addr, MASK_ALL_BITS, &reg_val);
+ reg_val &= (~mask);
+ reg_val |= (data & mask);
+ }
+
+ reg_write(addr, reg_val);
+}
+
+#define ODPG_ENABLE_REG 0x186d4
+#define ODPG_EN_OFFS 0
+#define ODPG_EN_MASK 0x1
+#define ODPG_EN_ENA 1
+#define ODPG_EN_DONE 0
+#define ODPG_DIS_OFFS 8
+#define ODPG_DIS_MASK 0x1
+#define ODPG_DIS_DIS 1
+void mv_ddr_odpg_enable(void)
+{
+ dunit_write(ODPG_ENABLE_REG,
+ ODPG_EN_MASK << ODPG_EN_OFFS,
+ ODPG_EN_ENA << ODPG_EN_OFFS);
+}
+
+void mv_ddr_odpg_disable(void)
+{
+ dunit_write(ODPG_ENABLE_REG,
+ ODPG_DIS_MASK << ODPG_DIS_OFFS,
+ ODPG_DIS_DIS << ODPG_DIS_OFFS);
+}
+
+void mv_ddr_odpg_done_clr(void)
+{
+ return;
+}
+
+int mv_ddr_is_odpg_done(u32 count)
+{
+ u32 i, data;
+
+ for (i = 0; i < count; i++) {
+ dunit_read(ODPG_ENABLE_REG, MASK_ALL_BITS, &data);
+ if (((data >> ODPG_EN_OFFS) & ODPG_EN_MASK) ==
+ ODPG_EN_DONE)
+ break;
+ }
+
+ if (i >= count) {
+ printf("%s: timeout\n", __func__);
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+void mv_ddr_training_enable(void)
+{
+ dunit_write(GLOB_CTRL_STATUS_REG,
+ TRAINING_TRIGGER_MASK << TRAINING_TRIGGER_OFFS,
+ TRAINING_TRIGGER_ENA << TRAINING_TRIGGER_OFFS);
+}
+
+#define DRAM_INIT_CTRL_STATUS_REG 0x18488
+#define TRAINING_TRIGGER_OFFS 0
+#define TRAINING_TRIGGER_MASK 0x1
+#define TRAINING_TRIGGER_ENA 1
+#define TRAINING_DONE_OFFS 1
+#define TRAINING_DONE_MASK 0x1
+#define TRAINING_DONE_DONE 1
+#define TRAINING_DONE_NOT_DONE 0
+#define TRAINING_RESULT_OFFS 2
+#define TRAINING_RESULT_MASK 0x1
+#define TRAINING_RESULT_PASS 0
+#define TRAINING_RESULT_FAIL 1
+int mv_ddr_is_training_done(u32 count, u32 *result)
+{
+ u32 i, data;
+
+ if (result == NULL) {
+ printf("%s: NULL result pointer found\n", __func__);
+ return MV_FAIL;
+ }
+
+ for (i = 0; i < count; i++) {
+ dunit_read(DRAM_INIT_CTRL_STATUS_REG, MASK_ALL_BITS, &data);
+ if (((data >> TRAINING_DONE_OFFS) & TRAINING_DONE_MASK) ==
+ TRAINING_DONE_DONE)
+ break;
+ }
+
+ if (i >= count) {
+ printf("%s: timeout\n", __func__);
+ return MV_FAIL;
+ }
+
+ *result = (data >> TRAINING_RESULT_OFFS) & TRAINING_RESULT_MASK;
+
+ return MV_OK;
+}
+
+#define DM_PAD 10
+u32 mv_ddr_dm_pad_get(void)
+{
+ return DM_PAD;
+}
+
+/*
+ * Name: ddr3_tip_a38x_select_ddr_controller.
+ * Desc: Enable/Disable access to Marvell's server.
+ * Args: dev_num - device number
+ * enable - whether to enable or disable the server
+ * Notes:
+ * Returns: MV_OK if success, other error code if fail.
+ */
+static int ddr3_tip_a38x_select_ddr_controller(u8 dev_num, int enable)
+{
+ u32 reg;
+
+ reg = reg_read(DUAL_DUNIT_CFG_REG);
+
+ if (enable)
+ reg |= (1 << 6);
+ else
+ reg &= ~(1 << 6);
+
+ reg_write(DUAL_DUNIT_CFG_REG, reg);
+
+ return MV_OK;
+}
+
+static u8 ddr3_tip_clock_mode(u32 frequency)
+{
+ if ((frequency == MV_DDR_FREQ_LOW_FREQ) || (mv_ddr_freq_get(frequency) <= 400))
+ return 1;
+
+ return 2;
+}
+
+static int mv_ddr_sar_freq_get(int dev_num, enum mv_ddr_freq *freq)
+{
+ u32 reg, ref_clk_satr;
+
+ /* Read sample at reset setting */
+ reg = (reg_read(REG_DEVICE_SAR1_ADDR) >>
+ RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) &
+ RST2_CPU_DDR_CLOCK_SELECT_IN_MASK;
+
+ ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG);
+ if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) ==
+ DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) {
+ switch (reg) {
+ case 0x1:
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("Warning: Unsupported freq mode for 333Mhz configured(%d)\n",
+ reg));
+ /* fallthrough */
+ case 0x0:
+ *freq = MV_DDR_FREQ_333;
+ break;
+ case 0x3:
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("Warning: Unsupported freq mode for 400Mhz configured(%d)\n",
+ reg));
+ /* fallthrough */
+ case 0x2:
+ *freq = MV_DDR_FREQ_400;
+ break;
+ case 0xd:
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("Warning: Unsupported freq mode for 533Mhz configured(%d)\n",
+ reg));
+ /* fallthrough */
+ case 0x4:
+ *freq = MV_DDR_FREQ_533;
+ break;
+ case 0x6:
+ *freq = MV_DDR_FREQ_600;
+ break;
+ case 0x11:
+ case 0x14:
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("Warning: Unsupported freq mode for 667Mhz configured(%d)\n",
+ reg));
+ /* fallthrough */
+ case 0x8:
+ *freq = MV_DDR_FREQ_667;
+ break;
+ case 0x15:
+ case 0x1b:
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("Warning: Unsupported freq mode for 800Mhz configured(%d)\n",
+ reg));
+ /* fallthrough */
+ case 0xc:
+ *freq = MV_DDR_FREQ_800;
+ break;
+ case 0x10:
+ *freq = MV_DDR_FREQ_933;
+ break;
+ case 0x12:
+ *freq = MV_DDR_FREQ_900;
+ break;
+ case 0x13:
+ *freq = MV_DDR_FREQ_933;
+ break;
+ default:
+ *freq = 0;
+ return MV_NOT_SUPPORTED;
+ }
+ } else { /* REFCLK 40MHz case */
+ switch (reg) {
+ case 0x3:
+ *freq = MV_DDR_FREQ_400;
+ break;
+ case 0x5:
+ *freq = MV_DDR_FREQ_533;
+ break;
+ case 0xb:
+ *freq = MV_DDR_FREQ_800;
+ break;
+ case 0x1e:
+ *freq = MV_DDR_FREQ_900;
+ break;
+ default:
+ *freq = 0;
+ return MV_NOT_SUPPORTED;
+ }
+ }
+
+ return MV_OK;
+}
+
+static int ddr3_tip_a38x_get_medium_freq(int dev_num, enum mv_ddr_freq *freq)
+{
+ u32 reg, ref_clk_satr;
+
+ /* Read sample at reset setting */
+ reg = (reg_read(REG_DEVICE_SAR1_ADDR) >>
+ RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) &
+ RST2_CPU_DDR_CLOCK_SELECT_IN_MASK;
+
+ ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG);
+ if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) ==
+ DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) {
+ switch (reg) {
+ case 0x0:
+ case 0x1:
+ /* Medium is same as TF to run PBS in this freq */
+ *freq = MV_DDR_FREQ_333;
+ break;
+ case 0x2:
+ case 0x3:
+ /* Medium is same as TF to run PBS in this freq */
+ *freq = MV_DDR_FREQ_400;
+ break;
+ case 0x4:
+ case 0xd:
+ /* Medium is same as TF to run PBS in this freq */
+ *freq = MV_DDR_FREQ_533;
+ break;
+ case 0x8:
+ case 0x10:
+ case 0x11:
+ case 0x14:
+ *freq = MV_DDR_FREQ_333;
+ break;
+ case 0xc:
+ case 0x15:
+ case 0x1b:
+ *freq = MV_DDR_FREQ_400;
+ break;
+ case 0x6:
+ *freq = MV_DDR_FREQ_300;
+ break;
+ case 0x12:
+ *freq = MV_DDR_FREQ_360;
+ break;
+ case 0x13:
+ *freq = MV_DDR_FREQ_400;
+ break;
+ default:
+ *freq = 0;
+ return MV_NOT_SUPPORTED;
+ }
+ } else { /* REFCLK 40MHz case */
+ switch (reg) {
+ case 0x3:
+ /* Medium is same as TF to run PBS in this freq */
+ *freq = MV_DDR_FREQ_400;
+ break;
+ case 0x5:
+ /* Medium is same as TF to run PBS in this freq */
+ *freq = MV_DDR_FREQ_533;
+ break;
+ case 0xb:
+ *freq = MV_DDR_FREQ_400;
+ break;
+ case 0x1e:
+ *freq = MV_DDR_FREQ_360;
+ break;
+ default:
+ *freq = 0;
+ return MV_NOT_SUPPORTED;
+ }
+ }
+
+ return MV_OK;
+}
+
+static int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr)
+{
+ info_ptr->device_id = 0x6800;
+ info_ptr->ck_delay = ck_delay;
+
+ return MV_OK;
+}
+
+/* check indirect access to phy register file completed */
+static int is_prfa_done(void)
+{
+ u32 reg_val;
+ u32 iter = 0;
+
+ do {
+ if (iter++ > MAX_POLLING_ITERATIONS) {
+ printf("error: %s: polling timeout\n", __func__);
+ return MV_FAIL;
+ }
+ dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, &reg_val);
+ reg_val >>= PRFA_REQ_OFFS;
+ reg_val &= PRFA_REQ_MASK;
+ } while (reg_val == PRFA_REQ_ENA); /* request pending */
+
+ return MV_OK;
+}
+
+/* write to phy register thru indirect access */
+static int prfa_write(enum hws_access_type phy_access, u32 phy,
+ enum hws_ddr_phy phy_type, u32 addr,
+ u32 data, enum hws_operation op_type)
+{
+ u32 reg_val = ((data & PRFA_DATA_MASK) << PRFA_DATA_OFFS) |
+ ((addr & PRFA_REG_NUM_MASK) << PRFA_REG_NUM_OFFS) |
+ ((phy & PRFA_PUP_NUM_MASK) << PRFA_PUP_NUM_OFFS) |
+ ((phy_type & PRFA_PUP_CTRL_DATA_MASK) << PRFA_PUP_CTRL_DATA_OFFS) |
+ ((phy_access & PRFA_PUP_BCAST_WR_ENA_MASK) << PRFA_PUP_BCAST_WR_ENA_OFFS) |
+ (((addr >> 6) & PRFA_REG_NUM_HI_MASK) << PRFA_REG_NUM_HI_OFFS) |
+ ((op_type & PRFA_TYPE_MASK) << PRFA_TYPE_OFFS);
+ dunit_write(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, reg_val);
+ reg_val |= (PRFA_REQ_ENA << PRFA_REQ_OFFS);
+ dunit_write(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, reg_val);
+
+ /* polling for prfa request completion */
+ if (is_prfa_done() != MV_OK)
+ return MV_FAIL;
+
+ return MV_OK;
+}
+
+/* read from phy register thru indirect access */
+static int prfa_read(enum hws_access_type phy_access, u32 phy,
+ enum hws_ddr_phy phy_type, u32 addr, u32 *data)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 max_phy = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ u32 i, reg_val;
+
+ if (phy_access == ACCESS_TYPE_MULTICAST) {
+ for (i = 0; i < max_phy; i++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, i);
+ if (prfa_write(ACCESS_TYPE_UNICAST, i, phy_type, addr, 0, OPERATION_READ) != MV_OK)
+ return MV_FAIL;
+ dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, &reg_val);
+ data[i] = (reg_val >> PRFA_DATA_OFFS) & PRFA_DATA_MASK;
+ }
+ } else {
+ if (prfa_write(phy_access, phy, phy_type, addr, 0, OPERATION_READ) != MV_OK)
+ return MV_FAIL;
+ dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, &reg_val);
+ *data = (reg_val >> PRFA_DATA_OFFS) & PRFA_DATA_MASK;
+ }
+
+ return MV_OK;
+}
+
+static int mv_ddr_sw_db_init(u32 dev_num, u32 board_id)
+{
+ struct hws_tip_config_func_db config_func;
+
+ /* new read leveling version */
+ config_func.mv_ddr_dunit_read = dunit_read;
+ config_func.mv_ddr_dunit_write = dunit_write;
+ config_func.tip_dunit_mux_select_func =
+ ddr3_tip_a38x_select_ddr_controller;
+ config_func.tip_get_freq_config_info_func =
+ ddr3_tip_a38x_get_freq_config;
+ config_func.tip_set_freq_divider_func = ddr3_tip_a38x_set_divider;
+ config_func.tip_get_device_info_func = ddr3_tip_a38x_get_device_info;
+ config_func.tip_get_temperature = ddr3_ctrl_get_junc_temp;
+ config_func.tip_get_clock_ratio = ddr3_tip_clock_mode;
+ config_func.tip_external_read = ddr3_tip_ext_read;
+ config_func.tip_external_write = ddr3_tip_ext_write;
+ config_func.mv_ddr_phy_read = prfa_read;
+ config_func.mv_ddr_phy_write = prfa_write;
+
+ ddr3_tip_init_config_func(dev_num, &config_func);
+
+ ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin);
+
+ /* set device attributes*/
+ ddr3_tip_dev_attr_init(dev_num);
+ ddr3_tip_dev_attr_set(dev_num, MV_ATTR_TIP_REV, MV_TIP_REV_4);
+ ddr3_tip_dev_attr_set(dev_num, MV_ATTR_PHY_EDGE, MV_DDR_PHY_EDGE_POSITIVE);
+ ddr3_tip_dev_attr_set(dev_num, MV_ATTR_OCTET_PER_INTERFACE, DDR_INTERFACE_OCTETS_NUM);
+ ddr3_tip_dev_attr_set(dev_num, MV_ATTR_INTERLEAVE_WA, 0);
+
+ ca_delay = 0;
+ delay_enable = 1;
+ dfs_low_freq = DFS_LOW_FREQ_VALUE;
+ calibration_update_control = 1;
+
+ ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq);
+
+ return MV_OK;
+}
+
+static int mv_ddr_training_mask_set(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum mv_ddr_freq ddr_freq = tm->interface_params[0].memory_freq;
+
+ mask_tune_func = (SET_LOW_FREQ_MASK_BIT |
+ LOAD_PATTERN_MASK_BIT |
+ SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT |
+ WRITE_LEVELING_SUPP_MASK_BIT |
+ READ_LEVELING_MASK_BIT |
+ PBS_RX_MASK_BIT |
+ PBS_TX_MASK_BIT |
+ SET_TARGET_FREQ_MASK_BIT |
+ WRITE_LEVELING_TF_MASK_BIT |
+ WRITE_LEVELING_SUPP_TF_MASK_BIT |
+ READ_LEVELING_TF_MASK_BIT |
+ CENTRALIZATION_RX_MASK_BIT |
+ CENTRALIZATION_TX_MASK_BIT);
+ rl_mid_freq_wa = 1;
+
+ if ((ddr_freq == MV_DDR_FREQ_333) || (ddr_freq == MV_DDR_FREQ_400)) {
+ mask_tune_func = (WRITE_LEVELING_MASK_BIT |
+ LOAD_PATTERN_2_MASK_BIT |
+ WRITE_LEVELING_SUPP_MASK_BIT |
+ READ_LEVELING_MASK_BIT |
+ PBS_RX_MASK_BIT |
+ PBS_TX_MASK_BIT |
+ CENTRALIZATION_RX_MASK_BIT |
+ CENTRALIZATION_TX_MASK_BIT);
+ rl_mid_freq_wa = 0; /* WA not needed if 333/400 is TF */
+ }
+
+ /* Supplementary not supported for ECC modes */
+ if (mv_ddr_is_ecc_ena()) {
+ mask_tune_func &= ~WRITE_LEVELING_SUPP_TF_MASK_BIT;
+ mask_tune_func &= ~WRITE_LEVELING_SUPP_MASK_BIT;
+ mask_tune_func &= ~PBS_TX_MASK_BIT;
+ mask_tune_func &= ~PBS_RX_MASK_BIT;
+ }
+
+ return MV_OK;
+}
+
+/* function: mv_ddr_set_calib_controller
+ * this function sets the controller which will control
+ * the calibration cycle in the end of the training.
+ * 1 - internal controller
+ * 2 - external controller
+ */
+void mv_ddr_set_calib_controller(void)
+{
+ calibration_update_control = CAL_UPDATE_CTRL_INT;
+}
+
+static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id,
+ enum mv_ddr_freq frequency)
+{
+ u32 divider = 0;
+ u32 sar_val, ref_clk_satr;
+ u32 async_val;
+ u32 freq = mv_ddr_freq_get(frequency);
+
+ if (if_id != 0) {
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("A38x does not support interface 0x%x\n",
+ if_id));
+ return MV_BAD_PARAM;
+ }
+
+ /* get VCO freq index */
+ sar_val = (reg_read(REG_DEVICE_SAR1_ADDR) >>
+ RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) &
+ RST2_CPU_DDR_CLOCK_SELECT_IN_MASK;
+
+ ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG);
+ if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) ==
+ DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ)
+ divider = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val] / freq;
+ else
+ divider = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val] / freq;
+
+ if ((async_mode_at_tf == 1) && (freq > 400)) {
+ /* Set async mode */
+ dunit_write(0x20220, 0x1000, 0x1000);
+ dunit_write(0xe42f4, 0x200, 0x200);
+
+ /* Wait for async mode setup */
+ mdelay(5);
+
+ /* Set KNL values */
+ switch (frequency) {
+ case MV_DDR_FREQ_467:
+ async_val = 0x806f012;
+ break;
+ case MV_DDR_FREQ_533:
+ async_val = 0x807f012;
+ break;
+ case MV_DDR_FREQ_600:
+ async_val = 0x805f00a;
+ break;
+ case MV_DDR_FREQ_667:
+ async_val = 0x809f012;
+ break;
+ case MV_DDR_FREQ_800:
+ async_val = 0x807f00a;
+ break;
+ case MV_DDR_FREQ_850:
+ async_val = 0x80cb012;
+ break;
+ case MV_DDR_FREQ_900:
+ async_val = 0x80d7012;
+ break;
+ case MV_DDR_FREQ_933:
+ async_val = 0x80df012;
+ break;
+ case MV_DDR_FREQ_1000:
+ async_val = 0x80ef012;
+ break;
+ case MV_DDR_FREQ_1066:
+ async_val = 0x80ff012;
+ break;
+ default:
+ /* set MV_DDR_FREQ_667 as default */
+ async_val = 0x809f012;
+ }
+ dunit_write(0xe42f0, 0xffffffff, async_val);
+ } else {
+ /* Set sync mode */
+ dunit_write(0x20220, 0x1000, 0x0);
+ dunit_write(0xe42f4, 0x200, 0x0);
+
+ /* cpupll_clkdiv_reset_mask */
+ dunit_write(0xe4264, 0xff, 0x1f);
+
+ /* cpupll_clkdiv_reload_smooth */
+ dunit_write(0xe4260, (0xff << 8), (0x2 << 8));
+
+ /* cpupll_clkdiv_relax_en */
+ dunit_write(0xe4260, (0xff << 24), (0x2 << 24));
+
+ /* write the divider */
+ dunit_write(0xe4268, (0x3f << 8), (divider << 8));
+
+ /* set cpupll_clkdiv_reload_ratio */
+ dunit_write(0xe4264, (1 << 8), (1 << 8));
+
+ /* undet cpupll_clkdiv_reload_ratio */
+ dunit_write(0xe4264, (1 << 8), 0x0);
+
+ /* clear cpupll_clkdiv_reload_force */
+ dunit_write(0xe4260, (0xff << 8), 0x0);
+
+ /* clear cpupll_clkdiv_relax_en */
+ dunit_write(0xe4260, (0xff << 24), 0x0);
+
+ /* clear cpupll_clkdiv_reset_mask */
+ dunit_write(0xe4264, 0xff, 0x0);
+ }
+
+ /* Dunit training clock + 1:1/2:1 mode */
+ dunit_write(0x18488, (1 << 16), ((ddr3_tip_clock_mode(frequency) & 0x1) << 16));
+ dunit_write(0x1524, (1 << 15), ((ddr3_tip_clock_mode(frequency) - 1) << 15));
+
+ return MV_OK;
+}
+
+/*
+ * external read from memory
+ */
+int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr,
+ u32 num_of_bursts, u32 *data)
+{
+ u32 burst_num;
+
+ for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++)
+ data[burst_num] = readl(reg_addr + 4 * burst_num);
+
+ return MV_OK;
+}
+
+/*
+ * external write to memory
+ */
+int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr,
+ u32 num_of_bursts, u32 *data) {
+ u32 burst_num;
+
+ for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++)
+ writel(data[burst_num], reg_addr + 4 * burst_num);
+
+ return MV_OK;
+}
+
+int mv_ddr_early_init(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /* FIXME: change this configuration per ddr type
+ * configure a380 and a390 to work with receiver odt timing
+ * the odt_config is defined:
+ * '1' in ddr4
+ * '0' in ddr3
+ * here the parameter is run over in ddr4 and ddr3 to '1' (in ddr4 the default is '1')
+ * to configure the odt to work with timing restrictions
+ */
+
+ mv_ddr_sw_db_init(0, 0);
+
+ if (tm->interface_params[0].memory_freq != MV_DDR_FREQ_SAR)
+ async_mode_at_tf = 1;
+
+ return MV_OK;
+}
+
+int mv_ddr_early_init2(void)
+{
+ mv_ddr_training_mask_set();
+
+ return MV_OK;
+}
+
+int mv_ddr_pre_training_fixup(void)
+{
+ return 0;
+}
+
+int mv_ddr_post_training_fixup(void)
+{
+ return 0;
+}
+
+int ddr3_post_run_alg(void)
+{
+ return MV_OK;
+}
+
+int ddr3_silicon_post_init(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ /* Set half bus width */
+ if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask)) {
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, 0x0, 0x8000));
+ }
+
+ return MV_OK;
+}
+
+u32 mv_ddr_init_freq_get(void)
+{
+ enum mv_ddr_freq freq;
+
+ mv_ddr_sar_freq_get(0, &freq);
+
+ return freq;
+}
+
+static u32 ddr3_get_bus_width(void)
+{
+ u32 bus_width;
+
+ bus_width = (reg_read(SDRAM_CFG_REG) & 0x8000) >>
+ BUS_IN_USE_OFFS;
+
+ return (bus_width == 0) ? 16 : 32;
+}
+
+static u32 ddr3_get_device_width(u32 cs)
+{
+ u32 device_width;
+
+ device_width = (reg_read(SDRAM_ADDR_CTRL_REG) &
+ (CS_STRUCT_MASK << CS_STRUCT_OFFS(cs))) >>
+ CS_STRUCT_OFFS(cs);
+
+ return (device_width == 0) ? 8 : 16;
+}
+
+static u32 ddr3_get_device_size(u32 cs)
+{
+ u32 device_size_low, device_size_high, device_size;
+ u32 data, cs_low_offset, cs_high_offset;
+
+ cs_low_offset = CS_SIZE_OFFS(cs);
+ cs_high_offset = CS_SIZE_HIGH_OFFS(cs);
+
+ data = reg_read(SDRAM_ADDR_CTRL_REG);
+ device_size_low = (data >> cs_low_offset) & 0x3;
+ device_size_high = (data >> cs_high_offset) & 0x1;
+
+ device_size = device_size_low | (device_size_high << 2);
+
+ switch (device_size) {
+ case 0:
+ return 2048;
+ case 2:
+ return 512;
+ case 3:
+ return 1024;
+ case 4:
+ return 4096;
+ case 5:
+ return 8192;
+ case 1:
+ default:
+ DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1);
+ /* zeroes mem size in ddr3_calc_mem_cs_size */
+ return 0;
+ }
+}
+
+int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size)
+{
+ u32 cs_mem_size;
+
+ /* Calculate in MiB */
+ cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) *
+ ddr3_get_device_size(cs)) / 8;
+
+ /*
+ * Multiple controller bus width, 2x for 64 bit
+ * (SoC controller may be 32 or 64 bit,
+ * so bit 15 in 0x1400, that means if whole bus used or only half,
+ * have a differnt meaning
+ */
+ cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER;
+
+ if ((cs_mem_size < 128) || (cs_mem_size > 4096)) {
+ DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1);
+ return MV_BAD_VALUE;
+ }
+
+ *cs_size = cs_mem_size;
+
+ return MV_OK;
+}
+
+static int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena)
+{
+ u32 reg, cs;
+ uint64_t mem_total_size = 0;
+ uint64_t cs_mem_size_mb = 0;
+ uint64_t cs_mem_size = 0;
+ uint64_t mem_total_size_c, cs_mem_size_c;
+
+
+#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE
+ u32 physical_mem_size;
+ u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+#endif
+
+ /* Open fast path windows */
+ for (cs = 0; cs < MAX_CS_NUM; cs++) {
+ if (cs_ena & (1 << cs)) {
+ /* get CS size */
+ if (ddr3_calc_mem_cs_size(cs, &cs_mem_size_mb) != MV_OK)
+ return MV_FAIL;
+ cs_mem_size = cs_mem_size_mb * _1M;
+
+#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE
+ /*
+ * if number of address pins doesn't allow to use max
+ * mem size that is defined in topology
+ * mem size is defined by DEVICE_MAX_DRAM_ADDRESS_SIZE
+ */
+ physical_mem_size = mem_size
+ [tm->interface_params[0].memory_size];
+
+ if (ddr3_get_device_width(cs) == 16) {
+ /*
+ * 16bit mem device can be twice more - no need
+ * in less significant pin
+ */
+ max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2;
+ }
+
+ if (physical_mem_size > max_mem_size) {
+ cs_mem_size = max_mem_size *
+ (ddr3_get_bus_width() /
+ ddr3_get_device_width(cs));
+ printf("Updated Physical Mem size is from 0x%x to %x\n",
+ physical_mem_size,
+ DEVICE_MAX_DRAM_ADDRESS_SIZE);
+ }
+#endif
+
+ /* set fast path window control for the cs */
+ reg = 0xffffe1;
+ reg |= (cs << 2);
+ reg |= (cs_mem_size - 1) & 0xffff0000;
+ /*Open fast path Window */
+ reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg);
+
+ /* Set fast path window base address for the cs */
+ reg = ((cs_mem_size) * cs) & 0xffff0000;
+ /* Set base address */
+ reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg);
+
+ /*
+ * Since memory size may be bigger than 4G the summ may
+ * be more than 32 bit word,
+ * so to estimate the result divide mem_total_size and
+ * cs_mem_size by 0x10000 (it is equal to >> 16)
+ */
+ mem_total_size_c = (mem_total_size >> 16) & 0xffffffffffff;
+ cs_mem_size_c = (cs_mem_size >> 16) & 0xffffffffffff;
+
+ /* if the sum less than 2 G - calculate the value */
+ if (mem_total_size_c + cs_mem_size_c < 0x10000)
+ mem_total_size += cs_mem_size;
+ else /* put max possible size */
+ mem_total_size = L2_FILTER_FOR_MAX_MEMORY_SIZE;
+ }
+ }
+
+ /* Set L2 filtering to Max Memory size */
+ reg_write(ADDRESS_FILTERING_END_REGISTER, mem_total_size);
+
+ return MV_OK;
+}
+
+static int ddr3_restore_and_set_final_windows(u32 *win, const char *ddr_type)
+{
+ u32 win_ctrl_reg, num_of_win_regs;
+ u32 cs_ena = mv_ddr_sys_env_get_cs_ena_from_reg();
+ u32 ui;
+
+ win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR;
+ num_of_win_regs = 16;
+
+ /* Return XBAR windows 4-7 or 16-19 init configuration */
+ for (ui = 0; ui < num_of_win_regs; ui++)
+ reg_write((win_ctrl_reg + 0x4 * ui), win[ui]);
+
+ printf("%s Training Sequence - Switching XBAR Window to FastPath Window\n",
+ ddr_type);
+
+#if defined DYNAMIC_CS_SIZE_CONFIG
+ if (ddr3_fast_path_dynamic_cs_size_config(cs_ena) != MV_OK)
+ printf("ddr3_fast_path_dynamic_cs_size_config FAILED\n");
+#else
+ u32 reg, cs;
+ reg = 0x1fffffe1;
+ for (cs = 0; cs < MAX_CS_NUM; cs++) {
+ if (cs_ena & (1 << cs)) {
+ reg |= (cs << 2);
+ break;
+ }
+ }
+ /* Open fast path Window to - 0.5G */
+ reg_write(REG_FASTPATH_WIN_CTRL_ADDR(0), reg);
+#endif
+
+ return MV_OK;
+}
+
+static int ddr3_save_and_set_training_windows(u32 *win)
+{
+ u32 cs_ena;
+ u32 reg, tmp_count, cs, ui;
+ u32 win_ctrl_reg, win_base_reg, win_remap_reg;
+ u32 num_of_win_regs, win_jump_index;
+ win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR;
+ win_base_reg = REG_XBAR_WIN_4_BASE_ADDR;
+ win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR;
+ win_jump_index = 0x10;
+ num_of_win_regs = 16;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+#ifdef DISABLE_L2_FILTERING_DURING_DDR_TRAINING
+ /*
+ * Disable L2 filtering during DDR training
+ * (when Cross Bar window is open)
+ */
+ reg_write(ADDRESS_FILTERING_END_REGISTER, 0);
+#endif
+
+ cs_ena = tm->interface_params[0].as_bus_params[0].cs_bitmask;
+
+ /* Close XBAR Window 19 - Not needed */
+ /* {0x000200e8} - Open Mbus Window - 2G */
+ reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0);
+
+ /* Save XBAR Windows 4-19 init configurations */
+ for (ui = 0; ui < num_of_win_regs; ui++)
+ win[ui] = reg_read(win_ctrl_reg + 0x4 * ui);
+
+ /* Open XBAR Windows 4-7 or 16-19 for other CS */
+ reg = 0;
+ tmp_count = 0;
+ for (cs = 0; cs < MAX_CS_NUM; cs++) {
+ if (cs_ena & (1 << cs)) {
+ switch (cs) {
+ case 0:
+ reg = 0x0e00;
+ break;
+ case 1:
+ reg = 0x0d00;
+ break;
+ case 2:
+ reg = 0x0b00;
+ break;
+ case 3:
+ reg = 0x0700;
+ break;
+ }
+ reg |= (1 << 0);
+ reg |= (SDRAM_CS_SIZE & 0xffff0000);
+
+ reg_write(win_ctrl_reg + win_jump_index * tmp_count,
+ reg);
+ reg = (((SDRAM_CS_SIZE + 1) * (tmp_count)) &
+ 0xffff0000);
+ reg_write(win_base_reg + win_jump_index * tmp_count,
+ reg);
+
+ if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR)
+ reg_write(win_remap_reg +
+ win_jump_index * tmp_count, 0);
+
+ tmp_count++;
+ }
+ }
+
+ return MV_OK;
+}
+
+static u32 win[16];
+
+int mv_ddr_pre_training_soc_config(const char *ddr_type)
+{
+ u32 soc_num;
+ u32 reg_val;
+
+ /* Switching CPU to MRVL ID */
+ soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >>
+ SAR1_CPU_CORE_OFFSET;
+ switch (soc_num) {
+ case 0x3:
+ reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET);
+ reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET);
+ /* fallthrough */
+ case 0x1:
+ reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET);
+ /* fallthrough */
+ case 0x0:
+ reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET);
+ /* fallthrough */
+ default:
+ break;
+ }
+
+ /*
+ * Set DRAM Reset Mask in case detected GPIO indication of wakeup from
+ * suspend i.e the DRAM values will not be overwritten / reset when
+ * waking from suspend
+ */
+ if (mv_ddr_sys_env_suspend_wakeup_check() ==
+ SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED) {
+ reg_bit_set(SDRAM_INIT_CTRL_REG,
+ DRAM_RESET_MASK_MASKED << DRAM_RESET_MASK_OFFS);
+ }
+
+ /* Check if DRAM is already initialized */
+ if (reg_read(REG_BOOTROM_ROUTINE_ADDR) &
+ (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) {
+ printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type);
+ return MV_OK;
+ }
+
+ /* Fix read ready phases for all SOC in reg 0x15c8 */
+ reg_val = reg_read(TRAINING_DBG_3_REG);
+
+ reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(0));
+ reg_val |= (0x4 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(0)); /* phase 0 */
+
+ reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(1));
+ reg_val |= (0x4 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(1)); /* phase 1 */
+
+ reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(3));
+ reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(3)); /* phase 3 */
+
+ reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(4));
+ reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(4)); /* phase 4 */
+
+ reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(5));
+ reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(5)); /* phase 5 */
+
+ reg_write(TRAINING_DBG_3_REG, reg_val);
+
+ /*
+ * Axi_bresp_mode[8] = Compliant,
+ * Axi_addr_decode_cntrl[11] = Internal,
+ * Axi_data_bus_width[0] = 128bit
+ * */
+ /* 0x14a8 - AXI Control Register */
+ reg_write(AXI_CTRL_REG, 0);
+
+ /*
+ * Stage 2 - Training Values Setup
+ */
+ /* Set X-BAR windows for the training sequence */
+ ddr3_save_and_set_training_windows(win);
+
+ return MV_OK;
+}
+
+static int ddr3_new_tip_dlb_config(void)
+{
+ u32 reg, i = 0;
+ struct dlb_config *config_table_ptr = sys_env_dlb_config_ptr_get();
+
+ /* Write the configuration */
+ while (config_table_ptr[i].reg_addr != 0) {
+ reg_write(config_table_ptr[i].reg_addr,
+ config_table_ptr[i].reg_data);
+ i++;
+ }
+
+
+ /* Enable DLB */
+ reg = reg_read(DLB_CTRL_REG);
+ reg &= ~(DLB_EN_MASK << DLB_EN_OFFS) &
+ ~(WR_COALESCE_EN_MASK << WR_COALESCE_EN_OFFS) &
+ ~(AXI_PREFETCH_EN_MASK << AXI_PREFETCH_EN_OFFS) &
+ ~(MBUS_PREFETCH_EN_MASK << MBUS_PREFETCH_EN_OFFS) &
+ ~(PREFETCH_NXT_LN_SZ_TRIG_MASK << PREFETCH_NXT_LN_SZ_TRIG_OFFS);
+
+ reg |= (DLB_EN_ENA << DLB_EN_OFFS) |
+ (WR_COALESCE_EN_ENA << WR_COALESCE_EN_OFFS) |
+ (AXI_PREFETCH_EN_ENA << AXI_PREFETCH_EN_OFFS) |
+ (MBUS_PREFETCH_EN_ENA << MBUS_PREFETCH_EN_OFFS) |
+ (PREFETCH_NXT_LN_SZ_TRIG_ENA << PREFETCH_NXT_LN_SZ_TRIG_OFFS);
+
+ reg_write(DLB_CTRL_REG, reg);
+
+ return MV_OK;
+}
+
+int mv_ddr_post_training_soc_config(const char *ddr_type)
+{
+ u32 reg_val;
+
+ /* Restore and set windows */
+ ddr3_restore_and_set_final_windows(win, ddr_type);
+
+ /* Update DRAM init indication in bootROM register */
+ reg_val = reg_read(REG_BOOTROM_ROUTINE_ADDR);
+ reg_write(REG_BOOTROM_ROUTINE_ADDR,
+ reg_val | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS));
+
+ /* DLB config */
+ ddr3_new_tip_dlb_config();
+
+ return MV_OK;
+}
+
+void mv_ddr_mc_config(void)
+{
+ /* Memory controller initializations */
+ struct init_cntr_param init_param;
+ int status;
+
+ init_param.do_mrs_phy = 1;
+ init_param.is_ctrl64_bit = 0;
+ init_param.init_phy = 1;
+ init_param.msys_init = 1;
+ status = hws_ddr3_tip_init_controller(0, &init_param);
+ if (status != MV_OK)
+ printf("DDR3 init controller - FAILED 0x%x\n", status);
+
+ status = mv_ddr_mc_init();
+ if (status != MV_OK)
+ printf("DDR3 init_sequence - FAILED 0x%x\n", status);
+}
+/* function: mv_ddr_mc_init
+ * this function enables the dunit after init controller configuration
+ */
+int mv_ddr_mc_init(void)
+{
+ CHECK_STATUS(ddr3_tip_enable_init_sequence(0));
+
+ return MV_OK;
+}
+
+/* function: ddr3_tip_configure_phy
+ * configures phy and electrical parameters
+ */
+int ddr3_tip_configure_phy(u32 dev_num)
+{
+ u32 if_id, phy_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();
+
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ PAD_ZRI_CAL_PHY_REG,
+ ((0x7f & g_zpri_data) << 7 | (0x7f & g_znri_data))));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL,
+ PAD_ZRI_CAL_PHY_REG,
+ ((0x7f & g_zpri_ctrl) << 7 | (0x7f & g_znri_ctrl))));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ PAD_ODT_CAL_PHY_REG,
+ ((0x3f & g_zpodt_data) << 6 | (0x3f & g_znodt_data))));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL,
+ PAD_ODT_CAL_PHY_REG,
+ ((0x3f & g_zpodt_ctrl) << 6 | (0x3f & g_znodt_ctrl))));
+
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ PAD_PRE_DISABLE_PHY_REG, 0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ CMOS_CONFIG_PHY_REG, 0));
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL,
+ CMOS_CONFIG_PHY_REG, 0));
+
+ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
+ /* check if the interface is enabled */
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ for (phy_id = 0;
+ phy_id < octets_per_if_num;
+ phy_id++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id);
+ /* Vref & clamp */
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, phy_id, DDR_PHY_DATA,
+ PAD_CFG_PHY_REG,
+ ((clamp_tbl[if_id] << 4) | vref_init_val),
+ ((0x7 << 4) | 0x7)));
+ /* clamp not relevant for control */
+ CHECK_STATUS(ddr3_tip_bus_read_modify_write
+ (dev_num, ACCESS_TYPE_UNICAST,
+ if_id, phy_id, DDR_PHY_CONTROL,
+ PAD_CFG_PHY_REG, 0x4, 0x7));
+ }
+ }
+
+ if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_PHY_EDGE) ==
+ MV_DDR_PHY_EDGE_POSITIVE)
+ CHECK_STATUS(ddr3_tip_bus_write
+ (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR_PHY_DATA, 0x90, 0x6002));
+
+
+ return MV_OK;
+}
+
+
+int mv_ddr_manual_cal_do(void)
+{
+ return 0;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.h
new file mode 100644
index 000000000..44998847c
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_plat.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR_PLAT_H
+#define _MV_DDR_PLAT_H
+
+#include <linux/delay.h>
+
+#define MAX_DEVICE_NUM 1
+#define MAX_INTERFACE_NUM 1
+#define MAX_BUS_NUM 5
+#define DDR_IF_CTRL_SUBPHYS_NUM 3
+
+#define DFS_LOW_FREQ_VALUE 120
+#define SDRAM_CS_SIZE 0xfffffff /* FIXME: implement a function for cs size for each platform */
+
+#define INTER_REGS_BASE SOC_REGS_PHY_BASE
+#define AP_INT_REG_START_ADDR 0xd0000000
+#define AP_INT_REG_END_ADDR 0xd0100000
+
+/* Controler bus divider 1 for 32 bit, 2 for 64 bit */
+#define DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER 1
+
+/* Tune internal training params values */
+#define TUNE_TRAINING_PARAMS_CK_DELAY 160
+#define TUNE_TRAINING_PARAMS_PHYREG3VAL 0xA
+#define TUNE_TRAINING_PARAMS_PRI_DATA 123
+#define TUNE_TRAINING_PARAMS_NRI_DATA 123
+#define TUNE_TRAINING_PARAMS_PRI_CTRL 74
+#define TUNE_TRAINING_PARAMS_NRI_CTRL 74
+#define TUNE_TRAINING_PARAMS_P_ODT_DATA 45
+#define TUNE_TRAINING_PARAMS_N_ODT_DATA 45
+#define TUNE_TRAINING_PARAMS_P_ODT_CTRL 45
+#define TUNE_TRAINING_PARAMS_N_ODT_CTRL 45
+#define TUNE_TRAINING_PARAMS_DIC 0x2
+#define TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS 0x120012
+#define TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS 0x10000
+#define TUNE_TRAINING_PARAMS_RTT_NOM 0x44
+
+#define TUNE_TRAINING_PARAMS_RTT_WR_1CS 0x0 /*off*/
+#define TUNE_TRAINING_PARAMS_RTT_WR_2CS 0x0 /*off*/
+
+#define MARVELL_BOARD MARVELL_BOARD_ID_BASE
+
+
+#define REG_DEVICE_SAR1_ADDR 0xe4204
+#define RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET 17
+#define RST2_CPU_DDR_CLOCK_SELECT_IN_MASK 0x1f
+#define DEVICE_SAMPLE_AT_RESET2_REG 0x18604
+
+#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET 0
+#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ 0
+#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_40MHZ 1
+
+/* DRAM Windows */
+#define REG_XBAR_WIN_5_CTRL_ADDR 0x20050
+#define REG_XBAR_WIN_5_BASE_ADDR 0x20054
+
+/* DRAM Windows */
+#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040
+#define REG_XBAR_WIN_4_BASE_ADDR 0x20044
+#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048
+#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078
+#define REG_XBAR_WIN_16_CTRL_ADDR 0x200d0
+#define REG_XBAR_WIN_16_BASE_ADDR 0x200d4
+#define REG_XBAR_WIN_16_REMAP_ADDR 0x200dc
+#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8
+
+#define REG_FASTPATH_WIN_BASE_ADDR(win) (0x20180 + (0x8 * win))
+#define REG_FASTPATH_WIN_CTRL_ADDR(win) (0x20184 + (0x8 * win))
+
+#define CPU_CONFIGURATION_REG(id) (0x21800 + (id * 0x100))
+#define CPU_MRVL_ID_OFFSET 0x10
+#define SAR1_CPU_CORE_MASK 0x00000018
+#define SAR1_CPU_CORE_OFFSET 3
+
+/* SatR defined too change topology busWidth and ECC configuration */
+#define DDR_SATR_CONFIG_MASK_WIDTH 0x8
+#define DDR_SATR_CONFIG_MASK_ECC 0x10
+#define DDR_SATR_CONFIG_MASK_ECC_PUP 0x20
+
+#define REG_SAMPLE_RESET_HIGH_ADDR 0x18600
+
+#define MV_BOARD_REFCLK_25MHZ 25000000
+#define MV_BOARD_REFCLK MV_BOARD_REFCLK_25MHZ
+
+#define MAX_DQ_NUM 40
+
+/* dram line buffer registers */
+#define DLB_CTRL_REG 0x1700
+#define DLB_EN_OFFS 0
+#define DLB_EN_MASK 0x1
+#define DLB_EN_ENA 1
+#define DLB_EN_DIS 0
+#define WR_COALESCE_EN_OFFS 2
+#define WR_COALESCE_EN_MASK 0x1
+#define WR_COALESCE_EN_ENA 1
+#define WR_COALESCE_EN_DIS 0
+#define AXI_PREFETCH_EN_OFFS 3
+#define AXI_PREFETCH_EN_MASK 0x1
+#define AXI_PREFETCH_EN_ENA 1
+#define AXI_PREFETCH_EN_DIS 0
+#define MBUS_PREFETCH_EN_OFFS 4
+#define MBUS_PREFETCH_EN_MASK 0x1
+#define MBUS_PREFETCH_EN_ENA 1
+#define MBUS_PREFETCH_EN_DIS 0
+#define PREFETCH_NXT_LN_SZ_TRIG_OFFS 6
+#define PREFETCH_NXT_LN_SZ_TRIG_MASK 0x1
+#define PREFETCH_NXT_LN_SZ_TRIG_ENA 1
+#define PREFETCH_NXT_LN_SZ_TRIG_DIS 0
+
+#define DLB_BUS_OPT_WT_REG 0x1704
+#define DLB_AGING_REG 0x1708
+#define DLB_EVICTION_CTRL_REG 0x170c
+#define DLB_EVICTION_TIMERS_REG 0x1710
+#define DLB_USER_CMD_REG 0x1714
+#define DLB_WTS_DIFF_CS_REG 0x1770
+#define DLB_WTS_DIFF_BG_REG 0x1774
+#define DLB_WTS_SAME_BG_REG 0x1778
+#define DLB_WTS_CMDS_REG 0x177c
+#define DLB_WTS_ATTR_PRIO_REG 0x1780
+#define DLB_QUEUE_MAP_REG 0x1784
+#define DLB_SPLIT_REG 0x1788
+
+/* ck swap control subphy number */
+#define CK_SWAP_CTRL_PHY_NUM 2
+
+/* Subphy result control per byte registers */
+#define RESULT_CONTROL_BYTE_PUP_0_REG 0x1830
+#define RESULT_CONTROL_BYTE_PUP_1_REG 0x1834
+#define RESULT_CONTROL_BYTE_PUP_2_REG 0x1838
+#define RESULT_CONTROL_BYTE_PUP_3_REG 0x183c
+#define RESULT_CONTROL_BYTE_PUP_4_REG 0x18b0
+
+/* Subphy result control per bit registers */
+#define RESULT_CONTROL_PUP_0_BIT_0_REG 0x18b4
+#define RESULT_CONTROL_PUP_0_BIT_1_REG 0x18b8
+#define RESULT_CONTROL_PUP_0_BIT_2_REG 0x18bc
+#define RESULT_CONTROL_PUP_0_BIT_3_REG 0x18c0
+#define RESULT_CONTROL_PUP_0_BIT_4_REG 0x18c4
+#define RESULT_CONTROL_PUP_0_BIT_5_REG 0x18c8
+#define RESULT_CONTROL_PUP_0_BIT_6_REG 0x18cc
+#define RESULT_CONTROL_PUP_0_BIT_7_REG 0x18f0
+
+#define RESULT_CONTROL_PUP_1_BIT_0_REG 0x18f4
+#define RESULT_CONTROL_PUP_1_BIT_1_REG 0x18f8
+#define RESULT_CONTROL_PUP_1_BIT_2_REG 0x18fc
+#define RESULT_CONTROL_PUP_1_BIT_3_REG 0x1930
+#define RESULT_CONTROL_PUP_1_BIT_4_REG 0x1934
+#define RESULT_CONTROL_PUP_1_BIT_5_REG 0x1938
+#define RESULT_CONTROL_PUP_1_BIT_6_REG 0x193c
+#define RESULT_CONTROL_PUP_1_BIT_7_REG 0x19b0
+
+#define RESULT_CONTROL_PUP_2_BIT_0_REG 0x19b4
+#define RESULT_CONTROL_PUP_2_BIT_1_REG 0x19b8
+#define RESULT_CONTROL_PUP_2_BIT_2_REG 0x19bc
+#define RESULT_CONTROL_PUP_2_BIT_3_REG 0x19c0
+#define RESULT_CONTROL_PUP_2_BIT_4_REG 0x19c4
+#define RESULT_CONTROL_PUP_2_BIT_5_REG 0x19c8
+#define RESULT_CONTROL_PUP_2_BIT_6_REG 0x19cc
+#define RESULT_CONTROL_PUP_2_BIT_7_REG 0x19f0
+
+#define RESULT_CONTROL_PUP_3_BIT_0_REG 0x19f4
+#define RESULT_CONTROL_PUP_3_BIT_1_REG 0x19f8
+#define RESULT_CONTROL_PUP_3_BIT_2_REG 0x19fc
+#define RESULT_CONTROL_PUP_3_BIT_3_REG 0x1a30
+#define RESULT_CONTROL_PUP_3_BIT_4_REG 0x1a34
+#define RESULT_CONTROL_PUP_3_BIT_5_REG 0x1a38
+#define RESULT_CONTROL_PUP_3_BIT_6_REG 0x1a3c
+#define RESULT_CONTROL_PUP_3_BIT_7_REG 0x1ab0
+
+#define RESULT_CONTROL_PUP_4_BIT_0_REG 0x1ab4
+#define RESULT_CONTROL_PUP_4_BIT_1_REG 0x1ab8
+#define RESULT_CONTROL_PUP_4_BIT_2_REG 0x1abc
+#define RESULT_CONTROL_PUP_4_BIT_3_REG 0x1ac0
+#define RESULT_CONTROL_PUP_4_BIT_4_REG 0x1ac4
+#define RESULT_CONTROL_PUP_4_BIT_5_REG 0x1ac8
+#define RESULT_CONTROL_PUP_4_BIT_6_REG 0x1acc
+#define RESULT_CONTROL_PUP_4_BIT_7_REG 0x1af0
+
+/* CPU */
+#define REG_BOOTROM_ROUTINE_ADDR 0x182d0
+#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS 12
+
+/* Matrix enables DRAM modes (bus width/ECC) per boardId */
+#define TOPOLOGY_UPDATE_32BIT 0
+#define TOPOLOGY_UPDATE_32BIT_ECC 1
+#define TOPOLOGY_UPDATE_16BIT 2
+#define TOPOLOGY_UPDATE_16BIT_ECC 3
+#define TOPOLOGY_UPDATE_16BIT_ECC_PUP3 4
+#define TOPOLOGY_UPDATE { \
+ /* 32Bit, 32bit ECC, 16bit, 16bit ECC PUP4, 16bit ECC PUP3 */ \
+ {1, 1, 1, 1, 1}, /* RD_NAS_68XX_ID */ \
+ {1, 1, 1, 1, 1}, /* DB_68XX_ID */ \
+ {1, 0, 1, 0, 1}, /* RD_AP_68XX_ID */ \
+ {1, 0, 1, 0, 1}, /* DB_AP_68XX_ID */ \
+ {1, 0, 1, 0, 1}, /* DB_GP_68XX_ID */ \
+ {0, 0, 1, 1, 0}, /* DB_BP_6821_ID */ \
+ {1, 1, 1, 1, 1} /* DB_AMC_6820_ID */ \
+ };
+
+enum {
+ CPU_1066MHZ_DDR_400MHZ,
+ CPU_RESERVED_DDR_RESERVED0,
+ CPU_667MHZ_DDR_667MHZ,
+ CPU_800MHZ_DDR_800MHZ,
+ CPU_RESERVED_DDR_RESERVED1,
+ CPU_RESERVED_DDR_RESERVED2,
+ CPU_RESERVED_DDR_RESERVED3,
+ LAST_FREQ
+};
+
+/* struct used for DLB configuration array */
+struct dlb_config {
+ u32 reg_addr;
+ u32 reg_data;
+};
+
+#define ACTIVE_INTERFACE_MASK 0x1
+
+extern u32 dmin_phy_reg_table[][2];
+extern u16 odt_slope[];
+extern u16 odt_intercept[];
+
+int mv_ddr_pre_training_soc_config(const char *ddr_type);
+int mv_ddr_post_training_soc_config(const char *ddr_type);
+void mv_ddr_mem_scrubbing(void);
+u32 mv_ddr_init_freq_get(void);
+void mv_ddr_odpg_enable(void);
+void mv_ddr_odpg_disable(void);
+void mv_ddr_odpg_done_clr(void);
+int mv_ddr_is_odpg_done(u32 count);
+void mv_ddr_training_enable(void);
+int mv_ddr_is_training_done(u32 count, u32 *result);
+u32 mv_ddr_dm_pad_get(void);
+int mv_ddr_pre_training_fixup(void);
+int mv_ddr_post_training_fixup(void);
+int mv_ddr_manual_cal_do(void);
+int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size);
+
+#endif /* _MV_DDR_PLAT_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_regs.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_regs.h
new file mode 100644
index 000000000..cf2a6c92e
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_regs.h
@@ -0,0 +1,465 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR_REGS_H
+#define _MV_DDR_REGS_H
+
+#define GLOB_CTRL_STATUS_REG 0x1030
+#define TRAINING_TRIGGER_OFFS 0
+#define TRAINING_TRIGGER_MASK 0x1
+#define TRAINING_TRIGGER_ENA 1
+#define TRAINING_DONE_OFFS 1
+#define TRAINING_DONE_MASK 0x1
+#define TRAINING_DONE_DONE 1
+#define TRAINING_DONE_NOT_DONE 0
+#define TRAINING_RESULT_OFFS 2
+#define TRAINING_RESULT_MASK 0x1
+#define TRAINING_RESULT_PASS 0
+#define TRAINING_RESULT_FAIL 1
+
+#define GENERAL_TRAINING_OPCODE_REG 0x1034
+
+#define OPCODE_REG0_BASE 0x1038
+#define OPCODE_REG0_REG(obj) (OPCODE_REG0_BASE + (obj) * 0x4)
+
+#define OPCODE_REG1_BASE 0x10b0
+#define OPCODE_REG1_REG(obj) (OPCODE_REG1_BASE + (obj) * 0x4)
+
+#define CAL_PHY_BASE 0x10c0
+#define CAL_PHY_REG(obj) (CAL_PHY_BASE + (obj) * 0x4)
+
+#define WL_DONE_CNTR_REF_REG 0x10f8
+#define ODPG_WR_RD_MODE_ENA_REG 0x10fc
+
+#define SDRAM_CFG_REG 0x1400
+#define REFRESH_OFFS 0
+#define REFRESH_MASK 0x3fff
+#define DRAM_TYPE_OFFS 14
+#define DRAM_TYPE_MASK 0x1
+#define BUS_IN_USE_OFFS 15
+#define BUS_IN_USE_MASK 0x1
+#define CPU_2DRAM_WR_BUFF_CUT_TH_OFFS 16
+#define CPU_2DRAM_WR_BUFF_CUT_TH_MASK 0x1
+#define REG_DIMM_OFFS 17
+#define REG_DIMM_MASK 0x1
+#define ECC_OFFS 18
+#define ECC_MASK 0x1
+#define IGNORE_ERRORS_OFFS 19
+#define IGNORE_ERRORS_MASK 0x1
+#define DRAM_TYPE_HIGH_OFFS 20
+#define DRAM_TYPE_HIGH_MASK 0x1
+#define SELF_REFRESH_MODE_OFFS 24
+#define SELF_REFRESH_MODE_MASK 0x1
+#define CPU_RD_PER_PROP_OFFS 25
+#define CPU_RD_PER_PROP_MASK 0x1
+#define DDR4_EMULATION_OFFS 26
+#define DDR4_EMULATION_MASK 0x1
+#define PHY_RF_RST_OFFS 27
+#define PHY_RF_RST_MASK 0x1
+#define PUP_RST_DIVIDER_OFFS 28
+#define PUP_RST_DIVIDER_MASK 0x1
+#define DATA_PUP_WR_RESET_OFFS 29
+#define DATA_PUP_WR_RESET_MASK 0x1
+#define DATA_PUP_RD_RESET_OFFS 30
+#define DATA_PUP_RD_RESET_MASK 0x1
+#define DATA_PUP_RD_RESET_ENA 0x0
+#define DATA_PUP_RD_RESET_DIS 0x1
+#define IO_BIST_OFFS 31
+#define DATA_PUP_RD_RESET_MASK 0x1
+
+#define DUNIT_CTRL_LOW_REG 0x1404
+
+#define SDRAM_TIMING_LOW_REG 0x1408
+#define SDRAM_TIMING_LOW_TRAS_OFFS 0
+#define SDRAM_TIMING_LOW_TRAS_MASK 0xf
+#define SDRAM_TIMING_LOW_TRCD_OFFS 4
+#define SDRAM_TIMING_LOW_TRCD_MASK 0xf
+#define SDRAM_TIMING_HIGH_TRCD_OFFS 22
+#define SDRAM_TIMING_HIGH_TRCD_MASK 0x1
+#define SDRAM_TIMING_LOW_TRP_OFFS 8
+#define SDRAM_TIMING_LOW_TRP_MASK 0xf
+#define SDRAM_TIMING_HIGH_TRP_OFFS 23
+#define SDRAM_TIMING_HIGH_TRP_MASK 0x1
+#define SDRAM_TIMING_LOW_TWR_OFFS 12
+#define SDRAM_TIMING_LOW_TWR_MASK 0xf
+#define SDRAM_TIMING_LOW_TWTR_OFFS 16
+#define SDRAM_TIMING_LOW_TWTR_MASK 0xf
+#define SDRAM_TIMING_LOW_TRAS_HIGH_OFFS 20
+#define SDRAM_TIMING_LOW_TRAS_HIGH_MASK 0x3
+#define SDRAM_TIMING_LOW_TRRD_OFFS 24
+#define SDRAM_TIMING_LOW_TRRD_MASK 0xf
+#define SDRAM_TIMING_LOW_TRTP_OFFS 28
+#define SDRAM_TIMING_LOW_TRTP_MASK 0xf
+
+#define SDRAM_TIMING_HIGH_REG 0x140c
+#define SDRAM_TIMING_HIGH_TRFC_OFFS 0
+#define SDRAM_TIMING_HIGH_TRFC_MASK 0x7f
+#define SDRAM_TIMING_HIGH_TR2R_OFFS 7
+#define SDRAM_TIMING_HIGH_TR2R_MASK 0x3
+#define SDRAM_TIMING_HIGH_TR2W_W2R_OFFS 9
+#define SDRAM_TIMING_HIGH_TR2W_W2R_MASK 0x3
+#define SDRAM_TIMING_HIGH_TW2W_OFFS 11
+#define SDRAM_TIMING_HIGH_TW2W_MASK 0x1f
+#define SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS 16
+#define SDRAM_TIMING_HIGH_TRFC_HIGH_MASK 0x7
+#define SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS 19
+#define SDRAM_TIMING_HIGH_TR2R_HIGH_MASK 0x7
+#define SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS 22
+#define SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK 0x7
+#define SDRAM_TIMING_HIGH_TMOD_OFFS 25
+#define SDRAM_TIMING_HIGH_TMOD_MASK 0xf
+#define SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS 30
+#define SDRAM_TIMING_HIGH_TMOD_HIGH_MASK 0x3
+
+#define SDRAM_ADDR_CTRL_REG 0x1410
+#define CS_STRUCT_BASE 0
+#define CS_STRUCT_OFFS(cs) (CS_STRUCT_BASE + (cs) * 4)
+#define CS_STRUCT_MASK 0x3
+#define CS_SIZE_BASE 2
+#define CS_SIZE_OFFS(cs) (CS_SIZE_BASE + (cs) * 4)
+#define CS_SIZE_MASK 0x3
+#define CS_SIZE_HIGH_BASE 20
+#define CS_SIZE_HIGH_OFFS(cs) (CS_SIZE_HIGH_BASE + (cs))
+#define CS_SIZE_HIGH_MASK 0x1
+#define T_FAW_OFFS 24
+#define T_FAW_MASK 0x7f
+
+#define SDRAM_OPEN_PAGES_CTRL_REG 0x1414
+
+#define SDRAM_OP_REG 0x1418
+#define SDRAM_OP_CMD_OFFS 0
+#define SDRAM_OP_CMD_MASK 0x1f
+#define SDRAM_OP_CMD_CS_BASE 8
+#define SDRAM_OP_CMD_CS_OFFS(cs) (SDRAM_OP_CMD_CS_BASE + (cs))
+#define SDRAM_OP_CMD_CS_MASK 0x1
+#define SDRAM_OP_CMD_ALL_CS_MASK 0xf
+enum {
+ CMD_NORMAL,
+ CMD_PRECHARGE,
+ CMD_REFRESH,
+ CMD_DDR3_DDR4_MR0,
+ CMD_DDR3_DDR4_MR1,
+ CMD_NOP,
+ CMD_RES_0X6,
+ CMD_SELFREFRESH,
+ CMD_DDR3_DDR4_MR2,
+ CMD_DDR3_DDR4_MR3,
+ CMD_ACT_PDE,
+ CMD_PRE_PDE,
+ CMD_ZQCL,
+ CMD_ZQCS,
+ CMD_CWA,
+ CMD_RES_0XF,
+ CMD_DDR4_MR4,
+ CMD_DDR4_MR5,
+ CMD_DDR4_MR6,
+ DDR4_MPR_WR
+};
+
+#define DUNIT_CTRL_HIGH_REG 0x1424
+#define CPU_INTERJECTION_ENA_OFFS 3
+#define CPU_INTERJECTION_ENA_MASK 0x1
+#define CPU_INTERJECTION_ENA_SPLIT_ENA 0
+#define CPU_INTERJECTION_ENA_SPLIT_DIS 1
+
+#define DDR_ODT_TIMING_LOW_REG 0x1428
+
+#define DDR_TIMING_REG 0x142c
+#define DDR_TIMING_TCCD_OFFS 18
+#define DDR_TIMING_TCCD_MASK 0x7
+#define DDR_TIMING_TPD_OFFS 0
+#define DDR_TIMING_TPD_MASK 0xf
+#define DDR_TIMING_TXPDLL_OFFS 4
+#define DDR_TIMING_TXPDLL_MASK 0x1f
+
+#define DDR_ODT_TIMING_HIGH_REG 0x147c
+
+#define SDRAM_INIT_CTRL_REG 0x1480
+#define DRAM_RESET_MASK_OFFS 1
+#define DRAM_RESET_MASK_MASK 0x1
+#define DRAM_RESET_MASK_NORMAL 0
+#define DRAM_RESET_MASK_MASKED 1
+
+#define SDRAM_ODT_CTRL_HIGH_REG 0x1498
+#define DUNIT_ODT_CTRL_REG 0x149c
+#define RD_BUFFER_SEL_REG 0x14a4
+#define AXI_CTRL_REG 0x14a8
+#define DUNIT_MMASK_REG 0x14b0
+
+#define HORZ_SSTL_CAL_MACH_CTRL_REG 0x14c8
+#define HORZ_POD_CAL_MACH_CTRL_REG 0x17c8
+#define VERT_SSTL_CAL_MACH_CTRL_REG 0x1dc8
+#define VERT_POD_CAL_MACH_CTRL_REG 0x1ec8
+
+#define MAIN_PADS_CAL_MACH_CTRL_REG 0x14cc
+#define DYN_PADS_CAL_ENABLE_OFFS 0
+#define DYN_PADS_CAL_ENABLE_MASK 0x1
+#define DYN_PADS_CAL_ENABLE_DIS 0
+#define DYN_PADS_CAL_ENABLE_ENA 1
+#define PADS_RECAL_OFFS 1
+#define PADS_RECAL_MASK 0x1
+#define DYN_PADS_CAL_BLOCK_OFFS 2
+#define DYN_PADS_CAL_BLOCK_MASK 0x1
+#define CAL_UPDATE_CTRL_OFFS 3
+#define CAL_UPDATE_CTRL_MASK 0x3
+#define CAL_UPDATE_CTRL_INT 1
+#define CAL_UPDATE_CTRL_EXT 2
+#define DYN_PADS_CAL_CNTR_OFFS 13
+#define DYN_PADS_CAL_CNTR_MASK 0x3ffff
+#define CAL_MACH_STATUS_OFFS 31
+#define CAL_MACH_STATUS_MASK 0x1
+#define CAL_MACH_BUSY 0
+#define CAL_MACH_RDY 1
+
+#define DRAM_DLL_TIMING_REG 0x14e0
+#define DRAM_ZQ_INIT_TIMIMG_REG 0x14e4
+#define DRAM_ZQ_TIMING_REG 0x14e8
+
+#define DRAM_LONG_TIMING_REG 0x14ec
+#define DDR4_TRRD_L_OFFS 0
+#define DDR4_TRRD_L_MASK 0xf
+#define DDR4_TWTR_L_OFFS 4
+#define DDR4_TWTR_L_MASK 0xf
+
+#define DDR_IO_REG 0x1524
+#define DFS_REG 0x1528
+
+#define RD_DATA_SMPL_DLYS_REG 0x1538
+#define RD_SMPL_DLY_CS_BASE 0
+#define RD_SMPL_DLY_CS_OFFS(cs) (RD_SMPL_DLY_CS_BASE + (cs) * 8)
+#define RD_SMPL_DLY_CS_MASK 0x1f
+
+#define RD_DATA_RDY_DLYS_REG 0x153c
+#define RD_RDY_DLY_CS_BASE 0
+#define RD_RDY_DLY_CS_OFFS(cs) (RD_RDY_DLY_CS_BASE + (cs) * 8)
+#define RD_RDY_DLY_CS_MASK 0x1f
+
+#define TRAINING_REG 0x15b0
+#define TRN_START_OFFS 31
+#define TRN_START_MASK 0x1
+#define TRN_START_ENA 1
+#define TRN_START_DIS 0
+
+#define TRAINING_SW_1_REG 0x15b4
+
+#define TRAINING_SW_2_REG 0x15b8
+#define TRAINING_ECC_MUX_OFFS 1
+#define TRAINING_ECC_MUX_MASK 0x1
+#define TRAINING_ECC_MUX_DIS 0
+#define TRAINING_ECC_MUX_ENA 1
+#define TRAINING_SW_OVRD_OFFS 0
+#define TRAINING_SW_OVRD_MASK 0x1
+#define TRAINING_SW_OVRD_DIS 0
+#define TRAINING_SW_OVRD_ENA 1
+
+#define TRAINING_PATTERN_BASE_ADDR_REG 0x15bc
+#define TRAINING_DBG_1_REG 0x15c0
+#define TRAINING_DBG_2_REG 0x15c4
+
+#define TRAINING_DBG_3_REG 0x15c8
+#define TRN_DBG_RDY_INC_PH_2TO1_BASE 0
+#define TRN_DBG_RDY_INC_PH_2TO1_OFFS(phase) (TRN_DBG_RDY_INC_PH_2TO1_BASE + (phase) * 3)
+#define TRN_DBG_RDY_INC_PH_2TO1_MASK 0x7
+
+#define DDR3_RANK_CTRL_REG 0x15e0
+#define CS_EXIST_BASE 0
+#define CS_EXIST_OFFS(cs) (CS_EXIST_BASE + (cs))
+#define CS_EXIST_MASK 0x1
+
+#define ZQC_CFG_REG 0x15e4
+#define DRAM_PHY_CFG_REG 0x15ec
+#define ODPG_CTRL_CTRL_REG 0x1600
+#define ODPG_CTRL_AUTO_REFRESH_OFFS 21
+#define ODPG_CTRL_AUTO_REFRESH_MASK 0x1
+#define ODPG_CTRL_AUTO_REFRESH_DIS 1
+#define ODPG_CTRL_AUTO_REFRESH_ENA 0
+
+#define ODPG_DATA_CTRL_REG 0x1630
+#define ODPG_WRBUF_WR_CTRL_OFFS 0
+#define ODPG_WRBUF_WR_CTRL_MASK 0x1
+#define ODPG_WRBUF_WR_CTRL_DIS 0
+#define ODPG_WRBUF_WR_CTRL_ENA 1
+#define ODPG_WRBUF_RD_CTRL_OFFS 1
+#define ODPG_WRBUF_RD_CTRL_MASK 0x1
+#define ODPG_WRBUF_RD_CTRL_DIS 0
+#define ODPG_WRBUF_RD_CTRL_ENA 1
+#define ODPG_DATA_CBDEL_OFFS 15
+#define ODPG_DATA_CBDEL_MASK 0x3f
+#define ODPG_MODE_OFFS 25
+#define ODPG_MODE_MASK 0x1
+#define ODPG_MODE_RX 0
+#define ODPG_MODE_TX 1
+#define ODPG_DATA_CS_OFFS 26
+#define ODPG_DATA_CS_MASK 0x3
+#define ODPG_DISABLE_OFFS 30
+#define ODPG_DISABLE_MASK 0x1
+#define ODPG_DISABLE_DIS 1
+#define ODPG_ENABLE_OFFS 31
+#define ODPG_ENABLE_MASK 0x1
+#define ODPG_ENABLE_ENA 1
+
+#define ODPG_DATA_BUFFER_OFFS_REG 0x1638
+#define ODPG_DATA_BUFFER_SIZE_REG 0x163c
+#define PHY_LOCK_STATUS_REG 0x1674
+
+#define PHY_REG_FILE_ACCESS_REG 0x16a0
+#define PRFA_DATA_OFFS 0
+#define PRFA_DATA_MASK 0xffff
+#define PRFA_REG_NUM_OFFS 16
+#define PRFA_REG_NUM_MASK 0x3f
+#define PRFA_PUP_NUM_OFFS 22
+#define PRFA_PUP_NUM_MASK 0xf
+#define PRFA_PUP_CTRL_DATA_OFFS 26
+#define PRFA_PUP_CTRL_DATA_MASK 0x1
+#define PRFA_PUP_BCAST_WR_ENA_OFFS 27
+#define PRFA_PUP_BCAST_WR_ENA_MASK 0x1
+#define PRFA_REG_NUM_HI_OFFS 28
+#define PRFA_REG_NUM_HI_MASK 0x3
+#define PRFA_TYPE_OFFS 30
+#define PRFA_TYPE_MASK 0x1
+#define PRFA_REQ_OFFS 31
+#define PRFA_REQ_MASK 0x1
+#define PRFA_REQ_DIS 0x0
+#define PRFA_REQ_ENA 0x1
+
+#define TRAINING_WL_REG 0x16ac
+
+#define ODPG_DATA_WR_ADDR_REG 0x16b0
+#define ODPG_DATA_WR_ACK_OFFS 0
+#define ODPG_DATA_WR_ACK_MASK 0x7f
+#define ODPG_DATA_WR_DATA_OFFS 8
+#define ODPG_DATA_WR_DATA_MASK 0xff
+
+#define ODPG_DATA_WR_DATA_HIGH_REG 0x16b4
+#define ODPG_DATA_WR_DATA_LOW_REG 0x16b8
+#define ODPG_DATA_RX_WORD_ERR_ADDR_REG 0x16bc
+#define ODPG_DATA_RX_WORD_ERR_CNTR_REG 0x16c0
+#define ODPG_DATA_RX_WORD_ERR_DATA_HIGH_REG 0x16c4
+#define ODPG_DATA_RX_WORD_ERR_DATA_LOW_REG 0x16c8
+#define ODPG_DATA_WR_DATA_ERR_REG 0x16cc
+
+#define DUAL_DUNIT_CFG_REG 0x16d8
+#define FC_SAMPLE_STAGES_OFFS 0
+#define FC_SAMPLE_STAGES_MASK 0x7
+#define SINGLE_CS_PIN_OFFS 3
+#define SINGLE_CS_PIN_MASK 0x1
+#define SINGLE_CS_ENA 1
+#define TUNING_ACTIVE_SEL_OFFS 6
+#define TUNING_ACTIVE_SEL_MASK 0x1
+#define TUNING_ACTIVE_SEL_MC 0
+#define TUNING_ACTIVE_SEL_TIP 1
+
+#define WL_DQS_PATTERN_REG 0x16dc
+#define ODPG_DONE_STATUS_REG 0x16fc
+#define ODPG_DONE_STATUS_BIT_OFFS 0
+#define ODPG_DONE_STATUS_BIT_MASK 0x1
+#define ODPG_DONE_STATUS_BIT_CLR 0
+#define ODPG_DONE_STATUS_BIT_SET 1
+
+#define RESULT_CTRL_BASE 0x1830
+#define BLOCK_STATUS_OFFS 25
+#define BLOCK_STATUS_MASK 0x1
+#define BLOCK_STATUS_LOCK 1
+#define BLOCK_STATUS_NOT_LOCKED 0
+
+#define MR0_REG 0x15d0
+#define MR1_REG 0x15d4
+#define MR2_REG 0x15d8
+#define MR3_REG 0x15dc
+#define MRS0_CMD 0x3
+#define MRS1_CMD 0x4
+#define MRS2_CMD 0x8
+#define MRS3_CMD 0x9
+
+
+#define DRAM_PINS_MUX_REG 0x19d4
+#define CTRL_PINS_MUX_OFFS 0
+#define CTRL_PINS_MUX_MASK 0x3
+enum {
+ DUNIT_DDR3_ON_BOARD,
+ DUNIT_DDR3_DIMM,
+ DUNIT_DDR4_ON_BOARD,
+ DUNIT_DDR4_DIMM
+};
+
+/* ddr phy registers */
+#define WL_PHY_BASE 0x0
+#define WL_PHY_REG(cs) (WL_PHY_BASE + (cs) * 0x4)
+#define WR_LVL_PH_SEL_OFFS 6
+#define WR_LVL_PH_SEL_MASK 0x7
+#define WR_LVL_PH_SEL_PHASE1 1
+#define WR_LVL_REF_DLY_OFFS 0
+#define WR_LVL_REF_DLY_MASK 0x1f
+#define CTRL_CENTER_DLY_OFFS 10
+#define CTRL_CENTER_DLY_MASK 0x1f
+#define CTRL_CENTER_DLY_INV_OFFS 15
+#define CTRL_CENTER_DLY_INV_MASK 0x1
+
+#define CTX_PHY_BASE 0x1
+#define CTX_PHY_REG(cs) (CTX_PHY_BASE + (cs) * 0x4)
+
+#define RL_PHY_BASE 0x2
+#define RL_PHY_REG(cs) (RL_PHY_BASE + (cs) * 0x4)
+#define RL_REF_DLY_OFFS 0
+#define RL_REF_DLY_MASK 0x1f
+#define RL_PH_SEL_OFFS 6
+#define RL_PH_SEL_MASK 0x7
+
+#define CRX_PHY_BASE 0x3
+#define CRX_PHY_REG(cs) (CRX_PHY_BASE + (cs) * 0x4)
+
+#define PHY_CTRL_PHY_REG 0x90
+#define INV_PAD0_OFFS 2
+#define INV_PAD1_OFFS 3
+#define INV_PAD2_OFFS 4
+#define INV_PAD3_OFFS 5
+#define INV_PAD4_OFFS 6
+#define INV_PAD5_OFFS 7
+#define INV_PAD6_OFFS 8
+#define INV_PAD7_OFFS 9
+#define INV_PAD8_OFFS 10
+#define INV_PAD9_OFFS 11
+#define INV_PAD10_OFFS 12
+#define INV_PAD_MASK 0x1
+#define INVERT_PAD 1
+
+#define ADLL_CFG0_PHY_REG 0x92
+#define ADLL_CFG1_PHY_REG 0x93
+#define ADLL_CFG2_PHY_REG 0x94
+#define CMOS_CONFIG_PHY_REG 0xa2
+#define PAD_ZRI_CAL_PHY_REG 0xa4
+#define PAD_ODT_CAL_PHY_REG 0xa6
+#define PAD_CFG_PHY_REG 0xa8
+#define PAD_PRE_DISABLE_PHY_REG 0xa9
+#define TEST_ADLL_PHY_REG 0xbf
+
+#define VREF_PHY_BASE 0xd0
+#define VREF_PHY_REG(cs, bit) (VREF_PHY_BASE + (cs) * 12 + bit)
+enum {
+ DQSP_PAD = 4,
+ DQSN_PAD
+};
+
+#define VREF_BCAST_PHY_BASE 0xdb
+#define VREF_BCAST_PHY_REG(cs) (VREF_BCAST_PHY_BASE + (cs) * 12)
+
+#define PBS_TX_PHY_BASE 0x10
+#define PBS_TX_PHY_REG(cs, bit) (PBS_TX_PHY_BASE + (cs) * 0x10 + (bit))
+
+#define PBS_TX_BCAST_PHY_BASE 0x1f
+#define PBS_TX_BCAST_PHY_REG(cs) (PBS_TX_BCAST_PHY_BASE + (cs) * 0x10)
+
+#define PBS_RX_PHY_BASE 0x50
+#define PBS_RX_PHY_REG(cs, bit) (PBS_RX_PHY_BASE + (cs) * 0x10 + (bit))
+
+#define PBS_RX_BCAST_PHY_BASE 0x5f
+#define PBS_RX_BCAST_PHY_REG(cs) (PBS_RX_BCAST_PHY_BASE + (cs) * 0x10)
+
+#define RESULT_PHY_REG 0xc0
+#define RESULT_PHY_RX_OFFS 5
+#define RESULT_PHY_TX_OFFS 0
+
+
+#endif /* _MV_DDR_REGS_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.c b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.c
new file mode 100644
index 000000000..04dbfe94d
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.c
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "mv_ddr_spd.h"
+
+#define MV_DDR_SPD_DATA_MTB 125 /* medium timebase, ps */
+#define MV_DDR_SPD_DATA_FTB 1 /* fine timebase, ps */
+#define MV_DDR_SPD_MSB_OFFS 8 /* most significant byte offset, bits */
+
+#define MV_DDR_SPD_SUPPORTED_CLS_NUM 30
+
+static unsigned int mv_ddr_spd_supported_cls[MV_DDR_SPD_SUPPORTED_CLS_NUM];
+
+int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data)
+{
+ unsigned int byte, bit, start_cl;
+
+ start_cl = (spd_data->all_bytes[23] & 0x8) ? 23 : 7;
+
+ for (byte = 20; byte < 23; byte++) {
+ for (bit = 0; bit < 8; bit++) {
+ if (spd_data->all_bytes[byte] & (1 << bit))
+ mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit;
+ else
+ mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0;
+ }
+ }
+
+ for (byte = 23, bit = 0; bit < 6; bit++) {
+ if (spd_data->all_bytes[byte] & (1 << bit))
+ mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit;
+ else
+ mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0;
+ }
+
+ return 0;
+}
+
+unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl)
+{
+ unsigned int supported_cl;
+ int i = 0;
+
+ while (i < MV_DDR_SPD_SUPPORTED_CLS_NUM &&
+ mv_ddr_spd_supported_cls[i] < cl)
+ i++;
+
+ if (i < MV_DDR_SPD_SUPPORTED_CLS_NUM)
+ supported_cl = mv_ddr_spd_supported_cls[i];
+ else
+ supported_cl = 0;
+
+ return supported_cl;
+}
+
+int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[])
+{
+ int calc_val;
+
+ /* t ck avg min, ps */
+ calc_val = spd_data->byte_fields.byte_18 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_125 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TCK_AVG_MIN] = calc_val;
+
+ /* t aa min, ps */
+ calc_val = spd_data->byte_fields.byte_24 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_123 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TAA_MIN] = calc_val;
+
+ /* t rfc1 min, ps */
+ timing_data[MV_DDR_TRFC1_MIN] = (spd_data->byte_fields.byte_30 +
+ (spd_data->byte_fields.byte_31 << MV_DDR_SPD_MSB_OFFS)) * MV_DDR_SPD_DATA_MTB;
+
+ /* t wr min, ps */
+ timing_data[MV_DDR_TWR_MIN] = (spd_data->byte_fields.byte_42 +
+ (spd_data->byte_fields.byte_41.bit_fields.t_wr_min_msn << MV_DDR_SPD_MSB_OFFS)) *
+ MV_DDR_SPD_DATA_MTB;
+
+ /* t rcd min, ps */
+ calc_val = spd_data->byte_fields.byte_25 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_122 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TRCD_MIN] = calc_val;
+
+ /* t rp min, ps */
+ calc_val = spd_data->byte_fields.byte_26 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_121 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TRP_MIN] = calc_val;
+
+ /* t rc min, ps */
+ calc_val = (spd_data->byte_fields.byte_29 +
+ (spd_data->byte_fields.byte_27.bit_fields.t_rc_min_msn << MV_DDR_SPD_MSB_OFFS)) *
+ MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_120 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TRC_MIN] = calc_val;
+
+ /* t ras min, ps */
+ timing_data[MV_DDR_TRAS_MIN] = (spd_data->byte_fields.byte_28 +
+ (spd_data->byte_fields.byte_27.bit_fields.t_ras_min_msn << MV_DDR_SPD_MSB_OFFS)) *
+ MV_DDR_SPD_DATA_MTB;
+
+ /* t rrd s min, ps */
+ calc_val = spd_data->byte_fields.byte_38 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_119 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TRRD_S_MIN] = calc_val;
+
+ /* t rrd l min, ps */
+ calc_val = spd_data->byte_fields.byte_39 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_118 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TRRD_L_MIN] = calc_val;
+
+ /* t ccd l min, ps */
+ calc_val = spd_data->byte_fields.byte_40 * MV_DDR_SPD_DATA_MTB +
+ (signed char)spd_data->byte_fields.byte_117 * MV_DDR_SPD_DATA_FTB;
+ if (calc_val < 0)
+ return 1;
+ timing_data[MV_DDR_TCCD_L_MIN] = calc_val;
+
+ /* t faw min, ps */
+ timing_data[MV_DDR_TFAW_MIN] = (spd_data->byte_fields.byte_37 +
+ (spd_data->byte_fields.byte_36.bit_fields.t_faw_min_msn << MV_DDR_SPD_MSB_OFFS)) *
+ MV_DDR_SPD_DATA_MTB;
+
+ /* t wtr s min, ps */
+ timing_data[MV_DDR_TWTR_S_MIN] = (spd_data->byte_fields.byte_44 +
+ (spd_data->byte_fields.byte_43.bit_fields.t_wtr_s_min_msn << MV_DDR_SPD_MSB_OFFS)) *
+ MV_DDR_SPD_DATA_MTB;
+
+ /* t wtr l min, ps */
+ timing_data[MV_DDR_TWTR_L_MIN] = (spd_data->byte_fields.byte_45 +
+ (spd_data->byte_fields.byte_43.bit_fields.t_wtr_l_min_msn << MV_DDR_SPD_MSB_OFFS)) *
+ MV_DDR_SPD_DATA_MTB;
+
+ return 0;
+}
+
+enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char dev_width = spd_data->byte_fields.byte_12.bit_fields.device_width;
+ enum mv_ddr_dev_width ret_val;
+
+ switch (dev_width) {
+ case 0x00:
+ ret_val = MV_DDR_DEV_WIDTH_4BIT;
+ break;
+ case 0x01:
+ ret_val = MV_DDR_DEV_WIDTH_8BIT;
+ break;
+ case 0x02:
+ ret_val = MV_DDR_DEV_WIDTH_16BIT;
+ break;
+ case 0x03:
+ ret_val = MV_DDR_DEV_WIDTH_32BIT;
+ break;
+ default:
+ ret_val = MV_DDR_DEV_WIDTH_LAST;
+ }
+
+ return ret_val;
+}
+
+enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char die_cap = spd_data->byte_fields.byte_4.bit_fields.die_capacity;
+ enum mv_ddr_die_capacity ret_val;
+
+ switch (die_cap) {
+ case 0x00:
+ ret_val = MV_DDR_DIE_CAP_256MBIT;
+ break;
+ case 0x01:
+ ret_val = MV_DDR_DIE_CAP_512MBIT;
+ break;
+ case 0x02:
+ ret_val = MV_DDR_DIE_CAP_1GBIT;
+ break;
+ case 0x03:
+ ret_val = MV_DDR_DIE_CAP_2GBIT;
+ break;
+ case 0x04:
+ ret_val = MV_DDR_DIE_CAP_4GBIT;
+ break;
+ case 0x05:
+ ret_val = MV_DDR_DIE_CAP_8GBIT;
+ break;
+ case 0x06:
+ ret_val = MV_DDR_DIE_CAP_16GBIT;
+ break;
+ case 0x07:
+ ret_val = MV_DDR_DIE_CAP_32GBIT;
+ break;
+ case 0x08:
+ ret_val = MV_DDR_DIE_CAP_12GBIT;
+ break;
+ case 0x09:
+ ret_val = MV_DDR_DIE_CAP_24GBIT;
+ break;
+ default:
+ ret_val = MV_DDR_DIE_CAP_LAST;
+ }
+
+ return ret_val;
+}
+
+unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char mem_mirror = spd_data->byte_fields.byte_131.bit_fields.rank_1_mapping;
+
+ return mem_mirror;
+}
+
+enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char pri_bus_width = spd_data->byte_fields.byte_13.bit_fields.primary_bus_width;
+ enum mv_ddr_pri_bus_width ret_val;
+
+ switch (pri_bus_width) {
+ case 0x00:
+ ret_val = MV_DDR_PRI_BUS_WIDTH_8;
+ break;
+ case 0x01:
+ ret_val = MV_DDR_PRI_BUS_WIDTH_16;
+ break;
+ case 0x02:
+ ret_val = MV_DDR_PRI_BUS_WIDTH_32;
+ break;
+ case 0x03:
+ ret_val = MV_DDR_PRI_BUS_WIDTH_64;
+ break;
+ default:
+ ret_val = MV_DDR_PRI_BUS_WIDTH_LAST;
+ }
+
+ return ret_val;
+}
+
+enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char bus_width_ext = spd_data->byte_fields.byte_13.bit_fields.bus_width_ext;
+ enum mv_ddr_bus_width_ext ret_val;
+
+ switch (bus_width_ext) {
+ case 0x00:
+ ret_val = MV_DDR_BUS_WIDTH_EXT_0;
+ break;
+ case 0x01:
+ ret_val = MV_DDR_BUS_WIDTH_EXT_8;
+ break;
+ default:
+ ret_val = MV_DDR_BUS_WIDTH_EXT_LAST;
+ }
+
+ return ret_val;
+}
+
+static enum mv_ddr_pkg_rank mv_ddr_spd_pkg_rank_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char pkg_rank = spd_data->byte_fields.byte_12.bit_fields.dimm_pkg_ranks_num;
+ enum mv_ddr_pkg_rank ret_val;
+
+ switch (pkg_rank) {
+ case 0x00:
+ ret_val = MV_DDR_PKG_RANK_1;
+ break;
+ case 0x01:
+ ret_val = MV_DDR_PKG_RANK_2;
+ break;
+ case 0x02:
+ ret_val = MV_DDR_PKG_RANK_3;
+ break;
+ case 0x03:
+ ret_val = MV_DDR_PKG_RANK_4;
+ break;
+ case 0x04:
+ ret_val = MV_DDR_PKG_RANK_5;
+ break;
+ case 0x05:
+ ret_val = MV_DDR_PKG_RANK_6;
+ break;
+ case 0x06:
+ ret_val = MV_DDR_PKG_RANK_7;
+ break;
+ case 0x07:
+ ret_val = MV_DDR_PKG_RANK_8;
+ break;
+ default:
+ ret_val = MV_DDR_PKG_RANK_LAST;
+ }
+
+ return ret_val;
+}
+
+static enum mv_ddr_die_count mv_ddr_spd_die_count_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char die_count = spd_data->byte_fields.byte_6.bit_fields.die_count;
+ enum mv_ddr_die_count ret_val;
+
+ switch (die_count) {
+ case 0x00:
+ ret_val = MV_DDR_DIE_CNT_1;
+ break;
+ case 0x01:
+ ret_val = MV_DDR_DIE_CNT_2;
+ break;
+ case 0x02:
+ ret_val = MV_DDR_DIE_CNT_3;
+ break;
+ case 0x03:
+ ret_val = MV_DDR_DIE_CNT_4;
+ break;
+ case 0x04:
+ ret_val = MV_DDR_DIE_CNT_5;
+ break;
+ case 0x05:
+ ret_val = MV_DDR_DIE_CNT_6;
+ break;
+ case 0x06:
+ ret_val = MV_DDR_DIE_CNT_7;
+ break;
+ case 0x07:
+ ret_val = MV_DDR_DIE_CNT_8;
+ break;
+ default:
+ ret_val = MV_DDR_DIE_CNT_LAST;
+ }
+
+ return ret_val;
+}
+
+unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char cs_bit_mask = 0x0;
+ enum mv_ddr_pkg_rank pkg_rank = mv_ddr_spd_pkg_rank_get(spd_data);
+ enum mv_ddr_die_count die_cnt = mv_ddr_spd_die_count_get(spd_data);
+
+ if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_1)
+ cs_bit_mask = 0x1;
+ else if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_2)
+ cs_bit_mask = 0x3;
+ else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_1)
+ cs_bit_mask = 0x3;
+ else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_2)
+ cs_bit_mask = 0xf;
+
+ return cs_bit_mask;
+}
+
+unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char dev_type = spd_data->byte_fields.byte_2;
+
+ return dev_type;
+}
+
+unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data)
+{
+ unsigned char module_type = spd_data->byte_fields.byte_3.bit_fields.module_type;
+
+ return module_type;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.h
new file mode 100644
index 000000000..6043f11b2
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_spd.h
@@ -0,0 +1,295 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR_SPD_H
+#define _MV_DDR_SPD_H
+
+#include "mv_ddr_topology.h"
+
+/*
+ * Based on JEDEC Standard No. 21-C, 4.1.2.L-4:
+ * Serial Presence Detect (SPD) for DDR4 SDRAM Modules
+ */
+
+/* block 0: base configuration and dram parameters */
+#define MV_DDR_SPD_DATA_BLOCK0_SIZE 128
+/* block 1: module specific parameters sub-block */
+#define MV_DDR_SPD_DATA_BLOCK1M_SIZE 64
+/* block 1: hybrid memory parameters sub-block */
+#define MV_DDR_SPD_DATA_BLOCK1H_SIZE 64
+/* block 2: extended function parameter block */
+#define MV_DDR_SPD_DATA_BLOCK2E_SIZE 64
+/* block 2: manufacturing information */
+#define MV_DDR_SPD_DATA_BLOCK2M_SIZE 64
+/* block 3: end user programmable */
+#define MV_DDR_SPD_DATA_BLOCK3_SIZE 128
+
+#define MV_DDR_SPD_DEV_TYPE_DDR4 0xc
+#define MV_DDR_SPD_MODULE_TYPE_UDIMM 0x2
+#define MV_DDR_SPD_MODULE_TYPE_SO_DIMM 0x3
+#define MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM 0x6
+#define MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM 0x9
+#define MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM 0xc
+#define MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM 0xd
+
+/*
+ * TODO: For now, the struct contains block 0 & block 1 with module specific
+ * parameters for unbuffered memory module types only.
+ */
+union mv_ddr_spd_data {
+ unsigned char all_bytes[MV_DDR_SPD_DATA_BLOCK0_SIZE +
+ MV_DDR_SPD_DATA_BLOCK1M_SIZE +
+ MV_DDR_SPD_DATA_BLOCK1H_SIZE +
+ MV_DDR_SPD_DATA_BLOCK2E_SIZE +
+ MV_DDR_SPD_DATA_BLOCK2M_SIZE];
+ struct {
+ /* block 0 */
+ union { /* num of bytes used/num of bytes in spd device/crc coverage */
+ unsigned char all_bits;
+ struct {
+ unsigned char spd_bytes_used:4,
+ spd_bytes_total:3,
+ reserved:1;
+ } bit_fields;
+ } byte_0;
+ union { /* spd revision */
+ unsigned char all_bits;
+ struct {
+ unsigned char addtions_level:4,
+ encoding_level:4;
+ } bit_fields;
+ } byte_1;
+ unsigned char byte_2; /* key_byte/dram device type */
+ union { /* key byte/module type */
+ unsigned char all_bits;
+ struct {
+ unsigned char module_type:4,
+ hybrid_media:3,
+ hybrid:1;
+ } bit_fields;
+ } byte_3;
+ union { /* sdram density & banks */
+ unsigned char all_bits;
+ struct {
+ unsigned char die_capacity:4,
+ bank_address:2,
+ bank_group:2;
+ } bit_fields;
+ } byte_4;
+ union { /* sdram addressing */
+ unsigned char all_bits;
+ struct {
+ unsigned char col_address:3,
+ row_address:3,
+ reserved:2;
+ } bit_fields;
+ } byte_5;
+ union { /* sdram package type */
+ unsigned char all_bits;
+ struct {
+ unsigned char signal_loading:2,
+ reserved:2,
+ die_count:3,
+ sdram_package_type:1;
+ } bit_fields;
+ } byte_6;
+ union { /* sdram optional features */
+ unsigned char all_bits;
+ struct {
+ unsigned char mac:4, /* max activate count */
+ t_maw:2, /* max activate window */
+ reserved:2; /* all 0s */
+ } bit_fields;
+ } byte_7;
+ unsigned char byte_8; /* sdram thermal & refresh options; reserved; 0x00 */
+ union { /* other sdram optional features */
+ unsigned char all_bits;
+ struct {
+ unsigned char reserved:5, /* all 0s */
+ soft_ppr:1,
+ ppr:2; /* post package repair */
+ } bit_fields;
+ } byte_9;
+ union { /* secondary sdram package type */
+ unsigned char all_bits;
+ struct {
+ unsigned char signal_loading:2,
+ density_ratio:2, /* dram density ratio */
+ die_count:3,
+ sdram_package_type:1;
+ } bit_fields;
+ } byte_10;
+ union { /* module nominal voltage, vdd */
+ unsigned char all_bits;
+ struct {
+ unsigned char operable:1,
+ endurant:1,
+ reserved:5; /* all 0s */
+ } bit_fields;
+ } byte_11;
+ union { /* module organization*/
+ unsigned char all_bits;
+ struct {
+ unsigned char device_width:3,
+ dimm_pkg_ranks_num:3, /* package ranks per dimm number */
+ rank_mix:1,
+ reserved:1; /* 0 */
+ } bit_fields;
+ } byte_12;
+ union { /* module memory bus width */
+ unsigned char all_bits;
+ struct {
+ unsigned char primary_bus_width:3, /* in bits */
+ bus_width_ext:2, /* in bits */
+ reserved:3; /* all 0s */
+ } bit_fields;
+ } byte_13;
+ union { /* module thernal sensor */
+ unsigned char all_bits;
+ struct {
+ unsigned char reserved:7,
+ thermal_sensor:1;
+ } bit_fields;
+ } byte_14;
+ union { /* extended module type */
+ unsigned char all_bits;
+ struct {
+ unsigned char ext_base_module_type:4,
+ reserved:4; /* all 0s */
+ } bit_fields;
+ } byte_15;
+ unsigned char byte_16; /* reserved; 0x00 */
+ union { /* timebases */
+ unsigned char all_bits;
+ struct {
+ unsigned char ftb:2, /* fine timebase */
+ mtb:2, /* medium timebase */
+ reserved:4; /* all 0s */
+ } bit_fields;
+ } byte_17;
+ unsigned char byte_18; /* sdram min cycle time (t ck avg min), mtb */
+ unsigned char byte_19; /* sdram max cycle time (t ck avg max), mtb */
+ unsigned char byte_20; /* cas latencies supported, first byte */
+ unsigned char byte_21; /* cas latencies supported, second byte */
+ unsigned char byte_22; /* cas latencies supported, third byte */
+ unsigned char byte_23; /* cas latencies supported, fourth byte */
+ unsigned char byte_24; /* min cas latency time (t aa min), mtb */
+ unsigned char byte_25; /* min ras to cas delay time (t rcd min), mtb */
+ unsigned char byte_26; /* min row precharge delay time (t rp min), mtb */
+ union { /* upper nibbles for t ras min & t rc min */
+ unsigned char all_bits;
+ struct {
+ unsigned char t_ras_min_msn:4, /* t ras min most significant nibble */
+ t_rc_min_msn:4; /* t rc min most significant nibble */
+ } bit_fields;
+ } byte_27;
+ unsigned char byte_28; /* min active to precharge delay time (t ras min), l-s-byte, mtb */
+ unsigned char byte_29; /* min active to active/refresh delay time (t rc min), l-s-byte, mtb */
+ unsigned char byte_30; /* min refresh recovery delay time (t rfc1 min), l-s-byte, mtb */
+ unsigned char byte_31; /* min refresh recovery delay time (t rfc1 min), m-s-byte, mtb */
+ unsigned char byte_32; /* min refresh recovery delay time (t rfc2 min), l-s-byte, mtb */
+ unsigned char byte_33; /* min refresh recovery delay time (t rfc2 min), m-s-byte, mtb */
+ unsigned char byte_34; /* min refresh recovery delay time (t rfc4 min), l-s-byte, mtb */
+ unsigned char byte_35; /* min refresh recovery delay time (t rfc4 min), m-s-byte, mtb */
+ union { /* upper nibble for t faw */
+ unsigned char all_bits;
+ struct {
+ unsigned char t_faw_min_msn:4, /* t faw min most significant nibble */
+ reserved:4;
+ } bit_fields;
+ } byte_36;
+ unsigned char byte_37; /* min four activate window delay time (t faw min), l-s-byte, mtb */
+ /* byte 38: min activate to activate delay time (t rrd_s min), diff bank group, mtb */
+ unsigned char byte_38;
+ /* byte 39: min activate to activate delay time (t rrd_l min), same bank group, mtb */
+ unsigned char byte_39;
+ unsigned char byte_40; /* min cas to cas delay time (t ccd_l min), same bank group, mtb */
+ union { /* upper nibble for t wr min */
+ unsigned char all_bits;
+ struct {
+ unsigned char t_wr_min_msn:4, /* t wr min most significant nibble */
+ reserved:4;
+ } bit_fields;
+ } byte_41;
+ unsigned char byte_42; /* min write recovery time (t wr min) */
+ union { /* upper nibbles for t wtr min */
+ unsigned char all_bits;
+ struct {
+ unsigned char t_wtr_s_min_msn:4, /* t wtr s min most significant nibble */
+ t_wtr_l_min_msn:4; /* t wtr l min most significant nibble */
+ } bit_fields;
+ } byte_43;
+ unsigned char byte_44; /* min write to read time (t wtr s min), diff bank group, mtb */
+ unsigned char byte_45; /* min write to read time (t wtr l min), same bank group, mtb */
+ unsigned char bytes_46_59[14]; /* reserved; all 0s */
+ unsigned char bytes_60_77[18]; /* TODO: connector to sdram bit mapping */
+ unsigned char bytes_78_116[39]; /* reserved; all 0s */
+ /* fine offset for min cas to cas delay time (t ccd_l min), same bank group, ftb */
+ unsigned char byte_117;
+ /* fine offset for min activate to activate delay time (t rrd_l min), same bank group, ftb */
+ unsigned char byte_118;
+ /* fine offset for min activate to activate delay time (t rrd_s min), diff bank group, ftb */
+ unsigned char byte_119;
+ /* fine offset for min active to active/refresh delay time (t rc min), ftb */
+ unsigned char byte_120;
+ unsigned char byte_121; /* fine offset for min row precharge delay time (t rp min), ftb */
+ unsigned char byte_122; /* fine offset for min ras to cas delay time (t rcd min), ftb */
+ unsigned char byte_123; /* fine offset for min cas latency time (t aa min), ftb */
+ unsigned char byte_124; /* fine offset for sdram max cycle time (t ck avg max), ftb */
+ unsigned char byte_125; /* fine offset for sdram min cycle time (t ck avg min), ftb */
+ unsigned char byte_126; /* crc for base configuration section, l-s-byte */
+ unsigned char byte_127; /* crc for base configuration section, m-s-byte */
+ /*
+ * block 1: module specific parameters for unbuffered memory module types only
+ */
+ union { /* (unbuffered) raw card extension, module nominal height */
+ unsigned char all_bits;
+ struct {
+ unsigned char nom_height_max:5, /* in mm */
+ raw_cad_ext:3;
+ } bit_fields;
+ } byte_128;
+ union { /* (unbuffered) module maximum thickness */
+ unsigned char all_bits;
+ struct {
+ unsigned char front_thickness_max:4, /* in mm */
+ back_thickness_max:4; /* in mm */
+ } bit_fields;
+ } byte_129;
+ union { /* (unbuffered) reference raw card used */
+ unsigned char all_bits;
+ struct {
+ unsigned char ref_raw_card:5,
+ ref_raw_card_rev:2,
+ ref_raw_card_ext:1;
+ } bit_fields;
+ } byte_130;
+ union { /* (unbuffered) address mapping from edge connector to dram */
+ unsigned char all_bits;
+ struct {
+ unsigned char rank_1_mapping:1,
+ reserved:7;
+ } bit_fields;
+ } byte_131;
+ unsigned char bytes_132_191[60]; /* reserved; all 0s */
+ unsigned char bytes_192_255[MV_DDR_SPD_DATA_BLOCK1H_SIZE];
+ unsigned char bytes_256_319[MV_DDR_SPD_DATA_BLOCK2E_SIZE];
+ unsigned char bytes_320_383[MV_DDR_SPD_DATA_BLOCK2M_SIZE];
+ } byte_fields;
+};
+
+int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]);
+enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data);
+enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data);
+unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data);
+unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data);
+unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data);
+unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data);
+int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data);
+unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl);
+enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data);
+enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data);
+
+#endif /* _MV_DDR_SPD_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c
new file mode 100644
index 000000000..c9c6899e7
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "mv_ddr_regs.h"
+#include "mv_ddr_sys_env_lib.h"
+
+static u32 mv_ddr_board_id_get(void)
+{
+#if defined(CONFIG_TARGET_DB_88F6820_GP)
+ return DB_GP_68XX_ID;
+#else
+ /*
+ * Return 0 here for custom board as this should not be used
+ * for custom boards.
+ */
+ return 0;
+#endif
+}
+
+static u32 mv_ddr_board_id_index_get(u32 board_id)
+{
+ /*
+ * Marvell Boards use 0x10 as base for Board ID:
+ * mask MSB to receive index for board ID
+ */
+ return board_id & (MARVELL_BOARD_ID_MASK - 1);
+}
+
+/*
+ * read gpio input for suspend-wakeup indication
+ * return indicating suspend wakeup status:
+ * 0 - not supported,
+ * 1 - supported: read magic word detect wakeup,
+ * 2 - detected wakeup from gpio
+ */
+enum suspend_wakeup_status mv_ddr_sys_env_suspend_wakeup_check(void)
+{
+ u32 reg, board_id_index, gpio;
+ struct board_wakeup_gpio board_gpio[] = MV_BOARD_WAKEUP_GPIO_INFO;
+
+ board_id_index = mv_ddr_board_id_index_get(mv_ddr_board_id_get());
+ if (!(sizeof(board_gpio) / sizeof(struct board_wakeup_gpio) >
+ board_id_index)) {
+ printf("\n_failed loading Suspend-Wakeup information (invalid board ID)\n");
+ return SUSPEND_WAKEUP_DISABLED;
+ }
+
+ /*
+ * - Detect if Suspend-Wakeup is supported on current board
+ * - Fetch the GPIO number for wakeup status input indication
+ */
+ if (board_gpio[board_id_index].gpio_num == -1) {
+ /* Suspend to RAM is not supported */
+ return SUSPEND_WAKEUP_DISABLED;
+ } else if (board_gpio[board_id_index].gpio_num == -2) {
+ /*
+ * Suspend to RAM is supported but GPIO indication is
+ * not implemented - Skip
+ */
+ return SUSPEND_WAKEUP_ENABLED;
+ } else {
+ gpio = board_gpio[board_id_index].gpio_num;
+ }
+
+ /* Initialize MPP for GPIO (set MPP = 0x0) */
+ reg = reg_read(MPP_CONTROL_REG(MPP_REG_NUM(gpio)));
+ /* reset MPP21 to 0x0, keep rest of MPP settings*/
+ reg &= ~MPP_MASK(gpio);
+ reg_write(MPP_CONTROL_REG(MPP_REG_NUM(gpio)), reg);
+
+ /* Initialize GPIO as input */
+ reg = reg_read(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)));
+ reg |= GPP_MASK(gpio);
+ reg_write(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)), reg);
+
+ /*
+ * Check GPP for input status from PIC: 0 - regular init,
+ * 1 - suspend wakeup
+ */
+ reg = reg_read(GPP_DATA_IN_REG(GPP_REG_NUM(gpio)));
+
+ /* if GPIO is ON: wakeup from S2RAM indication detected */
+ return (reg & GPP_MASK(gpio)) ? SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED :
+ SUSPEND_WAKEUP_DISABLED;
+}
+
+/*
+ * get bit mask of enabled cs
+ * return bit mask of enabled cs:
+ * 1 - only cs0 enabled,
+ * 3 - both cs0 and cs1 enabled
+ */
+u32 mv_ddr_sys_env_get_cs_ena_from_reg(void)
+{
+ return reg_read(DDR3_RANK_CTRL_REG) &
+ ((CS_EXIST_MASK << CS_EXIST_OFFS(0)) |
+ (CS_EXIST_MASK << CS_EXIST_OFFS(1)) |
+ (CS_EXIST_MASK << CS_EXIST_OFFS(2)) |
+ (CS_EXIST_MASK << CS_EXIST_OFFS(3)));
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h
new file mode 100644
index 000000000..10b0d45b3
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR_SYS_ENV_LIB_H
+#define _MV_DDR_SYS_ENV_LIB_H
+
+#include "ddr_ml_wrapper.h"
+
+/* device revision */
+#define DEV_ID_REG 0x18238
+#define DEV_VERSION_ID_REG 0x1823c
+#define REVISON_ID_OFFS 8
+#define REVISON_ID_MASK 0xf00
+
+#define MPP_CONTROL_REG(id) (0x18000 + (id * 4))
+#define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00)
+#define GPP_DATA_OUT_EN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x04)
+#define GPP_DATA_IN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x10)
+#define MV_GPP_REGS_BASE(unit) (0x18100 + ((unit) * 0x40))
+
+#define MPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 8)
+#define MPP_MASK(GPIO_NUM) (0xf << 4 * (GPIO_NUM - \
+ (MPP_REG_NUM(GPIO_NUM) * 8)));
+#define GPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 32)
+#define GPP_MASK(GPIO_NUM) (1 << GPIO_NUM % 32)
+
+/* device ID */
+/* Board ID numbers */
+#define MARVELL_BOARD_ID_MASK 0x10
+
+/* Customer boards for A38x */
+#define A38X_CUSTOMER_BOARD_ID_BASE 0x0
+#define A38X_CUSTOMER_BOARD_ID0 (A38X_CUSTOMER_BOARD_ID_BASE + 0)
+#define A38X_CUSTOMER_BOARD_ID1 (A38X_CUSTOMER_BOARD_ID_BASE + 1)
+#define A38X_MV_MAX_CUSTOMER_BOARD_ID (A38X_CUSTOMER_BOARD_ID_BASE + 2)
+#define A38X_MV_CUSTOMER_BOARD_NUM (A38X_MV_MAX_CUSTOMER_BOARD_ID - \
+ A38X_CUSTOMER_BOARD_ID_BASE)
+
+/* Marvell boards for A38x */
+#define A38X_MARVELL_BOARD_ID_BASE 0x10
+#define RD_NAS_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 0)
+#define DB_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 1)
+#define RD_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 2)
+#define DB_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 3)
+#define DB_GP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 4)
+#define DB_BP_6821_ID (A38X_MARVELL_BOARD_ID_BASE + 5)
+#define DB_AMC_6820_ID (A38X_MARVELL_BOARD_ID_BASE + 6)
+#define A38X_MV_MAX_MARVELL_BOARD_ID (A38X_MARVELL_BOARD_ID_BASE + 7)
+#define A38X_MV_MARVELL_BOARD_NUM (A38X_MV_MAX_MARVELL_BOARD_ID - \
+ A38X_MARVELL_BOARD_ID_BASE)
+
+/* Marvell boards for A39x */
+#define A39X_MARVELL_BOARD_ID_BASE 0x30
+#define A39X_DB_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 0)
+#define A39X_RD_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 1)
+#define A39X_MV_MAX_MARVELL_BOARD_ID (A39X_MARVELL_BOARD_ID_BASE + 2)
+#define A39X_MV_MARVELL_BOARD_NUM (A39X_MV_MAX_MARVELL_BOARD_ID - \
+ A39X_MARVELL_BOARD_ID_BASE)
+
+struct board_wakeup_gpio {
+ u32 board_id;
+ int gpio_num;
+};
+
+enum suspend_wakeup_status {
+ SUSPEND_WAKEUP_DISABLED,
+ SUSPEND_WAKEUP_ENABLED,
+ SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED,
+};
+
+/*
+ * GPIO status indication for Suspend Wakeup:
+ * If suspend to RAM is supported and GPIO inidcation is implemented,
+ * set the gpio number
+ * If suspend to RAM is supported but GPIO indication is not implemented
+ * set '-2'
+ * If suspend to RAM is not supported set '-1'
+ */
+
+#define MV_BOARD_WAKEUP_GPIO_INFO { \
+ {RD_NAS_68XX_ID, -2 }, \
+ {DB_68XX_ID, -1 }, \
+ {RD_AP_68XX_ID, -2 }, \
+ {DB_AP_68XX_ID, -2 }, \
+ {DB_GP_68XX_ID, -2 }, \
+ {DB_BP_6821_ID, -2 }, \
+ {DB_AMC_6820_ID, -2 }, \
+};
+
+enum suspend_wakeup_status mv_ddr_sys_env_suspend_wakeup_check(void);
+u32 mv_ddr_sys_env_get_cs_ena_from_reg(void);
+
+#endif /* _MV_DDR_SYS_ENV_LIB_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.c b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.c
new file mode 100644
index 000000000..2db6283c2
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+#include "ddr_ml_wrapper.h"
+#include "mv_ddr_plat.h"
+
+#include "mv_ddr_topology.h"
+#include "mv_ddr_common.h"
+#include "mv_ddr_spd.h"
+#include "ddr_topology_def.h"
+#include "ddr3_training_ip_db.h"
+#include "ddr3_training_ip.h"
+#include "mv_ddr_training_db.h"
+
+unsigned int mv_ddr_cl_calc(unsigned int taa_min, unsigned int tclk)
+{
+ unsigned int cl = ceil_div(taa_min, tclk);
+
+ return mv_ddr_spd_supported_cl_get(cl);
+
+}
+
+unsigned int mv_ddr_cwl_calc(unsigned int tclk)
+{
+ unsigned int cwl;
+
+ if (tclk >= 1250)
+ cwl = 9;
+ else if (tclk >= 1071)
+ cwl = 10;
+ else if (tclk >= 938)
+ cwl = 11;
+ else if (tclk >= 833)
+ cwl = 12;
+ else if (tclk >= 750)
+ cwl = 14;
+ else if (tclk >= 625)
+ cwl = 16;
+ else
+ cwl = 0;
+
+ return cwl;
+}
+
+int mv_ddr_topology_map_update(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ struct if_params *iface_params = &(tm->interface_params[0]);
+ unsigned int octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ enum mv_ddr_speed_bin speed_bin_index;
+ enum mv_ddr_freq freq = MV_DDR_FREQ_LAST;
+ unsigned int tclk;
+ unsigned char val = 0;
+ int i;
+
+ if (iface_params->memory_freq == MV_DDR_FREQ_SAR)
+ iface_params->memory_freq = mv_ddr_init_freq_get();
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ /* check dram device type */
+ val = mv_ddr_spd_dev_type_get(&tm->spd_data);
+ if (val != MV_DDR_SPD_DEV_TYPE_DDR4) {
+ printf("mv_ddr: unsupported dram device type found\n");
+ return -1;
+ }
+
+ /* update topology map with timing data */
+ if (mv_ddr_spd_timing_calc(&tm->spd_data, tm->timing_data) > 0) {
+ printf("mv_ddr: negative timing data found\n");
+ return -1;
+ }
+
+ /* update device width in topology map */
+ iface_params->bus_width = mv_ddr_spd_dev_width_get(&tm->spd_data);
+
+ /* update die capacity in topology map */
+ iface_params->memory_size = mv_ddr_spd_die_capacity_get(&tm->spd_data);
+
+ /* update bus bit mask in topology map */
+ tm->bus_act_mask = mv_ddr_bus_bit_mask_get();
+
+ /* update cs bit mask in topology map */
+ val = mv_ddr_spd_cs_bit_mask_get(&tm->spd_data);
+ for (i = 0; i < octets_per_if_num; i++)
+ iface_params->as_bus_params[i].cs_bitmask = val;
+
+ /* check dram module type */
+ val = mv_ddr_spd_module_type_get(&tm->spd_data);
+ switch (val) {
+ case MV_DDR_SPD_MODULE_TYPE_UDIMM:
+ case MV_DDR_SPD_MODULE_TYPE_SO_DIMM:
+ case MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM:
+ case MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM:
+ case MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM:
+ case MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM:
+ break;
+ default:
+ printf("mv_ddr: unsupported dram module type found\n");
+ return -1;
+ }
+
+ /* update mirror bit mask in topology map */
+ val = mv_ddr_spd_mem_mirror_get(&tm->spd_data);
+ for (i = 0; i < octets_per_if_num; i++)
+ iface_params->as_bus_params[i].mirror_enable_bitmask = val << 1;
+
+ tclk = 1000000 / mv_ddr_freq_get(iface_params->memory_freq);
+ /* update cas write latency (cwl) */
+ val = mv_ddr_cwl_calc(tclk);
+ if (val == 0) {
+ printf("mv_ddr: unsupported cas write latency value found\n");
+ return -1;
+ }
+ iface_params->cas_wl = val;
+
+ /* update cas latency (cl) */
+ mv_ddr_spd_supported_cls_calc(&tm->spd_data);
+ val = mv_ddr_cl_calc(tm->timing_data[MV_DDR_TAA_MIN], tclk);
+ if (val == 0) {
+ printf("mv_ddr: unsupported cas latency value found\n");
+ return -1;
+ }
+ iface_params->cas_l = val;
+ } else if (tm->cfg_src == MV_DDR_CFG_DEFAULT) {
+ /* set cas and cas-write latencies per speed bin, if they unset */
+ speed_bin_index = iface_params->speed_bin_index;
+ freq = iface_params->memory_freq;
+
+ if (tm->twin_die_combined == COMBINED) {
+ iface_params->bus_width = MV_DDR_DEV_WIDTH_8BIT;
+ iface_params->memory_size -= 1;
+ }
+
+ if (iface_params->cas_l == 0)
+ iface_params->cas_l = mv_ddr_cl_val_get(speed_bin_index, freq);
+
+ if (iface_params->cas_wl == 0)
+ iface_params->cas_wl = mv_ddr_cwl_val_get(speed_bin_index, freq);
+ }
+
+ return 0;
+}
+
+unsigned short mv_ddr_bus_bit_mask_get(void)
+{
+ unsigned short pri_and_ext_bus_width = 0x0;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ if (tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK)
+ tm->spd_data.byte_fields.byte_13.bit_fields.primary_bus_width = MV_DDR_PRI_BUS_WIDTH_32;
+
+ enum mv_ddr_pri_bus_width pri_bus_width = mv_ddr_spd_pri_bus_width_get(&tm->spd_data);
+ enum mv_ddr_bus_width_ext bus_width_ext = mv_ddr_spd_bus_width_ext_get(&tm->spd_data);
+
+ switch (pri_bus_width) {
+ case MV_DDR_PRI_BUS_WIDTH_16:
+ pri_and_ext_bus_width = BUS_MASK_16BIT;
+ break;
+ case MV_DDR_PRI_BUS_WIDTH_32: /*each bit represents byte, so 0xf-is means 4 bytes-32 bit*/
+ pri_and_ext_bus_width = BUS_MASK_32BIT;
+ break;
+ case MV_DDR_PRI_BUS_WIDTH_64:
+ pri_and_ext_bus_width = MV_DDR_64BIT_BUS_MASK;
+ break;
+ default:
+ pri_and_ext_bus_width = 0x0;
+ }
+
+ if (bus_width_ext == MV_DDR_BUS_WIDTH_EXT_8)
+ pri_and_ext_bus_width |= 1 << (octets_per_if_num - 1);
+ }
+
+ return pri_and_ext_bus_width;
+}
+
+unsigned int mv_ddr_if_bus_width_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int bus_width;
+
+ switch (tm->bus_act_mask) {
+ case BUS_MASK_16BIT:
+ case BUS_MASK_16BIT_ECC:
+ case BUS_MASK_16BIT_ECC_PUP3:
+ bus_width = 16;
+ break;
+ case BUS_MASK_32BIT:
+ case BUS_MASK_32BIT_ECC:
+ case MV_DDR_32BIT_ECC_PUP8_BUS_MASK:
+ bus_width = 32;
+ break;
+ case MV_DDR_64BIT_BUS_MASK:
+ case MV_DDR_64BIT_ECC_PUP8_BUS_MASK:
+ bus_width = 64;
+ break;
+ default:
+ printf("mv_ddr: unsupported bus active mask parameter found\n");
+ bus_width = 0;
+ }
+
+ return bus_width;
+}
+
+unsigned int mv_ddr_cs_num_get(void)
+{
+ unsigned int cs_num = 0;
+ unsigned int cs, sphy;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ struct if_params *iface_params = &(tm->interface_params[0]);
+ unsigned int sphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+
+ for (sphy = 0; sphy < sphy_max; sphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sphy);
+ break;
+ }
+
+ for (cs = 0; cs < MAX_CS_NUM; cs++) {
+ VALIDATE_ACTIVE(iface_params->as_bus_params[sphy].cs_bitmask, cs);
+ cs_num++;
+ }
+
+ return cs_num;
+}
+
+int mv_ddr_is_ecc_ena(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) ||
+ DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask) ||
+ DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))
+ return 1;
+ else
+ return 0;
+}
+
+int mv_ddr_ck_delay_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (tm->ck_delay)
+ return tm->ck_delay;
+
+ return -1;
+}
+
+/* translate topology map definition to real memory size in bits */
+static unsigned int mem_size[] = {
+ ADDR_SIZE_512MB,
+ ADDR_SIZE_1GB,
+ ADDR_SIZE_2GB,
+ ADDR_SIZE_4GB,
+ ADDR_SIZE_8GB,
+ ADDR_SIZE_16GB
+ /* TODO: add capacity up to 256GB */
+};
+
+unsigned long long mv_ddr_mem_sz_per_cs_get(void)
+{
+ unsigned long long mem_sz_per_cs;
+ unsigned int i, sphys, sphys_per_dunit;
+ unsigned int sphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ struct if_params *iface_params = &(tm->interface_params[0]);
+
+ /* calc number of active subphys excl. ecc one */
+ for (i = 0, sphys = 0; i < sphy_max - 1; i++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, i);
+ sphys++;
+ }
+
+ /* calc number of subphys per ddr unit */
+ if (iface_params->bus_width == MV_DDR_DEV_WIDTH_8BIT)
+ sphys_per_dunit = MV_DDR_ONE_SPHY_PER_DUNIT;
+ else if (iface_params->bus_width == MV_DDR_DEV_WIDTH_16BIT)
+ sphys_per_dunit = MV_DDR_TWO_SPHY_PER_DUNIT;
+ else {
+ printf("mv_ddr: unsupported bus width type found\n");
+ return 0;
+ }
+
+ /* calc dram size per cs */
+ mem_sz_per_cs = (unsigned long long)mem_size[iface_params->memory_size] *
+ (unsigned long long)sphys /
+ (unsigned long long)sphys_per_dunit;
+ return mem_sz_per_cs;
+}
+
+unsigned long long mv_ddr_mem_sz_get(void)
+{
+ unsigned long long tot_mem_sz = 0;
+ unsigned long long mem_sz_per_cs = 0;
+ unsigned long long max_cs = mv_ddr_cs_num_get();
+
+ mem_sz_per_cs = mv_ddr_mem_sz_per_cs_get();
+ tot_mem_sz = max_cs * mem_sz_per_cs;
+
+ return tot_mem_sz;
+}
+
+unsigned int mv_ddr_rtt_nom_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int rtt_nom = tm->edata.mem_edata.rtt_nom;
+
+ if (rtt_nom >= MV_DDR_RTT_NOM_PARK_RZQ_LAST) {
+ printf("error: %s: unsupported rtt_nom parameter found\n", __func__);
+ rtt_nom = PARAM_UNDEFINED;
+ }
+
+ return rtt_nom;
+}
+
+unsigned int mv_ddr_rtt_park_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int cs_num = mv_ddr_cs_num_get();
+ unsigned int rtt_park = MV_DDR_RTT_NOM_PARK_RZQ_LAST;
+
+ if (cs_num > 0 && cs_num <= MAX_CS_NUM)
+ rtt_park = tm->edata.mem_edata.rtt_park[cs_num - 1];
+
+ if (rtt_park >= MV_DDR_RTT_NOM_PARK_RZQ_LAST) {
+ printf("error: %s: unsupported rtt_park parameter found\n", __func__);
+ rtt_park = PARAM_UNDEFINED;
+ }
+
+ return rtt_park;
+}
+
+unsigned int mv_ddr_rtt_wr_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int cs_num = mv_ddr_cs_num_get();
+ unsigned int rtt_wr = MV_DDR_RTT_WR_RZQ_LAST;
+
+ if (cs_num > 0 && cs_num <= MAX_CS_NUM)
+ rtt_wr = tm->edata.mem_edata.rtt_wr[cs_num - 1];
+
+ if (rtt_wr >= MV_DDR_RTT_WR_RZQ_LAST) {
+ printf("error: %s: unsupported rtt_wr parameter found\n", __func__);
+ rtt_wr = PARAM_UNDEFINED;
+ }
+
+ return rtt_wr;
+}
+
+unsigned int mv_ddr_dic_get(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int dic = tm->edata.mem_edata.dic;
+
+ if (dic >= MV_DDR_DIC_RZQ_LAST) {
+ printf("error: %s: unsupported dic parameter found\n", __func__);
+ dic = PARAM_UNDEFINED;
+ }
+
+ return dic;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.h
new file mode 100644
index 000000000..1cb69ad08
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_topology.h
@@ -0,0 +1,332 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR_TOPOLOGY_H
+#define _MV_DDR_TOPOLOGY_H
+
+#define MAX_CS_NUM 4
+
+enum mv_ddr_speed_bin {
+ SPEED_BIN_DDR_800D,
+ SPEED_BIN_DDR_800E,
+ SPEED_BIN_DDR_1066E,
+ SPEED_BIN_DDR_1066F,
+ SPEED_BIN_DDR_1066G,
+ SPEED_BIN_DDR_1333F,
+ SPEED_BIN_DDR_1333G,
+ SPEED_BIN_DDR_1333H,
+ SPEED_BIN_DDR_1333J,
+ SPEED_BIN_DDR_1600G,
+ SPEED_BIN_DDR_1600H,
+ SPEED_BIN_DDR_1600J,
+ SPEED_BIN_DDR_1600K,
+ SPEED_BIN_DDR_1866J,
+ SPEED_BIN_DDR_1866K,
+ SPEED_BIN_DDR_1866L,
+ SPEED_BIN_DDR_1866M,
+ SPEED_BIN_DDR_2133K,
+ SPEED_BIN_DDR_2133L,
+ SPEED_BIN_DDR_2133M,
+ SPEED_BIN_DDR_2133N,
+
+ SPEED_BIN_DDR_1333H_EXT,
+ SPEED_BIN_DDR_1600K_EXT,
+ SPEED_BIN_DDR_1866M_EXT
+};
+
+enum mv_ddr_freq {
+ MV_DDR_FREQ_LOW_FREQ,
+ MV_DDR_FREQ_400,
+ MV_DDR_FREQ_533,
+ MV_DDR_FREQ_667,
+ MV_DDR_FREQ_800,
+ MV_DDR_FREQ_933,
+ MV_DDR_FREQ_1066,
+ MV_DDR_FREQ_311,
+ MV_DDR_FREQ_333,
+ MV_DDR_FREQ_467,
+ MV_DDR_FREQ_850,
+ MV_DDR_FREQ_600,
+ MV_DDR_FREQ_300,
+ MV_DDR_FREQ_900,
+ MV_DDR_FREQ_360,
+ MV_DDR_FREQ_1000,
+ MV_DDR_FREQ_LAST,
+ MV_DDR_FREQ_SAR
+};
+
+enum mv_ddr_speed_bin_timing {
+ SPEED_BIN_TRCD,
+ SPEED_BIN_TRP,
+ SPEED_BIN_TRAS,
+ SPEED_BIN_TRC,
+ SPEED_BIN_TRRD1K,
+ SPEED_BIN_TRRD2K,
+ SPEED_BIN_TPD,
+ SPEED_BIN_TFAW1K,
+ SPEED_BIN_TFAW2K,
+ SPEED_BIN_TWTR,
+ SPEED_BIN_TRTP,
+ SPEED_BIN_TWR,
+ SPEED_BIN_TMOD,
+ SPEED_BIN_TXPDLL,
+ SPEED_BIN_TXSDLL
+};
+
+/* ddr bus masks */
+#define BUS_MASK_32BIT 0xf
+#define BUS_MASK_32BIT_ECC 0x1f
+#define BUS_MASK_16BIT 0x3
+#define BUS_MASK_16BIT_ECC 0x13
+#define BUS_MASK_16BIT_ECC_PUP3 0xb
+#define MV_DDR_64BIT_BUS_MASK 0xff
+#define MV_DDR_64BIT_ECC_PUP8_BUS_MASK 0x1ff
+#define MV_DDR_32BIT_ECC_PUP8_BUS_MASK 0x10f
+
+#define MV_DDR_CS_BITMASK_1CS 0x1
+#define MV_DDR_CS_BITMASK_2CS 0x3
+
+#define MV_DDR_ONE_SPHY_PER_DUNIT 1
+#define MV_DDR_TWO_SPHY_PER_DUNIT 2
+
+/* source of ddr configuration data */
+enum mv_ddr_cfg_src {
+ MV_DDR_CFG_DEFAULT, /* based on data in mv_ddr_topology_map structure */
+ MV_DDR_CFG_SPD, /* based on data in spd */
+ MV_DDR_CFG_USER, /* based on data from user */
+ MV_DDR_CFG_STATIC, /* based on data from user in register-value format */
+ MV_DDR_CFG_LAST
+};
+
+enum mv_ddr_temperature {
+ MV_DDR_TEMP_LOW,
+ MV_DDR_TEMP_NORMAL,
+ MV_DDR_TEMP_HIGH
+};
+
+enum mv_ddr_timing {
+ MV_DDR_TIM_DEFAULT,
+ MV_DDR_TIM_1T,
+ MV_DDR_TIM_2T
+};
+
+enum mv_ddr_timing_data {
+ MV_DDR_TCK_AVG_MIN, /* sdram min cycle time (t ck avg min) */
+ MV_DDR_TAA_MIN, /* min cas latency time (t aa min) */
+ MV_DDR_TRFC1_MIN, /* min refresh recovery delay time (t rfc1 min) */
+ MV_DDR_TWR_MIN, /* min write recovery time (t wr min) */
+ MV_DDR_TRCD_MIN, /* min ras to cas delay time (t rcd min) */
+ MV_DDR_TRP_MIN, /* min row precharge delay time (t rp min) */
+ MV_DDR_TRC_MIN, /* min active to active/refresh delay time (t rc min) */
+ MV_DDR_TRAS_MIN, /* min active to precharge delay time (t ras min) */
+ MV_DDR_TRRD_S_MIN, /* min activate to activate delay time (t rrd_s min), diff bank group */
+ MV_DDR_TRRD_L_MIN, /* min activate to activate delay time (t rrd_l min), same bank group */
+ MV_DDR_TCCD_L_MIN, /* min cas to cas delay time (t ccd_l min), same bank group */
+ MV_DDR_TFAW_MIN, /* min four activate window delay time (t faw min) */
+ MV_DDR_TWTR_S_MIN, /* min write to read time (t wtr s min), diff bank group */
+ MV_DDR_TWTR_L_MIN, /* min write to read time (t wtr l min), same bank group */
+ MV_DDR_TDATA_LAST
+};
+
+enum mv_ddr_electrical_data {
+ MV_DDR_CK_DLY,
+ MV_DDR_PHY_REG3,
+ MV_DDR_ZPRI_DATA,
+ MV_DDR_ZNRI_DATA,
+ MV_DDR_ZPRI_CTRL,
+ MV_DDR_ZNRI_CTRL,
+ MV_DDR_ZPODT_DATA,
+ MV_DDR_ZNODT_DATA,
+ MV_DDR_ZPODT_CTRL,
+ MV_DDR_ZNODT_CTRL,
+ MV_DDR_DIC,
+ MV_DDR_ODT_CFG,
+ MV_DDR_RTT_NOM,
+ MV_DDR_RTT_WR,
+ MV_DDR_RTT_PARK,
+ MV_DDR_EDATA_LAST
+};
+
+/* memory electrical configuration values */
+enum mv_ddr_rtt_nom_park_evalue {
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE,
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* 60-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV2, /* 120-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV6, /* 40-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1, /* 240-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV5, /* 48-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV3, /* 80-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV7, /* 34-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_NOM_PARK_RZQ_LAST
+};
+
+enum mv_ddr_rtt_wr_evalue {
+ MV_DDR_RTT_WR_DYN_ODT_OFF,
+ MV_DDR_RTT_WR_RZQ_DIV2, /* 120-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_WR_RZQ_DIV1, /* 240-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_WR_HIZ,
+ MV_DDR_RTT_WR_RZQ_DIV3, /* 80-Ohm; RZQ = 240-Ohm */
+ MV_DDR_RTT_WR_RZQ_LAST
+};
+
+enum mv_ddr_dic_evalue {
+ MV_DDR_DIC_RZQ_DIV7, /* 34-Ohm; RZQ = 240-Ohm */
+ MV_DDR_DIC_RZQ_DIV5, /* 48-Ohm; RZQ = 240-Ohm */
+ MV_DDR_DIC_RZQ_LAST
+};
+
+/* phy electrical configuration values */
+enum mv_ddr_ohm_evalue {
+ MV_DDR_OHM_20 = 20,/*relevant for Synopsys C/A Drive strength only*/
+ MV_DDR_OHM_30 = 30,
+ MV_DDR_OHM_40 = 40,/*relevant for Synopsys C/A Drive strength only*/
+ MV_DDR_OHM_48 = 48,
+ MV_DDR_OHM_60 = 60,
+ MV_DDR_OHM_80 = 80,
+ MV_DDR_OHM_120 = 120,
+ MV_DDR_OHM_240 = 240,
+ MV_DDR_OHM_LAST
+};
+
+/* mac electrical configuration values */
+enum mv_ddr_odt_cfg_evalue {
+ MV_DDR_ODT_CFG_NORMAL,
+ MV_DDR_ODT_CFG_ALWAYS_ON,
+ MV_DDR_ODT_CFG_LAST
+};
+
+enum mv_ddr_dev_width { /* sdram device width */
+ MV_DDR_DEV_WIDTH_4BIT,
+ MV_DDR_DEV_WIDTH_8BIT,
+ MV_DDR_DEV_WIDTH_16BIT,
+ MV_DDR_DEV_WIDTH_32BIT,
+ MV_DDR_DEV_WIDTH_LAST
+};
+
+enum mv_ddr_die_capacity { /* total sdram capacity per die, megabits */
+ MV_DDR_DIE_CAP_256MBIT,
+ MV_DDR_DIE_CAP_512MBIT = 0,
+ MV_DDR_DIE_CAP_1GBIT,
+ MV_DDR_DIE_CAP_2GBIT,
+ MV_DDR_DIE_CAP_4GBIT,
+ MV_DDR_DIE_CAP_8GBIT,
+ MV_DDR_DIE_CAP_16GBIT,
+ MV_DDR_DIE_CAP_32GBIT,
+ MV_DDR_DIE_CAP_12GBIT,
+ MV_DDR_DIE_CAP_24GBIT,
+ MV_DDR_DIE_CAP_LAST
+};
+
+enum mv_ddr_pkg_rank { /* number of package ranks per dimm */
+ MV_DDR_PKG_RANK_1,
+ MV_DDR_PKG_RANK_2,
+ MV_DDR_PKG_RANK_3,
+ MV_DDR_PKG_RANK_4,
+ MV_DDR_PKG_RANK_5,
+ MV_DDR_PKG_RANK_6,
+ MV_DDR_PKG_RANK_7,
+ MV_DDR_PKG_RANK_8,
+ MV_DDR_PKG_RANK_LAST
+};
+
+enum mv_ddr_pri_bus_width { /* number of primary bus width bits */
+ MV_DDR_PRI_BUS_WIDTH_8,
+ MV_DDR_PRI_BUS_WIDTH_16,
+ MV_DDR_PRI_BUS_WIDTH_32,
+ MV_DDR_PRI_BUS_WIDTH_64,
+ MV_DDR_PRI_BUS_WIDTH_LAST
+};
+
+enum mv_ddr_bus_width_ext { /* number of extension bus width bits */
+ MV_DDR_BUS_WIDTH_EXT_0,
+ MV_DDR_BUS_WIDTH_EXT_8,
+ MV_DDR_BUS_WIDTH_EXT_LAST
+};
+
+enum mv_ddr_die_count {
+ MV_DDR_DIE_CNT_1,
+ MV_DDR_DIE_CNT_2,
+ MV_DDR_DIE_CNT_3,
+ MV_DDR_DIE_CNT_4,
+ MV_DDR_DIE_CNT_5,
+ MV_DDR_DIE_CNT_6,
+ MV_DDR_DIE_CNT_7,
+ MV_DDR_DIE_CNT_8,
+ MV_DDR_DIE_CNT_LAST
+};
+
+#define IS_ACTIVE(mask, id) \
+ ((mask) & (1 << (id)))
+
+#define VALIDATE_ACTIVE(mask, id) \
+ { \
+ if (IS_ACTIVE(mask, id) == 0) \
+ continue; \
+ }
+
+#define IS_IF_ACTIVE(if_mask, if_id) \
+ ((if_mask) & (1 << (if_id)))
+
+#define VALIDATE_IF_ACTIVE(mask, id) \
+ { \
+ if (IS_IF_ACTIVE(mask, id) == 0) \
+ continue; \
+ }
+
+#define IS_BUS_ACTIVE(if_mask , if_id) \
+ (((if_mask) >> (if_id)) & 1)
+
+#define VALIDATE_BUS_ACTIVE(mask, id) \
+ { \
+ if (IS_BUS_ACTIVE(mask, id) == 0) \
+ continue; \
+ }
+
+#define DDR3_IS_ECC_PUP3_MODE(if_mask) \
+ (((if_mask) == BUS_MASK_16BIT_ECC_PUP3) ? 1 : 0)
+
+#define DDR3_IS_ECC_PUP4_MODE(if_mask) \
+ (((if_mask) == BUS_MASK_32BIT_ECC || \
+ (if_mask) == BUS_MASK_16BIT_ECC) ? 1 : 0)
+
+#define DDR3_IS_16BIT_DRAM_MODE(mask) \
+ (((mask) == BUS_MASK_16BIT || \
+ (mask) == BUS_MASK_16BIT_ECC || \
+ (mask) == BUS_MASK_16BIT_ECC_PUP3) ? 1 : 0)
+
+#define DDR3_IS_ECC_PUP8_MODE(if_mask) \
+ (((if_mask) == MV_DDR_32BIT_ECC_PUP8_BUS_MASK || \
+ (if_mask) == MV_DDR_64BIT_ECC_PUP8_BUS_MASK) ? 1 : 0)
+
+#define MV_DDR_IS_64BIT_DRAM_MODE(mask) \
+ ((((mask) & MV_DDR_64BIT_BUS_MASK) == MV_DDR_64BIT_BUS_MASK) || \
+ (((mask) & MV_DDR_64BIT_ECC_PUP8_BUS_MASK) == MV_DDR_64BIT_ECC_PUP8_BUS_MASK) ? 1 : 0)
+
+#define MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(mask, sphys) \
+ (((sphys) == 9) && \
+ (((mask) == BUS_MASK_32BIT) || \
+ ((mask) == MV_DDR_32BIT_ECC_PUP8_BUS_MASK)) ? 1 : 0)
+
+#define MV_DDR_IS_HALF_BUS_DRAM_MODE(mask, sphys) \
+ (MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(mask, sphys) || \
+ DDR3_IS_16BIT_DRAM_MODE(mask))
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void);
+unsigned int mv_ddr_cl_calc(unsigned int taa_min, unsigned int tclk);
+unsigned int mv_ddr_cwl_calc(unsigned int tclk);
+int mv_ddr_topology_map_update(void);
+unsigned short mv_ddr_bus_bit_mask_get(void);
+unsigned int mv_ddr_if_bus_width_get(void);
+unsigned int mv_ddr_cs_num_get(void);
+int mv_ddr_is_ecc_ena(void);
+int mv_ddr_ck_delay_get(void);
+unsigned long long mv_ddr_mem_sz_per_cs_get(void);
+unsigned long long mv_ddr_mem_sz_get(void);
+unsigned int mv_ddr_rtt_nom_get(void);
+unsigned int mv_ddr_rtt_park_get(void);
+unsigned int mv_ddr_rtt_wr_get(void);
+unsigned int mv_ddr_dic_get(void);
+
+#endif /* _MV_DDR_TOPOLOGY_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_training_db.h b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_training_db.h
new file mode 100644
index 000000000..838be4574
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/mv_ddr_training_db.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ */
+
+#ifndef _MV_DDR_TRAINING_DB_H
+#define _MV_DDR_TRAINING_DB_H
+
+#include "mv_ddr_topology.h"
+
+/* in ns */
+#define TREFI_LOW 7800
+#define TREFI_HIGH 3900
+
+enum mv_ddr_page_size {
+ MV_DDR_PAGE_SIZE_1K = 1,
+ MV_DDR_PAGE_SIZE_2K
+};
+
+struct mv_ddr_page_element {
+ /* 8-bit bus width page size */
+ enum mv_ddr_page_size page_size_8bit;
+ /* 16-bit bus width page size */
+ enum mv_ddr_page_size page_size_16bit;
+};
+
+/* cas latency value per frequency */
+struct mv_ddr_cl_val_per_freq {
+ unsigned int cl_val[MV_DDR_FREQ_LAST];
+};
+
+u32 mv_ddr_rfc_get(u32 mem);
+unsigned int *mv_ddr_freq_tbl_get(void);
+u32 mv_ddr_freq_get(enum mv_ddr_freq freq);
+u32 mv_ddr_page_size_get(enum mv_ddr_dev_width bus_width, enum mv_ddr_die_capacity mem_size);
+unsigned int mv_ddr_speed_bin_timing_get(enum mv_ddr_speed_bin index, enum mv_ddr_speed_bin_timing element);
+u32 mv_ddr_cl_val_get(u32 index, u32 freq);
+u32 mv_ddr_cwl_val_get(u32 index, u32 freq);
+
+#endif /* _MV_DDR_TRAINING_DB_H */
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/seq_exec.h b/roms/u-boot/drivers/ddr/marvell/a38x/seq_exec.h
new file mode 100644
index 000000000..fe0cb8f75
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/seq_exec.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _SEQ_EXEC_H
+#define _SEQ_EXEC_H
+
+#define NA 0xff
+#define DEFAULT_PARAM 0
+#define MV_BOARD_TCLK_ERROR 0xffffffff
+
+#define NO_DATA 0xffffffff
+#define MAX_DATA_ARRAY 5
+#define FIRST_CELL 0
+
+/* Operation types */
+enum mv_op {
+ WRITE_OP,
+ DELAY_OP,
+ POLL_OP,
+};
+
+/* Operation parameters */
+struct op_params {
+ u32 unit_base_reg;
+ u32 unit_offset;
+ u32 mask;
+ u32 data[MAX_DATA_ARRAY]; /* data array */
+ u8 wait_time; /* msec */
+ u16 num_of_loops; /* for polling only */
+};
+
+/*
+ * Sequence parameters. Each sequence contains:
+ * 1. Sequence id.
+ * 2. Sequence size (total amount of operations during the sequence)
+ * 3. a series of operations. operations can be write, poll or delay
+ * 4. index in the data array (the entry where the relevant data sits)
+ */
+struct cfg_seq {
+ struct op_params *op_params_ptr;
+ u8 cfg_seq_size;
+ u8 data_arr_idx;
+};
+
+extern struct cfg_seq serdes_seq_db[];
+
+/*
+ * A generic function type for executing an operation (write, poll or delay)
+ */
+typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params,
+ u32 data_arr_idx);
+
+/* Specific functions for executing each operation */
+int write_op_execute(u32 serdes_num, struct op_params *params,
+ u32 data_arr_idx);
+int delay_op_execute(u32 serdes_num, struct op_params *params,
+ u32 data_arr_idx);
+int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx);
+enum mv_op get_cfg_seq_op(struct op_params *params);
+int mv_seq_exec(u32 serdes_num, u32 seq_id);
+
+#endif /*_SEQ_EXEC_H*/
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/xor.c b/roms/u-boot/drivers/ddr/marvell/a38x/xor.c
new file mode 100644
index 000000000..7bc626829
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/xor.c
@@ -0,0 +1,464 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#include "ddr3_init.h"
+#include "mv_ddr_common.h"
+#include "xor_regs.h"
+
+/* defines */
+#ifdef MV_DEBUG
+#define DB(x) x
+#else
+#define DB(x)
+#endif
+
+static u32 ui_xor_regs_ctrl_backup;
+static u32 ui_xor_regs_base_backup[MAX_CS_NUM + 1];
+static u32 ui_xor_regs_mask_backup[MAX_CS_NUM + 1];
+
+void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, uint64_t cs_size, u32 base_delta)
+{
+ u32 reg, ui, cs_count;
+ uint64_t base, size_mask;
+
+ ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0));
+ for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
+ ui_xor_regs_base_backup[ui] =
+ reg_read(XOR_BASE_ADDR_REG(0, ui));
+ for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
+ ui_xor_regs_mask_backup[ui] =
+ reg_read(XOR_SIZE_MASK_REG(0, ui));
+
+ reg = 0;
+ for (ui = 0, cs_count = 0;
+ (cs_count < num_of_cs) && (ui < 8);
+ ui++, cs_count++) {
+ if (cs_ena & (1 << ui)) {
+ /* Enable Window x for each CS */
+ reg |= (0x1 << (ui));
+ /* Enable Window x for each CS */
+ reg |= (0x3 << ((ui * 2) + 16));
+ }
+ }
+
+ reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg);
+
+ cs_count = 0;
+ for (ui = 0, cs_count = 0;
+ (cs_count < num_of_cs) && (ui < 8);
+ ui++, cs_count++) {
+ if (cs_ena & (1 << ui)) {
+ /*
+ * window x - Base - 0x00000000,
+ * Attribute 0x0e - DRAM
+ */
+ base = cs_size * ui + base_delta;
+ /* fixed size 2GB for each CS */
+ size_mask = 0x7FFF0000;
+ switch (ui) {
+ case 0:
+ base |= 0xe00;
+ break;
+ case 1:
+ base |= 0xd00;
+ break;
+ case 2:
+ base |= 0xb00;
+ break;
+ case 3:
+ base |= 0x700;
+ break;
+ case 4: /* SRAM */
+ base = 0x40000000;
+ /* configure as shared transaction */
+ base |= 0x1F00;
+ size_mask = 0xF0000;
+ break;
+ }
+
+ reg_write(XOR_BASE_ADDR_REG(0, ui), (u32)base);
+ size_mask = (cs_size / _64K) - 1;
+ size_mask = (size_mask << XESMRX_SIZE_MASK_OFFS) & XESMRX_SIZE_MASK_MASK;
+ /* window x - Size */
+ reg_write(XOR_SIZE_MASK_REG(0, ui), (u32)size_mask);
+ }
+ }
+
+ mv_xor_hal_init(1);
+
+ return;
+}
+
+void mv_sys_xor_finish(void)
+{
+ u32 ui;
+
+ reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup);
+ for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
+ reg_write(XOR_BASE_ADDR_REG(0, ui),
+ ui_xor_regs_base_backup[ui]);
+ for (ui = 0; ui < MAX_CS_NUM + 1; ui++)
+ reg_write(XOR_SIZE_MASK_REG(0, ui),
+ ui_xor_regs_mask_backup[ui]);
+
+ reg_write(XOR_ADDR_OVRD_REG(0, 0), 0);
+}
+
+/*
+ * mv_xor_hal_init - Initialize XOR engine
+ *
+ * DESCRIPTION:
+ * This function initialize XOR unit.
+ * INPUT:
+ * None.
+ *
+ * OUTPUT:
+ * None.
+ *
+ * RETURN:
+ * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ */
+void mv_xor_hal_init(u32 xor_chan_num)
+{
+ u32 i;
+
+ /* Abort any XOR activity & set default configuration */
+ for (i = 0; i < xor_chan_num; i++) {
+ mv_xor_command_set(i, MV_STOP);
+ mv_xor_ctrl_set(i, (1 << XEXCR_REG_ACC_PROTECT_OFFS) |
+ (4 << XEXCR_DST_BURST_LIMIT_OFFS) |
+ (4 << XEXCR_SRC_BURST_LIMIT_OFFS));
+ }
+}
+
+/*
+ * mv_xor_ctrl_set - Set XOR channel control registers
+ *
+ * DESCRIPTION:
+ *
+ * INPUT:
+ *
+ * OUTPUT:
+ * None.
+ *
+ * RETURN:
+ * MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+ * NOTE:
+ * This function does not modify the Operation_mode field of control register.
+ */
+int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl)
+{
+ u32 old_value;
+
+ /* update the XOR Engine [0..1] Configuration Registers (XEx_c_r) */
+ old_value = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan))) &
+ XEXCR_OPERATION_MODE_MASK;
+ xor_ctrl &= ~XEXCR_OPERATION_MODE_MASK;
+ xor_ctrl |= old_value;
+ reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), xor_ctrl);
+
+ return MV_OK;
+}
+
+int mv_xor_mem_init(u32 chan, u32 start_ptr, unsigned long long block_size,
+ u32 init_val_high, u32 init_val_low)
+{
+ u32 temp;
+
+ if (block_size == _4G)
+ block_size -= 1;
+
+ /* Parameter checking */
+ if (chan >= MV_XOR_MAX_CHAN)
+ return MV_BAD_PARAM;
+
+ if (MV_ACTIVE == mv_xor_state_get(chan))
+ return MV_BUSY;
+
+ if ((block_size < XEXBSR_BLOCK_SIZE_MIN_VALUE) ||
+ (block_size > XEXBSR_BLOCK_SIZE_MAX_VALUE))
+ return MV_BAD_PARAM;
+
+ /* set the operation mode to Memory Init */
+ temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+ temp &= ~XEXCR_OPERATION_MODE_MASK;
+ temp |= XEXCR_OPERATION_MODE_MEM_INIT;
+ reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+
+ /*
+ * update the start_ptr field in XOR Engine [0..1] Destination Pointer
+ * Register
+ */
+ reg_write(XOR_DST_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), start_ptr);
+
+ /*
+ * update the Block_size field in the XOR Engine[0..1] Block Size
+ * Registers
+ */
+ reg_write(XOR_BLOCK_SIZE_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+ block_size);
+
+ /*
+ * update the field Init_val_l in the XOR Engine Initial Value Register
+ * Low (XEIVRL)
+ */
+ reg_write(XOR_INIT_VAL_LOW_REG(XOR_UNIT(chan)), init_val_low);
+
+ /*
+ * update the field Init_val_h in the XOR Engine Initial Value Register
+ * High (XEIVRH)
+ */
+ reg_write(XOR_INIT_VAL_HIGH_REG(XOR_UNIT(chan)), init_val_high);
+
+ /* start transfer */
+ reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+ XEXACTR_XESTART_MASK);
+
+ return MV_OK;
+}
+
+/*
+ * mv_xor_state_get - Get XOR channel state.
+ *
+ * DESCRIPTION:
+ * XOR channel activity state can be active, idle, paused.
+ * This function retrunes the channel activity state.
+ *
+ * INPUT:
+ * chan - the channel number
+ *
+ * OUTPUT:
+ * None.
+ *
+ * RETURN:
+ * XOR_CHANNEL_IDLE - If the engine is idle.
+ * XOR_CHANNEL_ACTIVE - If the engine is busy.
+ * XOR_CHANNEL_PAUSED - If the engine is paused.
+ * MV_UNDEFINED_STATE - If the engine state is undefind or there is no
+ * such engine
+ */
+enum mv_state mv_xor_state_get(u32 chan)
+{
+ u32 state;
+
+ /* Parameter checking */
+ if (chan >= MV_XOR_MAX_CHAN) {
+ DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+ return MV_UNDEFINED_STATE;
+ }
+
+ /* read the current state */
+ state = reg_read(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+ state &= XEXACTR_XESTATUS_MASK;
+
+ /* return the state */
+ switch (state) {
+ case XEXACTR_XESTATUS_IDLE:
+ return MV_IDLE;
+ case XEXACTR_XESTATUS_ACTIVE:
+ return MV_ACTIVE;
+ case XEXACTR_XESTATUS_PAUSED:
+ return MV_PAUSED;
+ }
+
+ return MV_UNDEFINED_STATE;
+}
+
+/*
+ * mv_xor_command_set - Set command of XOR channel
+ *
+ * DESCRIPTION:
+ * XOR channel can be started, idle, paused and restarted.
+ * Paused can be set only if channel is active.
+ * Start can be set only if channel is idle or paused.
+ * Restart can be set only if channel is paused.
+ * Stop can be set only if channel is active.
+ *
+ * INPUT:
+ * chan - The channel number
+ * command - The command type (start, stop, restart, pause)
+ *
+ * OUTPUT:
+ * None.
+ *
+ * RETURN:
+ * MV_OK on success , MV_BAD_PARAM on erroneous parameter, MV_ERROR on
+ * undefind XOR engine mode
+ */
+int mv_xor_command_set(u32 chan, enum mv_command command)
+{
+ enum mv_state state;
+
+ /* Parameter checking */
+ if (chan >= MV_XOR_MAX_CHAN) {
+ DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+ return MV_BAD_PARAM;
+ }
+
+ /* get the current state */
+ state = mv_xor_state_get(chan);
+
+ if ((command == MV_START) && (state == MV_IDLE)) {
+ /* command is start and current state is idle */
+ reg_bit_set(XOR_ACTIVATION_REG
+ (XOR_UNIT(chan), XOR_CHAN(chan)),
+ XEXACTR_XESTART_MASK);
+ return MV_OK;
+ } else if ((command == MV_STOP) && (state == MV_ACTIVE)) {
+ /* command is stop and current state is active */
+ reg_bit_set(XOR_ACTIVATION_REG
+ (XOR_UNIT(chan), XOR_CHAN(chan)),
+ XEXACTR_XESTOP_MASK);
+ return MV_OK;
+ } else if (((enum mv_state)command == MV_PAUSED) &&
+ (state == MV_ACTIVE)) {
+ /* command is paused and current state is active */
+ reg_bit_set(XOR_ACTIVATION_REG
+ (XOR_UNIT(chan), XOR_CHAN(chan)),
+ XEXACTR_XEPAUSE_MASK);
+ return MV_OK;
+ } else if ((command == MV_RESTART) && (state == MV_PAUSED)) {
+ /* command is restart and current state is paused */
+ reg_bit_set(XOR_ACTIVATION_REG
+ (XOR_UNIT(chan), XOR_CHAN(chan)),
+ XEXACTR_XERESTART_MASK);
+ return MV_OK;
+ } else if ((command == MV_STOP) && (state == MV_IDLE)) {
+ /* command is stop and current state is active */
+ return MV_OK;
+ }
+
+ /* illegal command */
+ DB(printf("%s: ERR. Illegal command\n", __func__));
+
+ return MV_BAD_PARAM;
+}
+
+void ddr3_new_tip_ecc_scrub(void)
+{
+ u32 cs_c, max_cs;
+ u32 cs_ena = 0;
+ uint64_t total_mem_size, cs_mem_size_mb = 0, cs_mem_size = 0;
+
+ printf("DDR Training Sequence - Start scrubbing\n");
+ max_cs = mv_ddr_cs_num_get();
+ for (cs_c = 0; cs_c < max_cs; cs_c++)
+ cs_ena |= 1 << cs_c;
+
+ /* all chip-selects are of same size */
+ ddr3_calc_mem_cs_size(0, &cs_mem_size_mb);
+ cs_mem_size = cs_mem_size_mb * _1M;
+ mv_sys_xor_init(max_cs, cs_ena, cs_mem_size, 0);
+ total_mem_size = max_cs * cs_mem_size;
+ mv_xor_mem_init(0, 0, total_mem_size, 0xdeadbeef, 0xdeadbeef);
+ /* wait for previous transfer completion */
+ while (mv_xor_state_get(0) != MV_IDLE)
+ ;
+ /* Return XOR State */
+ mv_sys_xor_finish();
+
+ printf("DDR3 Training Sequence - End scrubbing\n");
+}
+
+/*
+* mv_xor_transfer - Transfer data from source to destination in one of
+* three modes: XOR, CRC32 or DMA
+*
+* DESCRIPTION:
+* This function initiates XOR channel, according to function parameters,
+* in order to perform XOR, CRC32 or DMA transaction.
+* To gain maximum performance the user is asked to keep the following
+* restrictions:
+* 1) Selected engine is available (not busy).
+* 2) This module does not take into consideration CPU MMU issues.
+* In order for the XOR engine to access the appropriate source
+* and destination, address parameters must be given in system
+* physical mode.
+* 3) This API does not take care of cache coherency issues. The source,
+* destination and, in case of chain, the descriptor list are assumed
+* to be cache coherent.
+* 4) Parameters validity.
+*
+* INPUT:
+* chan - XOR channel number.
+* type - One of three: XOR, CRC32 and DMA operations.
+* xor_chain_ptr - address of chain pointer
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise.
+*
+*******************************************************************************/
+int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr)
+{
+ u32 temp;
+
+ /* Parameter checking */
+ if (chan >= MV_XOR_MAX_CHAN) {
+ DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan));
+ return MV_BAD_PARAM;
+ }
+ if (mv_xor_state_get(chan) == MV_ACTIVE) {
+ DB(printf("%s: ERR. Channel is already active\n", __func__));
+ return MV_BUSY;
+ }
+ if (xor_chain_ptr == 0x0) {
+ DB(printf("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__));
+ return MV_BAD_PARAM;
+ }
+
+ /* read configuration register and mask the operation mode field */
+ temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)));
+ temp &= ~XEXCR_OPERATION_MODE_MASK;
+
+ switch (type) {
+ case MV_XOR:
+ if ((xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK) != 0) {
+ DB(printf("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n",
+ __func__));
+ return MV_BAD_PARAM;
+ }
+ /* set the operation mode to XOR */
+ temp |= XEXCR_OPERATION_MODE_XOR;
+ break;
+ case MV_DMA:
+ if ((xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK) != 0) {
+ DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+ __func__));
+ return MV_BAD_PARAM;
+ }
+ /* set the operation mode to DMA */
+ temp |= XEXCR_OPERATION_MODE_DMA;
+ break;
+ case MV_CRC32:
+ if ((xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK) != 0) {
+ DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n",
+ __func__));
+ return MV_BAD_PARAM;
+ }
+ /* set the operation mode to CRC32 */
+ temp |= XEXCR_OPERATION_MODE_CRC;
+ break;
+ default:
+ return MV_BAD_PARAM;
+ }
+
+ /* write the operation mode to the register */
+ reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp);
+ /*
+ * update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor
+ * Pointer Register (XExNDPR)
+ */
+ reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+ xor_chain_ptr);
+
+ /* start transfer */
+ reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)),
+ XEXACTR_XESTART_MASK);
+
+ return MV_OK;
+}
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/xor.h b/roms/u-boot/drivers/ddr/marvell/a38x/xor.h
new file mode 100644
index 000000000..1e0265036
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/xor.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _XOR_H
+#define _XOR_H
+
+#define SRAM_BASE 0x40000000
+
+#define MV_XOR_MAX_UNIT 2 /* XOR unit == XOR engine */
+#define MV_XOR_MAX_CHAN 4 /* total channels for all units */
+#define MV_XOR_MAX_CHAN_PER_UNIT 2 /* channels for units */
+
+#define MV_IS_POWER_OF_2(num) (((num) != 0) && (((num) & ((num) - 1)) == 0))
+
+/*
+ * This structure describes address space window. Window base can be
+ * 64 bit, window size up to 4GB
+ */
+struct addr_win {
+ u32 base_low; /* 32bit base low */
+ u32 base_high; /* 32bit base high */
+ u32 size; /* 32bit size */
+};
+
+/* This structure describes SoC units address decode window */
+struct unit_win_info {
+ struct addr_win addr_win; /* An address window */
+ int enable; /* Address decode window is enabled/disabled */
+ u8 attrib; /* chip select attributes */
+ u8 target_id; /* Target Id of this MV_TARGET */
+};
+
+/*
+ * This enumerator describes the type of functionality the XOR channel
+ * can have while using the same data structures.
+ */
+enum xor_type {
+ MV_XOR, /* XOR channel functions as XOR accelerator */
+ MV_DMA, /* XOR channel functions as IDMA channel */
+ MV_CRC32 /* XOR channel functions as CRC 32 calculator */
+};
+
+enum mv_state {
+ MV_IDLE,
+ MV_ACTIVE,
+ MV_PAUSED,
+ MV_UNDEFINED_STATE
+};
+
+/*
+ * This enumerator describes the set of commands that can be applied on
+ * an engine (e.g. IDMA, XOR). Appling a comman depends on the current
+ * status (see MV_STATE enumerator)
+ *
+ * Start can be applied only when status is IDLE
+ * Stop can be applied only when status is IDLE, ACTIVE or PAUSED
+ * Pause can be applied only when status is ACTIVE
+ * Restart can be applied only when status is PAUSED
+ */
+enum mv_command {
+ MV_START, /* Start */
+ MV_STOP, /* Stop */
+ MV_PAUSE, /* Pause */
+ MV_RESTART /* Restart */
+};
+
+enum xor_override_target {
+ SRC_ADDR0, /* Source Address #0 Control */
+ SRC_ADDR1, /* Source Address #1 Control */
+ SRC_ADDR2, /* Source Address #2 Control */
+ SRC_ADDR3, /* Source Address #3 Control */
+ SRC_ADDR4, /* Source Address #4 Control */
+ SRC_ADDR5, /* Source Address #5 Control */
+ SRC_ADDR6, /* Source Address #6 Control */
+ SRC_ADDR7, /* Source Address #7 Control */
+ XOR_DST_ADDR, /* Destination Address Control */
+ XOR_NEXT_DESC /* Next Descriptor Address Control */
+};
+
+enum mv_state mv_xor_state_get(u32 chan);
+void mv_xor_hal_init(u32 xor_chan_num);
+int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
+int mv_xor_command_set(u32 chan, enum mv_command command);
+int mv_xor_override_set(u32 chan, enum xor_override_target target, u32 win_num,
+ int enable);
+int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr);
+
+#endif
diff --git a/roms/u-boot/drivers/ddr/marvell/a38x/xor_regs.h b/roms/u-boot/drivers/ddr/marvell/a38x/xor_regs.h
new file mode 100644
index 000000000..fdfc0f234
--- /dev/null
+++ b/roms/u-boot/drivers/ddr/marvell/a38x/xor_regs.h
@@ -0,0 +1,235 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _XOR_REGS_h
+#define _XOR_REGS_h
+
+/*
+ * For controllers that have two XOR units, then chans 2 & 3 will be
+ * mapped to channels 0 & 1 of unit 1
+ */
+#define XOR_UNIT(chan) ((chan) >> 1)
+#define XOR_CHAN(chan) ((chan) & 1)
+
+#define MV_XOR_REGS_OFFSET(unit) (0x60900)
+#define MV_XOR_REGS_BASE(unit) (MV_XOR_REGS_OFFSET(unit))
+
+/* XOR Engine Control Register Map */
+#define XOR_CHANNEL_ARBITER_REG(unit) (MV_XOR_REGS_BASE(unit))
+#define XOR_CONFIG_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x10 + ((chan) * 4)))
+#define XOR_ACTIVATION_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x20 + ((chan) * 4)))
+
+/* XOR Engine Interrupt Register Map */
+#define XOR_CAUSE_REG(unit) (MV_XOR_REGS_BASE(unit)+(0x30))
+#define XOR_MASK_REG(unit) (MV_XOR_REGS_BASE(unit)+(0x40))
+#define XOR_ERROR_CAUSE_REG(unit) (MV_XOR_REGS_BASE(unit)+(0x50))
+#define XOR_ERROR_ADDR_REG(unit) (MV_XOR_REGS_BASE(unit)+(0x60))
+
+/* XOR Engine Descriptor Register Map */
+#define XOR_NEXT_DESC_PTR_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x200 + ((chan) * 4)))
+#define XOR_CURR_DESC_PTR_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x210 + ((chan) * 4)))
+#define XOR_BYTE_COUNT_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x220 + ((chan) * 4)))
+
+/* XOR Engine ECC/Mem_init Register Map */
+#define XOR_DST_PTR_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x2b0 + ((chan) * 4)))
+#define XOR_BLOCK_SIZE_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x2c0 + ((chan) * 4)))
+#define XOR_TIMER_MODE_CTRL_REG(unit) (MV_XOR_REGS_BASE(unit) + (0x2d0))
+#define XOR_TIMER_MODE_INIT_VAL_REG(unit) (MV_XOR_REGS_BASE(unit) + (0x2d4))
+#define XOR_TIMER_MODE_CURR_VAL_REG(unit) (MV_XOR_REGS_BASE(unit) + (0x2d8))
+#define XOR_INIT_VAL_LOW_REG(unit) (MV_XOR_REGS_BASE(unit) + (0x2e0))
+#define XOR_INIT_VAL_HIGH_REG(unit) (MV_XOR_REGS_BASE(unit) + (0x2e4))
+
+/* XOR Engine Debug Register Map */
+#define XOR_DEBUG_REG(unit) (MV_XOR_REGS_BASE(unit) + (0x70))
+
+/* XOR register fileds */
+
+/* XOR Engine Channel Arbiter Register */
+#define XECAR_SLICE_OFFS(slice_num) (slice_num)
+#define XECAR_SLICE_MASK(slice_num) (1 << (XECAR_SLICE_OFFS(slice_num)))
+
+/* XOR Engine [0..1] Configuration Registers */
+#define XEXCR_OPERATION_MODE_OFFS (0)
+#define XEXCR_OPERATION_MODE_MASK (7 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_XOR (0 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_CRC (1 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_DMA (2 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_ECC (3 << XEXCR_OPERATION_MODE_OFFS)
+#define XEXCR_OPERATION_MODE_MEM_INIT (4 << XEXCR_OPERATION_MODE_OFFS)
+
+#define XEXCR_SRC_BURST_LIMIT_OFFS (4)
+#define XEXCR_SRC_BURST_LIMIT_MASK (7 << XEXCR_SRC_BURST_LIMIT_OFFS)
+#define XEXCR_DST_BURST_LIMIT_OFFS (8)
+#define XEXCR_DST_BURST_LIMIT_MASK (7 << XEXCR_DST_BURST_LIMIT_OFFS)
+#define XEXCR_DRD_RES_SWP_OFFS (12)
+#define XEXCR_DRD_RES_SWP_MASK (1 << XEXCR_DRD_RES_SWP_OFFS)
+#define XEXCR_DWR_REQ_SWP_OFFS (13)
+#define XEXCR_DWR_REQ_SWP_MASK (1 << XEXCR_DWR_REQ_SWP_OFFS)
+#define XEXCR_DES_SWP_OFFS (14)
+#define XEXCR_DES_SWP_MASK (1 << XEXCR_DES_SWP_OFFS)
+#define XEXCR_REG_ACC_PROTECT_OFFS (15)
+#define XEXCR_REG_ACC_PROTECT_MASK (1 << XEXCR_REG_ACC_PROTECT_OFFS)
+
+/* XOR Engine [0..1] Activation Registers */
+#define XEXACTR_XESTART_OFFS (0)
+#define XEXACTR_XESTART_MASK (1 << XEXACTR_XESTART_OFFS)
+#define XEXACTR_XESTOP_OFFS (1)
+#define XEXACTR_XESTOP_MASK (1 << XEXACTR_XESTOP_OFFS)
+#define XEXACTR_XEPAUSE_OFFS (2)
+#define XEXACTR_XEPAUSE_MASK (1 << XEXACTR_XEPAUSE_OFFS)
+#define XEXACTR_XERESTART_OFFS (3)
+#define XEXACTR_XERESTART_MASK (1 << XEXACTR_XERESTART_OFFS)
+#define XEXACTR_XESTATUS_OFFS (4)
+#define XEXACTR_XESTATUS_MASK (3 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_IDLE (0 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_ACTIVE (1 << XEXACTR_XESTATUS_OFFS)
+#define XEXACTR_XESTATUS_PAUSED (2 << XEXACTR_XESTATUS_OFFS)
+
+/* XOR Engine Interrupt Cause Register (XEICR) */
+#define XEICR_CHAN_OFFS 16
+#define XEICR_CAUSE_OFFS(chan) (chan * XEICR_CHAN_OFFS)
+#define XEICR_CAUSE_MASK(chan, cause) (1 << (cause + XEICR_CAUSE_OFFS(chan)))
+#define XEICR_COMP_MASK_ALL 0x000f000f
+#define XEICR_COMP_MASK(chan) (0x000f << XEICR_CAUSE_OFFS(chan))
+#define XEICR_ERR_MASK 0x03800380
+
+/* XOR Engine Error Cause Register (XEECR) */
+#define XEECR_ERR_TYPE_OFFS 0
+#define XEECR_ERR_TYPE_MASK (0x1f << XEECR_ERR_TYPE_OFFS)
+
+/* XOR Engine Error Address Register (XEEAR) */
+#define XEEAR_ERR_ADDR_OFFS (0)
+#define XEEAR_ERR_ADDR_MASK (0xffffffff << XEEAR_ERR_ADDR_OFFS)
+
+/* XOR Engine [0..1] Next Descriptor Pointer Register */
+#define XEXNDPR_NEXT_DESC_PTR_OFFS (0)
+#define XEXNDPR_NEXT_DESC_PTR_MASK (0xffffffff << \
+ XEXNDPR_NEXT_DESC_PTR_OFFS)
+
+/* XOR Engine [0..1] Current Descriptor Pointer Register */
+#define XEXCDPR_CURRENT_DESC_PTR_OFFS (0)
+#define XEXCDPR_CURRENT_DESC_PTR_MASK (0xffffffff << \
+ XEXCDPR_CURRENT_DESC_PTR_OFFS)
+
+/* XOR Engine [0..1] Byte Count Register */
+#define XEXBCR_BYTE_CNT_OFFS (0)
+#define XEXBCR_BYTE_CNT_MASK (0xffffffff << XEXBCR_BYTE_CNT_OFFS)
+
+/* XOR Engine [0..1] Destination Pointer Register */
+#define XEXDPR_DST_PTR_OFFS (0)
+#define XEXDPR_DST_PTR_MASK (0xffffffff << XEXDPR_DST_PTR_OFFS)
+#define XEXDPR_DST_PTR_XOR_MASK (0x3f)
+#define XEXDPR_DST_PTR_DMA_MASK (0x1f)
+#define XEXDPR_DST_PTR_CRC_MASK (0x1f)
+
+/* XOR Engine[0..1] Block Size Registers */
+#define XEXBSR_BLOCK_SIZE_OFFS (0)
+#define XEXBSR_BLOCK_SIZE_MASK (0xffffffff << XEXBSR_BLOCK_SIZE_OFFS)
+#define XEXBSR_BLOCK_SIZE_MIN_VALUE (128)
+#define XEXBSR_BLOCK_SIZE_MAX_VALUE (0xffffffff)
+
+/* XOR Engine Timer Mode Control Register (XETMCR) */
+#define XETMCR_TIMER_EN_OFFS (0)
+#define XETMCR_TIMER_EN_MASK (1 << XETMCR_TIMER_EN_OFFS)
+#define XETMCR_TIMER_EN_ENABLE (1 << XETMCR_TIMER_EN_OFFS)
+#define XETMCR_TIMER_EN_DISABLE (0 << XETMCR_TIMER_EN_OFFS)
+#define XETMCR_SECTION_SIZE_CTRL_OFFS (8)
+#define XETMCR_SECTION_SIZE_CTRL_MASK (0x1f << XETMCR_SECTION_SIZE_CTRL_OFFS)
+#define XETMCR_SECTION_SIZE_MIN_VALUE (7)
+#define XETMCR_SECTION_SIZE_MAX_VALUE (31)
+
+/* XOR Engine Timer Mode Initial Value Register (XETMIVR) */
+#define XETMIVR_TIMER_INIT_VAL_OFFS (0)
+#define XETMIVR_TIMER_INIT_VAL_MASK (0xffffffff << \
+ XETMIVR_TIMER_INIT_VAL_OFFS)
+
+/* XOR Engine Timer Mode Current Value Register (XETMCVR) */
+#define XETMCVR_TIMER_CRNT_VAL_OFFS (0)
+#define XETMCVR_TIMER_CRNT_VAL_MASK (0xffffffff << \
+ XETMCVR_TIMER_CRNT_VAL_OFFS)
+
+/* XOR Engine Initial Value Register Low (XEIVRL) */
+#define XEIVRL_INIT_VAL_L_OFFS (0)
+#define XEIVRL_INIT_VAL_L_MASK (0xffffffff << XEIVRL_INIT_VAL_L_OFFS)
+
+/* XOR Engine Initial Value Register High (XEIVRH) */
+#define XEIVRH_INIT_VAL_H_OFFS (0)
+#define XEIVRH_INIT_VAL_H_MASK (0xffffffff << XEIVRH_INIT_VAL_H_OFFS)
+
+/* XOR Engine Debug Register (XEDBR) */
+#define XEDBR_PARITY_ERR_INSR_OFFS (0)
+#define XEDBR_PARITY_ERR_INSR_MASK (1 << XEDBR_PARITY_ERR_INSR_OFFS)
+#define XEDBR_XBAR_ERR_INSR_OFFS (1)
+#define XEDBR_XBAR_ERR_INSR_MASK (1 << XEDBR_XBAR_ERR_INSR_OFFS)
+
+/* XOR Engine address decode registers. */
+/* Maximum address decode windows */
+#define XOR_MAX_ADDR_DEC_WIN 8
+/* Maximum address arbiter windows */
+#define XOR_MAX_REMAP_WIN 4
+
+/* XOR Engine Address Decoding Register Map */
+#define XOR_WINDOW_CTRL_REG(unit, chan) (MV_XOR_REGS_BASE(unit) + \
+ (0x240 + ((chan) * 4)))
+#define XOR_BASE_ADDR_REG(unit, win_num) (MV_XOR_REGS_BASE(unit) + \
+ (0x250 + ((win_num) * 4)))
+#define XOR_SIZE_MASK_REG(unit, win_num) (MV_XOR_REGS_BASE(unit) + \
+ (0x270 + ((win_num) * 4)))
+#define XOR_HIGH_ADDR_REMAP_REG(unit, win_num) (MV_XOR_REGS_BASE(unit) + \
+ (0x290 + ((win_num) * 4)))
+#define XOR_ADDR_OVRD_REG(unit, win_num) (MV_XOR_REGS_BASE(unit) + \
+ (0x2a0 + ((win_num) * 4)))
+
+/* XOR Engine [0..1] Window Control Registers */
+#define XEXWCR_WIN_EN_OFFS(win_num) (win_num)
+#define XEXWCR_WIN_EN_MASK(win_num) (1 << (XEXWCR_WIN_EN_OFFS(win_num)))
+#define XEXWCR_WIN_EN_ENABLE(win_num) (1 << (XEXWCR_WIN_EN_OFFS(win_num)))
+#define XEXWCR_WIN_EN_DISABLE(win_num) (0 << (XEXWCR_WIN_EN_OFFS(win_num)))
+
+#define XEXWCR_WIN_ACC_OFFS(win_num) ((2 * win_num) + 16)
+#define XEXWCR_WIN_ACC_MASK(win_num) (3 << (XEXWCR_WIN_ACC_OFFS(win_num)))
+#define XEXWCR_WIN_ACC_NO_ACC(win_num) (0 << (XEXWCR_WIN_ACC_OFFS(win_num)))
+#define XEXWCR_WIN_ACC_RO(win_num) (1 << (XEXWCR_WIN_ACC_OFFS(win_num)))
+#define XEXWCR_WIN_ACC_RW(win_num) (3 << (XEXWCR_WIN_ACC_OFFS(win_num)))
+
+/* XOR Engine Base Address Registers (XEBARx) */
+#define XEBARX_TARGET_OFFS (0)
+#define XEBARX_TARGET_MASK (0xf << XEBARX_TARGET_OFFS)
+#define XEBARX_ATTR_OFFS (8)
+#define XEBARX_ATTR_MASK (0xff << XEBARX_ATTR_OFFS)
+#define XEBARX_BASE_OFFS (16)
+#define XEBARX_BASE_MASK (0xffff << XEBARX_BASE_OFFS)
+
+/* XOR Engine Size Mask Registers (XESMRx) */
+#define XESMRX_SIZE_MASK_OFFS (16)
+#define XESMRX_SIZE_MASK_MASK (0xffff << XESMRX_SIZE_MASK_OFFS)
+#define XOR_WIN_SIZE_ALIGN _64K
+
+/* XOR Engine High Address Remap Register (XEHARRx1) */
+#define XEHARRX_REMAP_OFFS (0)
+#define XEHARRX_REMAP_MASK (0xffffffff << XEHARRX_REMAP_OFFS)
+
+#define XOR_OVERRIDE_CTRL_REG(chan) (MV_XOR_REGS_BASE(XOR_UNIT(chan)) + \
+ (0x2a0 + ((XOR_CHAN(chan)) * 4)))
+
+/* XOR Engine [0..1] Address Override Control Register */
+#define XEXAOCR_OVR_EN_OFFS(target) (3 * target)
+#define XEXAOCR_OVR_EN_MASK(target) (1 << (XEXAOCR_OVR_EN_OFFS(target)))
+#define XEXAOCR_OVR_PTR_OFFS(target) ((3 * target) + 1)
+#define XEXAOCR_OVR_PTR_MASK(target) (3 << (XEXAOCR_OVR_PTR_OFFS(target)))
+#define XEXAOCR_OVR_BAR(win_num, target) (win_num << \
+ (XEXAOCR_OVR_PTR_OFFS(target)))
+
+/* Maximum address override windows */
+#define XOR_MAX_OVERRIDE_WIN 4
+
+#endif /* _XOR_REGS_h */